mirror of
https://github.com/taglib/taglib.git
synced 2026-04-02 12:12:45 -04:00
Use segment title as fallback for returned tag title
Some applications like handbrake store the title only in the segment info element.
This commit is contained in:
@ -91,6 +91,7 @@ std::unique_ptr<EBML::Element> EBML::Element::factory(File &file)
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileData);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSeekID);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkDuration);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkTitle);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSamplingFrequency);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::MkSeekHead);
|
||||
RETURN_ELEMENT_FOR_CASE(Id::VoidElement);
|
||||
|
||||
@ -75,6 +75,7 @@ namespace TagLib::EBML {
|
||||
MkInfo = 0x1549A966,
|
||||
MkTimestampScale = 0x2AD7B1,
|
||||
MkDuration = 0x4489,
|
||||
MkTitle = 0x7BA9,
|
||||
MkTracks = 0x1654AE6B,
|
||||
MkTrackEntry = 0xAE,
|
||||
MkCodecID = 0x86,
|
||||
@ -186,6 +187,7 @@ namespace TagLib::EBML {
|
||||
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
|
||||
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
|
||||
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };
|
||||
|
||||
@ -38,6 +38,7 @@ void EBML::MkInfo::parse(Matroska::Properties *properties)
|
||||
|
||||
unsigned long long timestampScale = 1000000;
|
||||
double duration = 0.0;
|
||||
String title;
|
||||
for(const auto &element : elements) {
|
||||
Id id = element->getId();
|
||||
if (id == Id::MkTimestampScale) {
|
||||
@ -46,8 +47,12 @@ void EBML::MkInfo::parse(Matroska::Properties *properties)
|
||||
else if (id == Id::MkDuration) {
|
||||
duration = element_cast<Id::MkDuration>(element)->getValueAsDouble();
|
||||
}
|
||||
else if (id == Id::MkTitle) {
|
||||
title = element_cast<Id::MkTitle>(element)->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
properties->setLengthInMilliseconds(
|
||||
static_cast<int>(duration * static_cast<double>(timestampScale) / 1000000.0));
|
||||
properties->setTitle(title);
|
||||
}
|
||||
|
||||
@ -108,8 +108,12 @@ Tag *Matroska::File::tag() const
|
||||
|
||||
Matroska::Tag *Matroska::File::tag(bool create) const
|
||||
{
|
||||
if(!d->tag && create)
|
||||
if(!d->tag && create) {
|
||||
d->tag = std::make_unique<Tag>();
|
||||
if(d->properties) {
|
||||
d->tag->setSegmentTitle(d->properties->title());
|
||||
}
|
||||
}
|
||||
return d->tag.get();
|
||||
}
|
||||
|
||||
@ -305,6 +309,9 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle)
|
||||
d->properties = std::make_unique<Properties>(this);
|
||||
segment->parseInfo(d->properties.get());
|
||||
segment->parseTracks(d->properties.get());
|
||||
if(d->tag) {
|
||||
d->tag->setSegmentTitle(d->properties->title());
|
||||
}
|
||||
}
|
||||
|
||||
if(readStyle == AudioProperties::Accurate &&
|
||||
|
||||
@ -40,6 +40,7 @@ public:
|
||||
|
||||
File *file;
|
||||
String codecName;
|
||||
String title;
|
||||
int length { 0 };
|
||||
int bitrate { -1 };
|
||||
int sampleRate { 0 };
|
||||
@ -92,6 +93,11 @@ String Matroska::Properties::codecName() const
|
||||
return d->codecName;
|
||||
}
|
||||
|
||||
String Matroska::Properties::title() const
|
||||
{
|
||||
return d->title;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -125,3 +131,8 @@ void Matroska::Properties::setCodecName(const String &codecName)
|
||||
{
|
||||
d->codecName = codecName;
|
||||
}
|
||||
|
||||
void Matroska::Properties::setTitle(const String& title)
|
||||
{
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
@ -86,6 +86,13 @@ namespace TagLib::Matroska {
|
||||
*/
|
||||
String codecName() const;
|
||||
|
||||
/*!
|
||||
* Returns the general name of the segment.
|
||||
* Some applications store the title of the file here, but players should
|
||||
* prioritize the tag title over the segment title.
|
||||
*/
|
||||
String title() const;
|
||||
|
||||
private:
|
||||
class PropertiesPrivate;
|
||||
friend class EBML::MkInfo;
|
||||
@ -97,6 +104,7 @@ namespace TagLib::Matroska {
|
||||
void setChannels(int channels);
|
||||
void setBitsPerSample(int bitsPerSample);
|
||||
void setCodecName(const String &codecName);
|
||||
void setTitle(const String &title);
|
||||
|
||||
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
|
||||
std::unique_ptr<PropertiesPrivate> d;
|
||||
|
||||
@ -74,6 +74,7 @@ public:
|
||||
|
||||
SimpleTagsList tags;
|
||||
ByteVector data;
|
||||
String segmentTitle;
|
||||
};
|
||||
|
||||
Matroska::Tag::Tag() :
|
||||
@ -115,6 +116,11 @@ const Matroska::SimpleTagsList &Matroska::Tag::simpleTagsList() const
|
||||
return d->tags;
|
||||
}
|
||||
|
||||
void Matroska::Tag::setSegmentTitle(const String& title)
|
||||
{
|
||||
d->segmentTitle = title;
|
||||
}
|
||||
|
||||
void Matroska::Tag::setTitle(const String &s)
|
||||
{
|
||||
d->setTag("TITLE", s);
|
||||
@ -152,7 +158,11 @@ void Matroska::Tag::setTrack(unsigned int i)
|
||||
|
||||
String Matroska::Tag::title() const
|
||||
{
|
||||
return d->getTag("TITLE");
|
||||
String s = d->getTag("TITLE");
|
||||
if(s.isEmpty()) {
|
||||
return d->segmentTitle;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
String Matroska::Tag::artist() const
|
||||
|
||||
@ -98,6 +98,8 @@ namespace TagLib {
|
||||
friend class EBML::MkTags;
|
||||
class TagPrivate;
|
||||
|
||||
void setSegmentTitle(const String &title);
|
||||
|
||||
// private Element implementation
|
||||
ByteVector renderInternal() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user