Merge remote-tracking branch 'origin/master'

master
Weblate 7 years ago
commit 1bc6e16418
  1. 10
      airsonic-main/src/main/java/org/airsonic/player/controller/CoverArtController.java
  2. 6
      airsonic-main/src/main/java/org/airsonic/player/service/MediaFileService.java
  3. 40
      airsonic-main/src/main/java/org/airsonic/player/service/ServiceLocator.java
  4. 70
      airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java
  5. 11
      airsonic-main/src/main/java/org/airsonic/player/service/metadata/DefaultMetaDataParser.java
  6. 14
      airsonic-main/src/main/java/org/airsonic/player/service/metadata/FFmpegParser.java
  7. 11
      airsonic-main/src/main/java/org/airsonic/player/service/metadata/JaudiotaggerParser.java
  8. 9
      airsonic-main/src/main/java/org/airsonic/player/service/metadata/MetaDataParser.java
  9. 14
      airsonic-main/src/main/resources/applicationContext-service.xml
  10. 6
      airsonic-main/src/test/java/org/airsonic/player/service/metadata/MetaDataParserTestCase.java

@ -82,6 +82,8 @@ public class CoverArtController implements LastModified {
private ArtistDao artistDao;
@Autowired
private AlbumDao albumDao;
@Autowired
private JaudiotaggerParser jaudiotaggerParser;
private Semaphore semaphore;
@PostConstruct
@ -217,8 +219,7 @@ public class CoverArtController implements LastModified {
private void sendUnscaled(CoverArtRequest coverArtRequest, HttpServletResponse response) throws IOException {
File file = coverArtRequest.getCoverArt();
JaudiotaggerParser parser = new JaudiotaggerParser();
if (!parser.isApplicable(file)) {
if (!jaudiotaggerParser.isApplicable(file)) {
response.setContentType(StringUtil.getMimeType(FilenameUtils.getExtension(file.getName())));
}
InputStream in = null;
@ -274,10 +275,9 @@ public class CoverArtController implements LastModified {
* the embedded album art is returned.
*/
private InputStream getImageInputStream(File file) throws IOException {
JaudiotaggerParser parser = new JaudiotaggerParser();
if (parser.isApplicable(file)) {
if (jaudiotaggerParser.isApplicable(file)) {
MediaFile mediaFile = mediaFileService.getMediaFile(file);
return new ByteArrayInputStream(parser.getImageData(mediaFile));
return new ByteArrayInputStream(jaudiotaggerParser.getImageData(mediaFile));
} else {
return new FileInputStream(file);
}

@ -52,6 +52,7 @@ public class MediaFileService {
private SettingsService settingsService;
private MediaFileDao mediaFileDao;
private AlbumDao albumDao;
private JaudiotaggerParser parser;
private MetaDataParserFactory metaDataParserFactory;
private boolean memoryCacheEnabled = true;
@ -600,7 +601,6 @@ public class MediaFileService {
}
// Look for embedded images in audiofiles. (Only check first audio file encountered).
JaudiotaggerParser parser = new JaudiotaggerParser();
for (File candidate : candidates) {
if (parser.isApplicable(candidate)) {
if (parser.isImageAvailable(getMediaFile(candidate))) {
@ -706,4 +706,8 @@ public class MediaFileService {
public void setAlbumDao(AlbumDao albumDao) {
this.albumDao = albumDao;
}
public void setParser(JaudiotaggerParser parser) {
this.parser = parser;
}
}

@ -1,40 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2016 (C) Airsonic Authors
Based upon Subsonic, Copyright 2009 (C) Sindre Mehus
*/
package org.airsonic.player.service;
/**
* Locates services for objects that are not part of the Spring context.
*
* @author Sindre Mehus
*/
@Deprecated
public class ServiceLocator {
private static SettingsService settingsService;
public static SettingsService getSettingsService() {
return settingsService;
}
public static void setSettingsService(SettingsService settingsService) {
ServiceLocator.settingsService = settingsService;
}
}

@ -87,7 +87,6 @@ public class SettingsService {
private static final String KEY_LDAP_SEARCH_FILTER = "LdapSearchFilter";
private static final String KEY_LDAP_AUTO_SHADOWING = "LdapAutoShadowing";
private static final String KEY_GETTING_STARTED_ENABLED = "GettingStartedEnabled";
private static final String KEY_SERVER_ID = "ServerId";
private static final String KEY_SETTINGS_CHANGED = "SettingsChanged";
private static final String KEY_LAST_SCANNED = "LastScanned";
private static final String KEY_ORGANIZE_BY_FOLDER_STRUCTURE = "OrganizeByFolderStructure";
@ -164,7 +163,6 @@ public class SettingsService {
private static final String DEFAULT_LDAP_SEARCH_FILTER = "(sAMAccountName={0})";
private static final boolean DEFAULT_LDAP_AUTO_SHADOWING = false;
private static final boolean DEFAULT_GETTING_STARTED_ENABLED = true;
private static final String DEFAULT_SERVER_ID = null;
private static final long DEFAULT_SETTINGS_CHANGED = 0L;
private static final boolean DEFAULT_ORGANIZE_BY_FOLDER_STRUCTURE = true;
private static final boolean DEFAULT_SORT_ALBUMS_BY_YEAR = true;
@ -222,9 +220,9 @@ public class SettingsService {
private String[] cachedMusicFileTypesArray;
private String[] cachedVideoFileTypesArray;
private List<MusicFolder> cachedMusicFolders;
private final ConcurrentMap<String, List<MusicFolder>> cachedMusicFoldersPerUser = new ConcurrentHashMap<String, List<MusicFolder>>();
private final ConcurrentMap<String, List<MusicFolder>> cachedMusicFoldersPerUser = new ConcurrentHashMap<>();
private void removeObseleteProperties() {
private void removeObsoleteProperties() {
OBSOLETE_KEYS.forEach( oKey -> {
if(configurationService.containsKey(oKey)) {
@ -254,7 +252,7 @@ public class SettingsService {
return home;
}
public static String getFileSystemAppName() {
private static String getFileSystemAppName() {
String home = getAirsonicHome().getPath();
return home.contains("libresonic") ? "libresonic" : "airsonic";
}
@ -275,7 +273,6 @@ public class SettingsService {
*/
public void init() {
logServerInfo();
ServiceLocator.setSettingsService(this);
}
private void logServerInfo() {
@ -289,7 +286,7 @@ public class SettingsService {
public void save(boolean updateSettingsChanged) {
if(updateSettingsChanged) {
removeObseleteProperties();
removeObsoleteProperties();
this.setLong(KEY_SETTINGS_CHANGED, System.currentTimeMillis());
}
configurationService.save();
@ -308,7 +305,7 @@ public class SettingsService {
}
}
public static File getPropertyFile() {
static File getPropertyFile() {
File propertyFile = getAirsonicHome();
return new File(propertyFile, getFileSystemAppName() + ".properties");
}
@ -361,7 +358,7 @@ public class SettingsService {
return getProperty(KEY_IGNORED_ARTICLES, DEFAULT_IGNORED_ARTICLES);
}
public String[] getIgnoredArticlesAsArray() {
String[] getIgnoredArticlesAsArray() {
return getIgnoredArticles().split("\\s+");
}
@ -373,7 +370,7 @@ public class SettingsService {
return getProperty(KEY_SHORTCUTS, DEFAULT_SHORTCUTS);
}
public String[] getShortcutsAsArray() {
String[] getShortcutsAsArray() {
return StringUtil.split(getShortcuts());
}
@ -398,7 +395,7 @@ public class SettingsService {
cachedMusicFileTypesArray = null;
}
public synchronized String[] getMusicFileTypesAsArray() {
synchronized String[] getMusicFileTypesAsArray() {
if (cachedMusicFileTypesArray == null) {
cachedMusicFileTypesArray = toStringArray(getMusicFileTypes());
}
@ -430,7 +427,7 @@ public class SettingsService {
cachedCoverArtFileTypesArray = null;
}
public synchronized String[] getCoverArtFileTypesAsArray() {
synchronized String[] getCoverArtFileTypesAsArray() {
if (cachedCoverArtFileTypesArray == null) {
cachedCoverArtFileTypesArray = toStringArray(getCoverArtFileTypes());
}
@ -613,7 +610,7 @@ public class SettingsService {
setProperty(KEY_HLS_COMMAND, command);
}
public String getJukeboxCommand() {
String getJukeboxCommand() {
return getProperty(KEY_JUKEBOX_COMMAND, DEFAULT_JUKEBOX_COMMAND);
}
public String getVideoImageCommand() {
@ -687,14 +684,6 @@ public class SettingsService {
setBoolean(KEY_GETTING_STARTED_ENABLED, isGettingStartedEnabled);
}
public String getServerId() {
return getProperty(KEY_SERVER_ID, DEFAULT_SERVER_ID);
}
public void setServerId(String serverId) {
setProperty(KEY_SERVER_ID, serverId);
}
public long getSettingsChanged() {
return getLong(KEY_SETTINGS_CHANGED, DEFAULT_SETTINGS_CHANGED);
}
@ -704,7 +693,7 @@ public class SettingsService {
return lastScanned == null ? null : new Date(Long.parseLong(lastScanned));
}
public void setLastScanned(Date date) {
void setLastScanned(Date date) {
if (date == null) {
setProperty(KEY_LAST_SCANNED, null);
} else {
@ -732,7 +721,7 @@ public class SettingsService {
return MediaLibraryStatistics.parse(getString(KEY_MEDIA_LIBRARY_STATISTICS, DEFAULT_MEDIA_LIBRARY_STATISTICS));
}
public void setMediaLibraryStatistics(MediaLibraryStatistics statistics) {
void setMediaLibraryStatistics(MediaLibraryStatistics statistics) {
setString(KEY_MEDIA_LIBRARY_STATISTICS, statistics.format());
}
@ -785,7 +774,7 @@ public class SettingsService {
*/
public synchronized Theme[] getAvailableThemes() {
if (themes == null) {
themes = new ArrayList<Theme>();
themes = new ArrayList<>();
try {
InputStream in = SettingsService.class.getResourceAsStream(THEMES_FILE);
String[] lines = StringUtil.readLines(in);
@ -814,7 +803,7 @@ public class SettingsService {
*/
public synchronized Locale[] getAvailableLocales() {
if (locales == null) {
locales = new ArrayList<Locale>();
locales = new ArrayList<>();
try {
InputStream in = SettingsService.class.getResourceAsStream(LOCALES_FILE);
String[] lines = StringUtil.readLines(in);
@ -876,7 +865,7 @@ public class SettingsService {
cachedMusicFolders = musicFolderDao.getAllMusicFolders();
}
List<MusicFolder> result = new ArrayList<MusicFolder>(cachedMusicFolders.size());
List<MusicFolder> result = new ArrayList<>(cachedMusicFolders.size());
for (MusicFolder folder : cachedMusicFolders) {
if ((includeDisabled || folder.isEnabled()) && (includeNonExisting || FileUtil.exists(folder.getPath()))) {
result.add(folder);
@ -913,7 +902,7 @@ public class SettingsService {
return allowed;
}
MusicFolder selected = getMusicFolderById(selectedMusicFolderId);
return allowed.contains(selected) ? Arrays.asList(selected) : Collections.<MusicFolder>emptyList();
return allowed.contains(selected) ? Collections.singletonList(selected) : Collections.emptyList();
}
/**
@ -993,21 +982,6 @@ public class SettingsService {
return getAllInternetRadios(false);
}
/**
* Returns the internet radio station with the given ID.
*
* @param id The ID.
* @return The internet radio station with the given ID, or <code>null</code> if not found.
*/
public InternetRadio getInternetRadioById(Integer id) {
for (InternetRadio radio : getAllInternetRadios()) {
if (id.equals(radio.getId())) {
return radio;
}
}
return null;
}
/**
* Returns all internet radio stations.
*
@ -1016,7 +990,7 @@ public class SettingsService {
*/
public List<InternetRadio> getAllInternetRadios(boolean includeAll) {
List<InternetRadio> all = internetRadioDao.getAllInternetRadios();
List<InternetRadio> result = new ArrayList<InternetRadio>(all.size());
List<InternetRadio> result = new ArrayList<>(all.size());
for (InternetRadio folder : all) {
if (includeAll || folder.isEnabled()) {
result.add(folder);
@ -1190,14 +1164,10 @@ public class SettingsService {
setString(KEY_SONOS_SERVICE_NAME, sonosServiceName);
}
public int getSonosServiceId() {
int getSonosServiceId() {
return getInt(KEY_SONOS_SERVICE_ID, DEFAULT_SONOS_SERVICE_ID);
}
public void setSonosServiceId(int sonosServiceid) {
setInt(KEY_SONOS_SERVICE_ID, sonosServiceid);
}
private void setProperty(String key, Object value) {
if (value == null) {
configurationService.clearProperty(key);
@ -1207,7 +1177,7 @@ public class SettingsService {
}
private String[] toStringArray(String s) {
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(s, " ");
while (tokenizer.hasMoreTokens()) {
result.add(tokenizer.nextToken());
@ -1378,7 +1348,7 @@ public class SettingsService {
setDatabaseConfigType(DEFAULT_DATABASE_CONFIG_TYPE);
}
public String getPlaylistExportFormat() {
String getPlaylistExportFormat() {
return getProperty(KEY_EXPORT_PLAYLIST_FORMAT, DEFAULT_EXPORT_PLAYLIST_FORMAT);
}
}

@ -20,6 +20,7 @@
package org.airsonic.player.service.metadata;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.service.SettingsService;
import java.io.File;
@ -30,6 +31,11 @@ import java.io.File;
*/
public class DefaultMetaDataParser extends MetaDataParser {
private final SettingsService settingsService;
public DefaultMetaDataParser(SettingsService settingsService) {
this.settingsService = settingsService;
}
/**
* Parses meta data for the given file.
*
@ -65,6 +71,11 @@ public class DefaultMetaDataParser extends MetaDataParser {
return false;
}
@Override
SettingsService getSettingsService() {
return settingsService;
}
/**
* Returns whether this parser is applicable to the given file.
*

@ -21,7 +21,7 @@ package org.airsonic.player.service.metadata;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.io.InputStreamReaderThread;
import org.airsonic.player.service.ServiceLocator;
import org.airsonic.player.service.SettingsService;
import org.airsonic.player.service.TranscodingService;
import org.airsonic.player.util.StringUtil;
import org.apache.commons.io.FilenameUtils;
@ -49,6 +49,7 @@ public class FFmpegParser extends MetaDataParser {
private static final Pattern PAR_PATTERN = Pattern.compile("PAR (\\d+):(\\d+)");
private TranscodingService transcodingService;
private SettingsService settingsService;
/**
* Parses meta data for the given music file. No guessing or reformatting is done.
@ -148,6 +149,11 @@ public class FFmpegParser extends MetaDataParser {
return false;
}
@Override
SettingsService getSettingsService() {
return settingsService;
}
/**
* Returns whether this parser is applicable to the given file.
*
@ -158,7 +164,7 @@ public class FFmpegParser extends MetaDataParser {
public boolean isApplicable(File file) {
String format = FilenameUtils.getExtension(file.getName()).toLowerCase();
for (String s : ServiceLocator.getSettingsService().getVideoFileTypesAsArray()) {
for (String s : settingsService.getVideoFileTypesAsArray()) {
if (format.equals(s)) {
return true;
}
@ -169,4 +175,8 @@ public class FFmpegParser extends MetaDataParser {
public void setTranscodingService(TranscodingService transcodingService) {
this.transcodingService = transcodingService;
}
public void setSettingsService(SettingsService settingsService) {
this.settingsService = settingsService;
}
}

@ -20,6 +20,7 @@
package org.airsonic.player.service.metadata;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.service.SettingsService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.jaudiotagger.audio.AudioFile;
@ -51,6 +52,11 @@ public class JaudiotaggerParser extends MetaDataParser {
private static final Pattern GENRE_PATTERN = Pattern.compile("\\((\\d+)\\).*");
private static final Pattern TRACK_NUMBER_PATTERN = Pattern.compile("(\\d+)/\\d+");
private static final Pattern YEAR_NUMBER_PATTERN = Pattern.compile("(\\d{4}).*");
private final SettingsService settingsService;
public JaudiotaggerParser(SettingsService settingsService) {
this.settingsService = settingsService;
}
static {
try {
@ -265,6 +271,11 @@ public class JaudiotaggerParser extends MetaDataParser {
return true;
}
@Override
SettingsService getSettingsService() {
return settingsService;
}
/**
* Returns whether this parser is applicable to the given file.
*

@ -21,7 +21,6 @@ package org.airsonic.player.service.metadata;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.domain.MusicFolder;
import org.airsonic.player.service.ServiceLocator;
import org.airsonic.player.service.SettingsService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
@ -108,7 +107,7 @@ public abstract class MetaDataParser {
/**
* Guesses the artist for the given file.
*/
public String guessArtist(File file) {
String guessArtist(File file) {
File parent = file.getParentFile();
if (isRoot(parent)) {
return null;
@ -120,7 +119,7 @@ public abstract class MetaDataParser {
/**
* Guesses the album for the given file.
*/
public String guessAlbum(File file, String artist) {
String guessAlbum(File file, String artist) {
File parent = file.getParentFile();
String album = isRoot(parent) ? null : parent.getName();
if (artist != null && album != null) {
@ -137,7 +136,7 @@ public abstract class MetaDataParser {
}
private boolean isRoot(File file) {
SettingsService settings = ServiceLocator.getSettingsService();
SettingsService settings = getSettingsService();
List<MusicFolder> folders = settings.getAllMusicFolders(false, true);
for (MusicFolder folder : folders) {
if (file.equals(folder.getPath())) {
@ -147,6 +146,8 @@ public abstract class MetaDataParser {
return false;
}
abstract SettingsService getSettingsService();
/**
* Removes any prefixed track number from the given title string.
*

@ -82,6 +82,7 @@
<property name="mediaFileDao" ref="mediaFileDao"/>
<property name="albumDao" ref="albumDao"/>
<property name="metaDataParserFactory" ref="metaDataParserFactory"/>
<property name="parser" ref="jaudiotaggerParser" />
</bean>
<bean id="securityService" class="org.airsonic.player.service.SecurityService">
@ -233,14 +234,23 @@
<property name="upnpService" ref="upnpService"/>
</bean>
<bean id="jaudiotaggerParser" class="org.airsonic.player.service.metadata.JaudiotaggerParser">
<constructor-arg name="settingsService" ref="settingsService" />
</bean>
<bean id="metaDataParserFactory" class="org.airsonic.player.service.metadata.MetaDataParserFactory">
<property name="parsers">
<list>
<bean class="org.airsonic.player.service.metadata.JaudiotaggerParser"/>
<bean class="org.airsonic.player.service.metadata.JaudiotaggerParser">
<constructor-arg name="settingsService" ref="settingsService" />
</bean>
<bean class="org.airsonic.player.service.metadata.FFmpegParser">
<property name="transcodingService" ref="transcodingService"/>
<property name="settingsService" ref="settingsService" />
</bean>
<bean class="org.airsonic.player.service.metadata.DefaultMetaDataParser">
<constructor-arg name="settingsService" ref="settingsService" />
</bean>
<bean class="org.airsonic.player.service.metadata.DefaultMetaDataParser"/>
</list>
</property>
</bean>

@ -21,6 +21,7 @@ package org.airsonic.player.service.metadata;
import junit.framework.TestCase;
import org.airsonic.player.domain.MediaFile;
import org.airsonic.player.service.SettingsService;
import java.io.File;
@ -45,6 +46,11 @@ public class MetaDataParserTestCase extends TestCase {
return false;
}
@Override
SettingsService getSettingsService() {
return null;
}
public boolean isApplicable(File file) {
return false;
}

Loading…
Cancel
Save