Skip to content
This repository has been archived by the owner on Sep 8, 2021. It is now read-only.

Make cover art source configurable #1774

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.airsonic.player.command;

import org.airsonic.player.controller.GeneralSettingsController;
import org.airsonic.player.domain.CoverArtSource;
import org.airsonic.player.domain.Theme;

/**
Expand All @@ -33,6 +34,7 @@ public class GeneralSettingsCommand {
private String musicFileTypes;
private String videoFileTypes;
private String coverArtFileTypes;
private CoverArtSource coverArtSource;
private String index;
private String ignoredArticles;
private String shortcuts;
Expand Down Expand Up @@ -79,6 +81,14 @@ public void setCoverArtFileTypes(String coverArtFileTypes) {
this.coverArtFileTypes = coverArtFileTypes;
}

public CoverArtSource getCoverArtSource() {
return coverArtSource;
}

public void setCoverArtSource(CoverArtSource coverArtSource) {
this.coverArtSource = coverArtSource;
}

public String getIndex() {
return index;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class MusicFolderSettingsCommand {
private String interval;
private String hour;
private boolean scanning;
private boolean fullScanOnce;
private boolean fastCache;
private boolean organizeByFolderStructure;
private List<MusicFolderInfo> musicFolders;
Expand Down Expand Up @@ -68,6 +69,14 @@ public void setScanning(boolean scanning) {
this.scanning = scanning;
}

public boolean isFullScanOnce() {
return fullScanOnce;
}

public void setFullScanOnce(boolean fullScanOnce) {
this.fullScanOnce = fullScanOnce;
}

public boolean isFastCache() {
return fastCache;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ protected String displayForm() {
protected void formBackingObject(Model model) {
GeneralSettingsCommand command = new GeneralSettingsCommand();
command.setCoverArtFileTypes(settingsService.getCoverArtFileTypes());
command.setCoverArtSource(settingsService.getCoverArtSource());
command.setIgnoredArticles(settingsService.getIgnoredArticles());
command.setShortcuts(settingsService.getShortcuts());
command.setIndex(settingsService.getIndexString());
Expand Down Expand Up @@ -110,13 +111,18 @@ protected String doSubmitAction(@ModelAttribute("command") GeneralSettingsComman
|| !settingsService.getThemeId().equals(theme.getId())
|| !settingsService.getLocale().equals(locale));

if (settingsService.getCoverArtSource() != command.getCoverArtSource()) {
settingsService.setFullScanOnce(true);
}

settingsService.setIndexString(command.getIndex());
settingsService.setIgnoredArticles(command.getIgnoredArticles());
settingsService.setShortcuts(command.getShortcuts());
settingsService.setPlaylistFolder(command.getPlaylistFolder());
settingsService.setMusicFileTypes(command.getMusicFileTypes());
settingsService.setVideoFileTypes(command.getVideoFileTypes());
settingsService.setCoverArtFileTypes(command.getCoverArtFileTypes());
settingsService.setCoverArtSource(command.getCoverArtSource());
settingsService.setSortAlbumsByYear(command.isSortAlbumsByYear());
settingsService.setGettingStartedEnabled(command.isGettingStartedEnabled());
settingsService.setWelcomeTitle(command.getWelcomeTitle());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ protected void formBackingObject(@RequestParam(value = "scanNow",required = fals
command.setInterval(String.valueOf(settingsService.getIndexCreationInterval()));
command.setHour(String.valueOf(settingsService.getIndexCreationHour()));
command.setFastCache(settingsService.isFastCacheEnabled());
command.setFullScanOnce(settingsService.isFullScanOnce());
command.setOrganizeByFolderStructure(settingsService.isOrganizeByFolderStructure());
command.setScanning(mediaScannerService.isScanning());
command.setMusicFolders(wrap(settingsService.getAllMusicFolders(true, true)));
Expand Down Expand Up @@ -164,6 +165,7 @@ protected String onSubmit(@ModelAttribute("command") MusicFolderSettingsCommand
settingsService.setIndexCreationInterval(Integer.parseInt(command.getInterval()));
settingsService.setIndexCreationHour(Integer.parseInt(command.getHour()));
settingsService.setFastCacheEnabled(command.isFastCache());
settingsService.setFullScanOnce(command.isFullScanOnce());
settingsService.setOrganizeByFolderStructure(command.isOrganizeByFolderStructure());
settingsService.setExcludePatternString(command.getExcludePatternString());
settingsService.setIgnoreSymLinks(command.getIgnoreSymLinks());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.airsonic.player.domain;

/**
* Enumeration of cover art source. Each value represents a method of
* how to handle scanning the cover art and which kind of cover art
* should be prefered
*
* @author Faeb35
*/
public enum CoverArtSource {
FILETAG,
TAGFILE,
FILE,
TAG
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public MediaFile getParentOf(MediaFile mediaFile) {

private MediaFile checkLastModified(MediaFile mediaFile, boolean useFastCache) {
if (useFastCache || (mediaFile.getVersion() >= MediaFileDao.VERSION
&& !settingsService.isIgnoreFileTimestamps()
&& !settingsService.isFullScanOnce()
&& mediaFile.getChanged().getTime() >= FileUtil.lastModified(mediaFile.getFile()))) {
LOG.debug("Detected unmodified file (id {}, path {})", mediaFile.getId(), mediaFile.getPath());
return mediaFile;
Expand Down Expand Up @@ -613,15 +613,43 @@ public File getCoverArt(MediaFile mediaFile) {
* Finds a cover art image for the given directory, by looking for it on the disk.
*/
private File findCoverArt(File[] candidates) {
File candidate = null;
CoverArtSource coverArtSource = settingsService.getCoverArtSource();
switch (coverArtSource) {
case TAGFILE:
candidate = findTagCover(candidates);
if (candidate != null) {
return candidate;
} else {
return findFileCover(candidates);
}
case FILE:
return findFileCover(candidates);
case TAG:
return findTagCover(candidates);
case FILETAG:
default:
candidate = findFileCover(candidates);
if (candidate != null) {
return candidate;
} else {
return findTagCover(candidates);
}
}
}

private File findFileCover(File[] candidates) {
for (String mask : settingsService.getCoverArtFileTypesAsArray()) {
for (File candidate : candidates) {
if (candidate.isFile() && candidate.getName().toUpperCase().endsWith(mask.toUpperCase()) && !candidate.getName().startsWith(".")) {
return candidate;
}
}
}
return null;
}

// Look for embedded images in audiofiles. (Only check first audio file encountered).
private File findTagCover(File[] candidates) {
for (File candidate : candidates) {
if (parser.isApplicable(candidate)) {
return JaudiotaggerParser.getArtwork(getMediaFile(candidate)) != null ? candidate : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ private void doScanLibrary() {

LOG.info("Completed media library scan.");

if (settingsService.isFullScanOnce()) {
settingsService.setFullScanOnce(false);
settingsService.save();
LOG.info("Full scan once property got reset.");
}

} catch (Throwable x) {
LOG.error("Failed to scan media library.", x);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public class SettingsService {
private static final String KEY_MUSIC_FILE_TYPES = "MusicFileTypes";
private static final String KEY_VIDEO_FILE_TYPES = "VideoFileTypes";
private static final String KEY_COVER_ART_FILE_TYPES = "CoverArtFileTypes2";
private static final String KEY_COVER_ART_SOURCE = "CoverArtSource";
private static final String KEY_COVER_ART_CONCURRENCY = "CoverArtConcurrency";
private static final String KEY_WELCOME_TITLE = "WelcomeTitle";
private static final String KEY_WELCOME_SUBTITLE = "WelcomeSubtitle";
Expand All @@ -77,7 +78,7 @@ public class SettingsService {
private static final String KEY_INDEX_CREATION_INTERVAL = "IndexCreationInterval";
private static final String KEY_INDEX_CREATION_HOUR = "IndexCreationHour";
private static final String KEY_FAST_CACHE_ENABLED = "FastCacheEnabled";
private static final String KEY_IGNORE_FILE_TIMESTAMPS = "IgnoreFileTimestamps";
private static final String KEY_FULL_SCAN_ONCE = "FullScanOnce";
private static final String KEY_PODCAST_UPDATE_INTERVAL = "PodcastUpdateInterval";
private static final String KEY_PODCAST_FOLDER = "PodcastFolder";
private static final String KEY_PODCAST_EPISODE_RETENTION_COUNT = "PodcastEpisodeRetentionCount";
Expand Down Expand Up @@ -141,6 +142,7 @@ public class SettingsService {
private static final String DEFAULT_MUSIC_FILE_TYPES = "mp3 ogg oga aac m4a m4b flac wav wma aif aiff ape mpc shn mka opus";
private static final String DEFAULT_VIDEO_FILE_TYPES = "flv avi mpg mpeg mp4 m4v mkv mov wmv ogv divx m2ts webm";
private static final String DEFAULT_COVER_ART_FILE_TYPES = "cover.jpg cover.png cover.gif folder.jpg jpg jpeg gif png";
private static final String DEFAULT_COVER_ART_SOURCE = "FILETAG";
private static final int DEFAULT_COVER_ART_CONCURRENCY = 4;
private static final String DEFAULT_WELCOME_TITLE = "Welcome to Airsonic!";
private static final String DEFAULT_WELCOME_SUBTITLE = null;
Expand All @@ -160,7 +162,7 @@ public class SettingsService {
private static final int DEFAULT_INDEX_CREATION_INTERVAL = 1;
private static final int DEFAULT_INDEX_CREATION_HOUR = 3;
private static final boolean DEFAULT_FAST_CACHE_ENABLED = false;
private static final boolean DEFAULT_IGNORE_FILE_TIMESTAMPS = false;
private static final boolean DEFAULT_FULL_SCAN_ONCE = false;
private static final int DEFAULT_PODCAST_UPDATE_INTERVAL = 24;
private static final String DEFAULT_PODCAST_FOLDER = Util.getDefaultPodcastFolder();
private static final int DEFAULT_PODCAST_EPISODE_RETENTION_COUNT = 10;
Expand Down Expand Up @@ -480,6 +482,18 @@ synchronized String[] getCoverArtFileTypesAsArray() {
return cachedCoverArtFileTypesArray;
}

public CoverArtSource getCoverArtSource() {
try {
return CoverArtSource.valueOf(getProperty(KEY_COVER_ART_SOURCE, DEFAULT_COVER_ART_SOURCE));
} catch (Exception exception) {
return CoverArtSource.valueOf(DEFAULT_COVER_ART_SOURCE);
}
}

public void setCoverArtSource(CoverArtSource source) {
setProperty(KEY_COVER_ART_SOURCE, source.name());
}

public int getCoverArtConcurrency() {
return getInt(KEY_COVER_ART_CONCURRENCY, DEFAULT_COVER_ART_CONCURRENCY);
}
Expand Down Expand Up @@ -554,12 +568,12 @@ public void setFastCacheEnabled(boolean enabled) {
setBoolean(KEY_FAST_CACHE_ENABLED, enabled);
}

public boolean isIgnoreFileTimestamps() {
return getBoolean(KEY_IGNORE_FILE_TIMESTAMPS, DEFAULT_IGNORE_FILE_TIMESTAMPS);
public boolean isFullScanOnce() {
return getBoolean(KEY_FULL_SCAN_ONCE, DEFAULT_FULL_SCAN_ONCE);
}

public void setIgnoreFileTimestamps(boolean ignore) {
setBoolean(KEY_IGNORE_FILE_TIMESTAMPS, ignore);
public void setFullScanOnce(boolean enabled) {
setBoolean(KEY_FULL_SCAN_ONCE, enabled);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ generalsettings.playlistfolder=Playlistordner
generalsettings.musicmask=Musikdateitypen
generalsettings.videomask=Videodateitypen
generalsettings.coverartmask=Coverdateitypen
generalsettings.coverartsource=Coverdateiquelle
generalsettings.coverartsource.option.filetag=Datei vor Tag bevorzugen (Standard)
generalsettings.coverartsource.option.tagfile=Tag vor Datei bevorzugen
generalsettings.coverartsource.option.file=Nur Datei
generalsettings.coverartsource.option.tag=Nur Tag
generalsettings.index=Index
generalsettings.ignoredarticles=Ignorierte W\u00F6rter
generalsettings.shortcuts=Verkn\u00FCpfung (Shortcuts)
Expand Down Expand Up @@ -396,6 +401,7 @@ musicfoldersettings.scannow=Durchsuche jetzt die Medienordner
musicfoldersettings.access=Benutzerzugriffe verwalten
musicfoldersettings.access.description=Konfigurieren sie, auf welche Ordner die einzelnen Benutzer zugreifen d\u00FCrfen.
musicfoldersettings.ignoresymlinks=Ignore Symbolic Links
musicfoldersettings.fullscanonce=N\u00E4chstes Mal vollst\u00E4ndig durchsuchen lassen
musicfoldersettings.excludepattern=Exclude pattern
musicfoldersettings.fastcache=Schnellzugriff
musicfoldersettings.fastcache.description=Nutze diese Funktion um den Festplattenzugriff zu minimieren, zum Beispiel wenn sich ihre Medien auf einem Netzlaufwerk befinden. Anmerkung: \u00C4nderungen an Dateien werden nur sichtbar, nachdem Sie Ihre Medienordner gescannt haben.
Expand Down Expand Up @@ -660,6 +666,8 @@ helppopup.embeddriver.title=JDBC Driver Class
helppopup.embeddriver.text=JDBC Driver dependent class name that implments java.sql.Driver. I.e. for PostgreSQL one would use org.postgresql.Driver. This class must be present in the classpath.
helppopup.excludepattern.title=Exclude Pattern
helppopup.excludepattern.text=Airsonic will not import any files matching this regular expression pattern.
helppopup.fullscanonce.title=Vollst\u00E4ndig durchsuchen
helppopup.fullscanonce.text=Wenn du diese Einstellung aktivierst, werden beim n\u00E4chsten Durchsuchen einmalig alle Dateien durchsucht. Beachte, dass du zuerst speichern musst, bevor du das Durchsuchen startest. Diese Einstellung wird wieder zur\u00FCckgesetzt, sobald das Durchsuchen abgeschlossen ist. Normalerweise durchsucht Airsonic nur Dateien, welche sich seit dem letzten Durchsuchen ge\u00E4ndert haben.
helppopup.playlistfolder.title=Playlist Ordner
helppopup.playlistfolder.text=Hier gibst du den Ordner an, indem sich die Playlists befinden.
helppopup.musicmask.title=Musikdateitypen
Expand All @@ -668,6 +676,8 @@ helppopup.videomask.title=Videodateitypen
helppopup.videomask.text=Hier kannst festlegen welcher Dateityp als Video erkannt werden soll.
helppopup.coverartmask.title=Coverdateitypen
helppopup.coverartmask.text=Hier kannst du angeben, welche Typen von Dateien f\u00FCr Album Covers verwendet werden.
helppopup.coverartsource.title=Coverdateiquelle
helppopup.coverartsource.text=Wenn du diese Einstellung \u00E4nderst, wird beim n\u00E4chsten Mal ein voller Suchvorgang durch die Musikordner durchgef\u00FChrt. Diese Einstellung wird erst nach dem n\u00E4chsten Durchsuchen wirksam. Beachte ausserdem, dass du wohl den Browser-Cache leeren musst, damit die Covers neu geladen werden.
helppopup.downsamplecommand.title=Downsample Befehl
helppopup.downsamplecommand.text=Erlaubt eigenen Befehl f\u00FCr Neuberechnung einer niedrigeren Bitrate.</p><p>(%s = Die Datei wird neu berechnet zu, %b = Max. Bitrate des Players)
helppopup.hlscommand.title=HTTP Live Streaming Befehl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,11 @@ generalsettings.playlistfolder=Import playlists from
generalsettings.musicmask=Music files
generalsettings.videomask=Video files
generalsettings.coverartmask=Cover art files
generalsettings.coverartsource=Cover art source
generalsettings.coverartsource.option.filetag=Prefer file over tag (default)
generalsettings.coverartsource.option.tagfile=Prefer tag over file
generalsettings.coverartsource.option.file=File only
generalsettings.coverartsource.option.tag=Tag only
generalsettings.index=Index
generalsettings.ignoredarticles=Articles to ignore
generalsettings.shortcuts=Shortcuts
Expand Down Expand Up @@ -471,6 +476,7 @@ musicfoldersettings.scannow=Scan media folders now
musicfoldersettings.access=Manage user access
musicfoldersettings.access.description=Configure which folders each user is allowed to access.
musicfoldersettings.ignoresymlinks=Ignore Symbolic Links
musicfoldersettings.fullscanonce=Do a full scan next time
musicfoldersettings.excludepattern=Exclude pattern
musicfoldersettings.fastcache=Fast access mode
musicfoldersettings.fastcache.description=Use this option to minimize disk access, for instance if your media files are located on a network share. Note: Changed or added files will only be visible after your media folders are scanned.
Expand Down Expand Up @@ -735,6 +741,8 @@ helppopup.embeddriver.title=JDBC Driver Class
helppopup.embeddriver.text=JDBC Driver dependent class name that implments java.sql.Driver. I.e. for PostgreSQL one would use org.postgresql.Driver. This class must be present in the classpath.
helppopup.excludepattern.title=Exclude Pattern
helppopup.excludepattern.text=Airsonic will not import any files matching this regular expression pattern.
helppopup.fullscanonce.title=Full scan
helppopup.fullscanonce.text=If you enable this setting Airsonic will do a full scan of all files once on next scan. After enabling this setting, press save before starting a scan. This setting will be reset after the full scan has been completed. Usually Airsonic only scans media which have been changed since the last scan.
helppopup.playlistfolder.title=Import playlist from
helppopup.playlistfolder.text=Playlists in this folder will be imported reqularly.
helppopup.musicmask.title=Music files
Expand All @@ -743,6 +751,8 @@ helppopup.videomask.title=Video files
helppopup.videomask.text=Allows you to specify the type of files that should be recognized as video.
helppopup.coverartmask.title=Cover art files
helppopup.coverartmask.text=Allows you to specify the type of files that should be recognized as cover art when browsing through the media folder.
helppopup.coverartsource.title=Cover art source
helppopup.coverartsource.text=Changing this setting will enable full scanning of media folders on next scan. You have to trigger a scan of your media folders to take effect of this setting. Be aware, that you probably also have to clear your browsercache to get the covers reloaded.
helppopup.downsamplecommand.title=Downsample command
helppopup.downsamplecommand.text=Allows you to specify the command for downsampling to lower bitrates.</p><p>(%s = The file to be downsampled, %b = Max bitrate of the player, %t = Title, %a = Artist, %l = Album)
helppopup.hlscommand.title=HTTP Live Streaming command
Expand Down
14 changes: 14 additions & 0 deletions airsonic-main/src/main/webapp/WEB-INF/jsp/generalSettings.jsp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
<%@ page import="org.airsonic.player.domain.CoverArtSource" %>
<%--@elvariable id="command" type="org.airsonic.player.command.GeneralSettingsCommand"--%>

<html><head>
Expand Down Expand Up @@ -42,6 +43,19 @@
</td>
</tr>

<tr>
<td><fmt:message key="generalsettings.coverartsource"/></td>
<td>
<form:select path="coverArtSource" cssStyle="width:25em">
<form:option value="${CoverArtSource.FILETAG}"><fmt:message key="generalsettings.coverartsource.option.filetag"/></form:option>
<form:option value="${CoverArtSource.TAGFILE}"><fmt:message key="generalsettings.coverartsource.option.tagfile"/></form:option>>
<form:option value="${CoverArtSource.FILE}"><fmt:message key="generalsettings.coverartsource.option.file"/></form:option>
<form:option value="${CoverArtSource.TAG}"><fmt:message key="generalsettings.coverartsource.option.tag"/></form:option>
</form:select>
<c:import url="helpToolTip.jsp"><c:param name="topic" value="coverartsource"/></c:import>
</td>
</tr>

<tr>
<td><fmt:message key="generalsettings.playlistfolder"/></td>
<td>
Expand Down