Subsonic API: added bitDepth, samplingRate and channelCount, see https://github.com/opensubsonic/open-subsonic-api/pull/83
This commit is contained in:
@@ -144,6 +144,17 @@ namespace lms::metadata
|
||||
try
|
||||
{
|
||||
const auto audioFile{ av::parseAudioFile(p) };
|
||||
|
||||
_audioProperties.duration = audioFile->getContainerInfo().duration;
|
||||
|
||||
const auto bestAudioStream{ audioFile->getBestStreamInfo() };
|
||||
if (bestAudioStream)
|
||||
{
|
||||
_audioProperties.bitrate = bestAudioStream->bitrate;
|
||||
_audioProperties.bitsPerSample = bestAudioStream->bitsPerSample;
|
||||
_audioProperties.channelCount = bestAudioStream->channelCount;
|
||||
_audioProperties.sampleRate = bestAudioStream->sampleRate;
|
||||
}
|
||||
|
||||
_containerInfo = audioFile->getContainerInfo();
|
||||
_metaDataMap = audioFile->getMetaData();
|
||||
|
||||
@@ -40,12 +40,9 @@ namespace lms::metadata
|
||||
void visitTagValues(std::string_view tag, TagValueVisitor visitor) const override;
|
||||
void visitPerformerTags(PerformerVisitor visitor) const override;
|
||||
bool hasEmbeddedCover() const override { return _hasEmbeddedCover; }
|
||||
const AudioProperties& getAudioProperties() const override { return _audioProperties; }
|
||||
|
||||
std::chrono::milliseconds getDuration() const override { return _containerInfo.duration; }
|
||||
std::size_t getBitrate() const override { return _containerInfo.bitrate; }
|
||||
std::size_t getBitsPerSample() const override { return 0; }
|
||||
std::size_t getSampleRate() const override { return 0; }
|
||||
|
||||
AudioProperties _audioProperties;
|
||||
av::IAudioFile::MetadataMap _metaDataMap;
|
||||
av::ContainerInfo _containerInfo;
|
||||
bool _hasEmbeddedCover{};
|
||||
|
||||
@@ -153,10 +153,6 @@ namespace lms::metadata
|
||||
virtual void visitPerformerTags(PerformerVisitor visitor) const = 0;
|
||||
|
||||
virtual bool hasEmbeddedCover() const = 0;
|
||||
|
||||
virtual std::chrono::milliseconds getDuration() const = 0;
|
||||
virtual std::size_t getBitrate() const = 0;
|
||||
virtual std::size_t getBitsPerSample() const = 0;
|
||||
virtual std::size_t getSampleRate() const = 0;
|
||||
virtual const AudioProperties& getAudioProperties() const = 0;
|
||||
};
|
||||
} // namespace lms::metadata
|
||||
|
||||
@@ -235,18 +235,12 @@ namespace lms::metadata
|
||||
{
|
||||
auto track{ std::make_unique<Track>() };
|
||||
|
||||
processAudioProperties(tagReader, *track);
|
||||
track->audioProperties = tagReader.getAudioProperties();
|
||||
processTags(tagReader, *track);
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
void Parser::processAudioProperties(const ITagReader& tagReader, Track& track)
|
||||
{
|
||||
track.duration = tagReader.getDuration();
|
||||
track.bitrate = tagReader.getBitrate();
|
||||
}
|
||||
|
||||
void Parser::processTags(const ITagReader& tagReader, Track& track)
|
||||
{
|
||||
track.hasCover = tagReader.hasEmbeddedCover();
|
||||
|
||||
@@ -37,7 +37,6 @@ namespace lms::metadata
|
||||
void setArtistTagDelimiters(std::span<const std::string> delimiters) override { _artistTagDelimiters.assign(std::cbegin(delimiters), std::cend(delimiters)); }
|
||||
void setDefaultTagDelimiters(std::span<const std::string> delimiters) override { _defaultTagDelimiters.assign(std::cbegin(delimiters), std::cend(delimiters)); }
|
||||
|
||||
void processAudioProperties(const ITagReader& reader, Track& track);
|
||||
void processTags(const ITagReader& reader, Track& track);
|
||||
|
||||
std::optional<Medium> getMedium(const ITagReader& tagReader);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <taglib/apeproperties.h>
|
||||
#include <taglib/apetag.h>
|
||||
#include <taglib/asffile.h>
|
||||
#include <taglib/id3v2tag.h>
|
||||
@@ -198,6 +199,8 @@ namespace lms::metadata
|
||||
throw ParsingFailedException{};
|
||||
}
|
||||
|
||||
computeAudioProperties();
|
||||
|
||||
_propertyMap = _file.file()->properties();
|
||||
|
||||
// Some tags may not be known by TagLib
|
||||
@@ -305,6 +308,28 @@ namespace lms::metadata
|
||||
}
|
||||
}
|
||||
|
||||
void TagLibTagReader::computeAudioProperties()
|
||||
{
|
||||
const TagLib::AudioProperties* properties{ _file.audioProperties() };
|
||||
|
||||
// Common properties
|
||||
_audioProperties.bitrate = static_cast<std::size_t>(properties->bitrate() * 1000);
|
||||
_audioProperties.channelCount = static_cast<std::size_t>(_file.audioProperties()->channels());
|
||||
_audioProperties.duration = std::chrono::milliseconds{ properties->lengthInMilliseconds() };
|
||||
_audioProperties.sampleRate = static_cast<std::size_t>(properties->sampleRate());
|
||||
|
||||
if (const auto * apeProperties{ dynamic_cast<const TagLib::APE::Properties*>(properties) })
|
||||
_audioProperties.bitsPerSample = apeProperties->bitsPerSample();
|
||||
if (const auto * asfProperties{ dynamic_cast<const TagLib::ASF::Properties*>(properties) })
|
||||
_audioProperties.bitsPerSample = asfProperties->bitsPerSample();
|
||||
else if (const auto * flacProperties{ dynamic_cast<const TagLib::FLAC::Properties*>(properties) })
|
||||
_audioProperties.bitsPerSample = flacProperties->bitsPerSample();
|
||||
else if (const auto * mp4Properties{ dynamic_cast<const TagLib::MP4::Properties*>(properties) })
|
||||
_audioProperties.bitsPerSample = mp4Properties->bitsPerSample();
|
||||
else if (const auto * wavePackProperties{ dynamic_cast<const TagLib::WavPack::Properties*>(properties) })
|
||||
_audioProperties.bitsPerSample = wavePackProperties->bitsPerSample();
|
||||
}
|
||||
|
||||
void TagLibTagReader::visitTagValues(TagType tag, TagValueVisitor visitor) const
|
||||
{
|
||||
auto itTagNames{ tagMapping.find(tag) };
|
||||
@@ -362,24 +387,4 @@ namespace lms::metadata
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::chrono::milliseconds TagLibTagReader::getDuration() const
|
||||
{
|
||||
return std::chrono::milliseconds{ _file.audioProperties()->lengthInMilliseconds() };
|
||||
}
|
||||
|
||||
std::size_t TagLibTagReader::getBitrate() const
|
||||
{
|
||||
return static_cast<std::size_t>(_file.audioProperties()->bitrate() * 1000);
|
||||
}
|
||||
|
||||
std::size_t TagLibTagReader::getBitsPerSample() const
|
||||
{
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
std::size_t TagLibTagReader::getSampleRate() const
|
||||
{
|
||||
return static_cast<std::size_t>(_file.audioProperties()->sampleRate());
|
||||
}
|
||||
} // namespace lms::metadata
|
||||
|
||||
@@ -38,17 +38,16 @@ namespace lms::metadata
|
||||
TagLibTagReader(const TagLibTagReader&) = delete;
|
||||
TagLibTagReader& operator=(const TagLibTagReader&) = delete;
|
||||
|
||||
void computeAudioProperties();
|
||||
void visitTagValues(TagType tag, TagValueVisitor visitor) const override;
|
||||
void visitTagValues(std::string_view tag, TagValueVisitor visitor) const override;
|
||||
void visitPerformerTags(PerformerVisitor visitor) const override;
|
||||
bool hasEmbeddedCover() const override { return _hasEmbeddedCover; }
|
||||
|
||||
std::chrono::milliseconds getDuration() const override;
|
||||
std::size_t getBitrate() const override;
|
||||
std::size_t getBitsPerSample() const override;
|
||||
std::size_t getSampleRate() const override;
|
||||
const AudioProperties& getAudioProperties() const override { return _audioProperties; }
|
||||
|
||||
const TagLib::FileRef _file;
|
||||
AudioProperties _audioProperties;
|
||||
TagLib::PropertyMap _propertyMap; // case-insensitive keys
|
||||
bool _hasEmbeddedCover{};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user