mirror of
https://github.com/airsonic/airsonic.git
synced 2025-10-03 09:49:17 +02:00
Clean up a bit the jaudiotagger wrapper
- ID3v24 are now fully supported by jaudiotagger, there is no need to have special code to handle them - Inline a couple of one-line'n'useless methods - Replace isImageAvailable with getArtwork - Make some methods static - Specialise some exceptions
This commit is contained in:
parent
03a607d659
commit
a13552b6f5
2 changed files with 49 additions and 135 deletions
|
@ -624,11 +624,7 @@ public class MediaFileService {
|
||||||
// Look for embedded images in audiofiles. (Only check first audio file encountered).
|
// Look for embedded images in audiofiles. (Only check first audio file encountered).
|
||||||
for (File candidate : candidates) {
|
for (File candidate : candidates) {
|
||||||
if (parser.isApplicable(candidate)) {
|
if (parser.isApplicable(candidate)) {
|
||||||
if (parser.isImageAvailable(getMediaFile(candidate))) {
|
return JaudiotaggerParser.getArtwork(getMediaFile(candidate)) != null ? candidate : null;
|
||||||
return candidate;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -27,10 +27,8 @@ import org.jaudiotagger.audio.AudioFile;
|
||||||
import org.jaudiotagger.audio.AudioFileIO;
|
import org.jaudiotagger.audio.AudioFileIO;
|
||||||
import org.jaudiotagger.audio.AudioHeader;
|
import org.jaudiotagger.audio.AudioHeader;
|
||||||
import org.jaudiotagger.tag.FieldKey;
|
import org.jaudiotagger.tag.FieldKey;
|
||||||
|
import org.jaudiotagger.tag.KeyNotFoundException;
|
||||||
import org.jaudiotagger.tag.Tag;
|
import org.jaudiotagger.tag.Tag;
|
||||||
import org.jaudiotagger.tag.id3.AbstractID3Tag;
|
|
||||||
import org.jaudiotagger.tag.id3.ID3v24Frames;
|
|
||||||
import org.jaudiotagger.tag.id3.ID3v24Tag;
|
|
||||||
import org.jaudiotagger.tag.images.Artwork;
|
import org.jaudiotagger.tag.images.Artwork;
|
||||||
import org.jaudiotagger.tag.reference.GenreTypes;
|
import org.jaudiotagger.tag.reference.GenreTypes;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -38,7 +36,6 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
@ -71,7 +68,7 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
LogManager.getLogManager().reset();
|
LogManager.getLogManager().reset();
|
||||||
} catch (Throwable x) {
|
} catch (SecurityException x) {
|
||||||
LOG.warn("Failed to turn off logging from Jaudiotagger.", x);
|
LOG.warn("Failed to turn off logging from Jaudiotagger.", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +76,6 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
/**
|
/**
|
||||||
* Parses meta data for the given music file. No guessing or reformatting is done.
|
* Parses meta data for the given music file. No guessing or reformatting is done.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @param file The music file to parse.
|
* @param file The music file to parse.
|
||||||
* @return Meta data for the file.
|
* @return Meta data for the file.
|
||||||
*/
|
*/
|
||||||
|
@ -87,106 +83,50 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
public MetaData getRawMetaData(File file) {
|
public MetaData getRawMetaData(File file) {
|
||||||
|
|
||||||
MetaData metaData = new MetaData();
|
MetaData metaData = new MetaData();
|
||||||
|
AudioFile audioFile;
|
||||||
try {
|
try {
|
||||||
AudioFile audioFile = AudioFileIO.read(file);
|
audioFile = AudioFileIO.read(file);
|
||||||
Tag tag = audioFile.getTag();
|
|
||||||
if (tag != null) {
|
|
||||||
metaData.setAlbumName(getTagField(tag, FieldKey.ALBUM));
|
|
||||||
metaData.setTitle(getTagField(tag, FieldKey.TITLE));
|
|
||||||
metaData.setYear(parseYear(getTagField(tag, FieldKey.YEAR)));
|
|
||||||
metaData.setGenre(mapGenre(getTagField(tag, FieldKey.GENRE)));
|
|
||||||
metaData.setDiscNumber(parseInteger(getTagField(tag, FieldKey.DISC_NO)));
|
|
||||||
metaData.setTrackNumber(parseTrackNumber(getTagField(tag, FieldKey.TRACK)));
|
|
||||||
metaData.setMusicBrainzReleaseId(getTagField(tag, FieldKey.MUSICBRAINZ_RELEASEID));
|
|
||||||
metaData.setMusicBrainzRecordingId(getTagField(tag, FieldKey.MUSICBRAINZ_TRACK_ID));
|
|
||||||
|
|
||||||
metaData.setArtist(getTagField(tag, FieldKey.ARTIST));
|
|
||||||
metaData.setAlbumArtist(getTagField(tag, FieldKey.ALBUM_ARTIST));
|
|
||||||
|
|
||||||
if (tag instanceof AbstractID3Tag && 0 < audioFile.getTag().getFieldCount()) {
|
|
||||||
|
|
||||||
AbstractID3Tag id3Tag = (AbstractID3Tag)tag;
|
|
||||||
if (ID3v24Tag.RELEASE == id3Tag.getRelease()
|
|
||||||
&& ID3v24Tag.MAJOR_VERSION == id3Tag.getMajorVersion()
|
|
||||||
&& ID3v24Tag.REVISION == id3Tag.getRevision()) {
|
|
||||||
|
|
||||||
audioFile.getTag().getFields().forEachRemaining(f -> {
|
|
||||||
switch (f.getId()) {
|
|
||||||
case ID3v24Frames.FRAME_ID_ALBUM:
|
|
||||||
if (StringUtils.isBlank(metaData.getAlbumName())) {
|
|
||||||
metaData.setAlbumName(f.toString());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_TITLE:
|
|
||||||
if (StringUtils.isBlank(metaData.getTitle())) {
|
|
||||||
metaData.setTitle(f.toString());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_YEAR:
|
|
||||||
if (ObjectUtils.isEmpty(metaData.getYear())) {
|
|
||||||
metaData.setYear(parseYear(f.toString()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_GENRE:
|
|
||||||
if (StringUtils.isBlank(metaData.getGenre())) {
|
|
||||||
metaData.setGenre(mapGenre(f.toString()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_SET:
|
|
||||||
if (ObjectUtils.isEmpty(metaData.getDiscNumber())) {
|
|
||||||
metaData.setDiscNumber(parseInteger(f.toString()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_TRACK:
|
|
||||||
if (ObjectUtils.isEmpty(metaData.getTrackNumber())) {
|
|
||||||
metaData.setTrackNumber(parseTrackNumber(f.toString()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_ARTIST:
|
|
||||||
if (StringUtils.isBlank(metaData.getArtist())) {
|
|
||||||
metaData.setArtist(f.toString());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ID3v24Frames.FRAME_ID_ACCOMPANIMENT:
|
|
||||||
if (StringUtils.isBlank(metaData.getAlbumArtist())) {
|
|
||||||
metaData.setAlbumArtist(f.toString());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (StringUtils.isBlank(metaData.getArtist())) {
|
|
||||||
metaData.setArtist(metaData.getAlbumArtist());
|
|
||||||
}
|
|
||||||
if (StringUtils.isBlank(metaData.getAlbumArtist())) {
|
|
||||||
metaData.setAlbumArtist(metaData.getArtist());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioHeader audioHeader = audioFile.getAudioHeader();
|
|
||||||
if (audioHeader != null) {
|
|
||||||
metaData.setVariableBitRate(audioHeader.isVariableBitRate());
|
|
||||||
metaData.setBitRate((int) audioHeader.getBitRateAsNumber());
|
|
||||||
metaData.setDurationSeconds(audioHeader.getTrackLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
LOG.warn("Error when parsing tags in " + file, x);
|
LOG.warn("Error when parsing tags in " + file, x);
|
||||||
|
return metaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag tag = audioFile.getTag();
|
||||||
|
if (tag != null) {
|
||||||
|
metaData.setAlbumArtist(getTagField(tag, FieldKey.ALBUM_ARTIST));
|
||||||
|
metaData.setAlbumName(getTagField(tag, FieldKey.ALBUM));
|
||||||
|
metaData.setArtist(getTagField(tag, FieldKey.ARTIST));
|
||||||
|
metaData.setDiscNumber(parseInteger(getTagField(tag, FieldKey.DISC_NO)));
|
||||||
|
metaData.setGenre(mapGenre(getTagField(tag, FieldKey.GENRE)));
|
||||||
|
metaData.setMusicBrainzRecordingId(getTagField(tag, FieldKey.MUSICBRAINZ_TRACK_ID));
|
||||||
|
metaData.setMusicBrainzReleaseId(getTagField(tag, FieldKey.MUSICBRAINZ_RELEASEID));
|
||||||
|
metaData.setTitle(getTagField(tag, FieldKey.TITLE));
|
||||||
|
metaData.setTrackNumber(parseIntegerPattern(getTagField(tag, FieldKey.TRACK), TRACK_NUMBER_PATTERN));
|
||||||
|
metaData.setYear(parseIntegerPattern(getTagField(tag, FieldKey.YEAR), YEAR_NUMBER_PATTERN));
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(metaData.getArtist())) {
|
||||||
|
metaData.setArtist(metaData.getAlbumArtist());
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(metaData.getAlbumArtist())) {
|
||||||
|
metaData.setAlbumArtist(metaData.getArtist());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioHeader audioHeader = audioFile.getAudioHeader();
|
||||||
|
if (audioHeader != null) {
|
||||||
|
metaData.setVariableBitRate(audioHeader.isVariableBitRate());
|
||||||
|
metaData.setBitRate((int) audioHeader.getBitRateAsNumber());
|
||||||
|
metaData.setDurationSeconds(audioHeader.getTrackLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
return metaData;
|
return metaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTagField(Tag tag, FieldKey fieldKey) {
|
private static String getTagField(Tag tag, FieldKey fieldKey) {
|
||||||
try {
|
try {
|
||||||
return StringUtils.trimToNull(tag.getFirst(fieldKey));
|
return StringUtils.trimToNull(tag.getFirst(fieldKey));
|
||||||
} catch (Exception x) {
|
} catch (KeyNotFoundException x) {
|
||||||
// Ignored.
|
// Ignored.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -196,14 +136,14 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
* Returns all tags supported by id3v1.
|
* Returns all tags supported by id3v1.
|
||||||
*/
|
*/
|
||||||
public static SortedSet<String> getID3V1Genres() {
|
public static SortedSet<String> getID3V1Genres() {
|
||||||
return new TreeSet<String>(GenreTypes.getInstanceOf().getAlphabeticalValueList());
|
return new TreeSet<>(GenreTypes.getInstanceOf().getAlphabeticalValueList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sometimes the genre is returned as "(17)" or "(17)Rock", instead of "Rock". This method
|
* Sometimes the genre is returned as "(17)" or "(17)Rock", instead of "Rock". This method
|
||||||
* maps the genre ID to the corresponding text.
|
* maps the genre ID to the corresponding text.
|
||||||
*/
|
*/
|
||||||
private String mapGenre(String genre) {
|
private static String mapGenre(String genre) {
|
||||||
if (genre == null) {
|
if (genre == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -217,19 +157,7 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
return genre;
|
return genre;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static Integer parseIntegerPattern(String str, Pattern pattern) {
|
||||||
* Parses the track number from the given string. Also supports
|
|
||||||
* track numbers on the form "4/12".
|
|
||||||
*/
|
|
||||||
private Integer parseTrackNumber(String trackNumber) {
|
|
||||||
return parseIntegerPattern(trackNumber, TRACK_NUMBER_PATTERN);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer parseYear(String year) {
|
|
||||||
return parseIntegerPattern(year, YEAR_NUMBER_PATTERN);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer parseIntegerPattern(String str, Pattern pattern) {
|
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -258,9 +186,8 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer parseInteger(String s) {
|
private static Integer parseInteger(String s) {
|
||||||
s = StringUtils.trimToNull(s);
|
return parseIntegerPattern(StringUtils.trimToNull(s), null);
|
||||||
return parseIntegerPattern(s, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -350,24 +277,15 @@ public class JaudiotaggerParser extends MetaDataParser {
|
||||||
"wma".equals(format);
|
"wma".equals(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static Artwork getArtwork(MediaFile file) {
|
||||||
* Returns whether cover art image data is available in the given file.
|
AudioFile audioFile;
|
||||||
*
|
|
||||||
* @param file The music file.
|
|
||||||
* @return Whether cover art image data is available.
|
|
||||||
*/
|
|
||||||
public boolean isImageAvailable(MediaFile file) {
|
|
||||||
try {
|
try {
|
||||||
return getArtwork(file) != null;
|
audioFile = AudioFileIO.read(file.getFile());
|
||||||
} catch (Throwable x) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Failed to find cover art tag in " + file, x);
|
LOG.info("Failed to find cover art tag in " + file, e);
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Artwork getArtwork(MediaFile file) throws Exception {
|
|
||||||
AudioFile audioFile = AudioFileIO.read(file.getFile());
|
|
||||||
Tag tag = audioFile.getTag();
|
Tag tag = audioFile.getTag();
|
||||||
return tag == null ? null : tag.getFirstArtwork();
|
return tag == null ? null : tag.getFirstArtwork();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue