Skip to content

Commit 1d3a375

Browse files
committed
Use segment title as fallback for returned tag title
Some applications like handbrake store the title only in the segment info element.
1 parent 241b3b2 commit 1d3a375

8 files changed

Lines changed: 48 additions & 2 deletions

File tree

taglib/matroska/ebml/ebmlelement.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ std::unique_ptr<EBML::Element> EBML::Element::factory(File &file)
9191
RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileData);
9292
RETURN_ELEMENT_FOR_CASE(Id::MkSeekID);
9393
RETURN_ELEMENT_FOR_CASE(Id::MkDuration);
94+
RETURN_ELEMENT_FOR_CASE(Id::MkTitle);
9495
RETURN_ELEMENT_FOR_CASE(Id::MkSamplingFrequency);
9596
RETURN_ELEMENT_FOR_CASE(Id::MkSeekHead);
9697
RETURN_ELEMENT_FOR_CASE(Id::VoidElement);

taglib/matroska/ebml/ebmlelement.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ namespace TagLib::EBML {
7575
MkInfo = 0x1549A966,
7676
MkTimestampScale = 0x2AD7B1,
7777
MkDuration = 0x4489,
78+
MkTitle = 0x7BA9,
7879
MkTracks = 0x1654AE6B,
7980
MkTrackEntry = 0xAE,
8081
MkCodecID = 0x86,
@@ -186,6 +187,7 @@ namespace TagLib::EBML {
186187
template <> struct GetElementTypeById<Element::Id::MkTagBinary> { using type = BinaryElement; };
187188
template <> struct GetElementTypeById<Element::Id::MkCodecState> { using type = BinaryElement; };
188189
template <> struct GetElementTypeById<Element::Id::MkDuration> { using type = FloatElement; };
190+
template <> struct GetElementTypeById<Element::Id::MkTitle> { using type = UTF8StringElement; };
189191
template <> struct GetElementTypeById<Element::Id::MkSamplingFrequency> { using type = FloatElement; };
190192
template <> struct GetElementTypeById<Element::Id::MkSeekHead> { using type = MkSeekHead; };
191193
template <> struct GetElementTypeById<Element::Id::VoidElement> { using type = VoidElement; };

taglib/matroska/ebml/ebmlmkinfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ void EBML::MkInfo::parse(Matroska::Properties *properties)
3838

3939
unsigned long long timestampScale = 1000000;
4040
double duration = 0.0;
41+
String title;
4142
for(const auto &element : elements) {
4243
Id id = element->getId();
4344
if (id == Id::MkTimestampScale) {
@@ -46,8 +47,12 @@ void EBML::MkInfo::parse(Matroska::Properties *properties)
4647
else if (id == Id::MkDuration) {
4748
duration = element_cast<Id::MkDuration>(element)->getValueAsDouble();
4849
}
50+
else if (id == Id::MkTitle) {
51+
title = element_cast<Id::MkTitle>(element)->getValue();
52+
}
4953
}
5054

5155
properties->setLengthInMilliseconds(
5256
static_cast<int>(duration * static_cast<double>(timestampScale) / 1000000.0));
57+
properties->setTitle(title);
5358
}

taglib/matroska/matroskafile.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,12 @@ Tag *Matroska::File::tag() const
108108

109109
Matroska::Tag *Matroska::File::tag(bool create) const
110110
{
111-
if(!d->tag && create)
111+
if(!d->tag && create) {
112112
d->tag = std::make_unique<Tag>();
113+
if(d->properties) {
114+
d->tag->setSegmentTitle(d->properties->title());
115+
}
116+
}
113117
return d->tag.get();
114118
}
115119

@@ -305,6 +309,9 @@ void Matroska::File::read(bool readProperties, Properties::ReadStyle readStyle)
305309
d->properties = std::make_unique<Properties>(this);
306310
segment->parseInfo(d->properties.get());
307311
segment->parseTracks(d->properties.get());
312+
if(d->tag) {
313+
d->tag->setSegmentTitle(d->properties->title());
314+
}
308315
}
309316

310317
if(readStyle == AudioProperties::Accurate &&

taglib/matroska/matroskaproperties.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Matroska::Properties::PropertiesPrivate
4040

4141
File *file;
4242
String codecName;
43+
String title;
4344
int length { 0 };
4445
int bitrate { -1 };
4546
int sampleRate { 0 };
@@ -92,6 +93,11 @@ String Matroska::Properties::codecName() const
9293
return d->codecName;
9394
}
9495

96+
String Matroska::Properties::title() const
97+
{
98+
return d->title;
99+
}
100+
95101
////////////////////////////////////////////////////////////////////////////////
96102
// private members
97103
////////////////////////////////////////////////////////////////////////////////
@@ -125,3 +131,8 @@ void Matroska::Properties::setCodecName(const String &codecName)
125131
{
126132
d->codecName = codecName;
127133
}
134+
135+
void Matroska::Properties::setTitle(const String& title)
136+
{
137+
d->title = title;
138+
}

taglib/matroska/matroskaproperties.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ namespace TagLib::Matroska {
8686
*/
8787
String codecName() const;
8888

89+
/*!
90+
* Returns the general name of the segment.
91+
* Some applications store the title of the file here, but players should
92+
* prioritize the tag title over the segment title.
93+
*/
94+
String title() const;
95+
8996
private:
9097
class PropertiesPrivate;
9198
friend class EBML::MkInfo;
@@ -97,6 +104,7 @@ namespace TagLib::Matroska {
97104
void setChannels(int channels);
98105
void setBitsPerSample(int bitsPerSample);
99106
void setCodecName(const String &codecName);
107+
void setTitle(const String &title);
100108

101109
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
102110
std::unique_ptr<PropertiesPrivate> d;

taglib/matroska/matroskatag.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Matroska::Tag::TagPrivate
7474

7575
SimpleTagsList tags;
7676
ByteVector data;
77+
String segmentTitle;
7778
};
7879

7980
Matroska::Tag::Tag() :
@@ -115,6 +116,11 @@ const Matroska::SimpleTagsList &Matroska::Tag::simpleTagsList() const
115116
return d->tags;
116117
}
117118

119+
void Matroska::Tag::setSegmentTitle(const String& title)
120+
{
121+
d->segmentTitle = title;
122+
}
123+
118124
void Matroska::Tag::setTitle(const String &s)
119125
{
120126
d->setTag("TITLE", s);
@@ -152,7 +158,11 @@ void Matroska::Tag::setTrack(unsigned int i)
152158

153159
String Matroska::Tag::title() const
154160
{
155-
return d->getTag("TITLE");
161+
String s = d->getTag("TITLE");
162+
if(s.isEmpty()) {
163+
return d->segmentTitle;
164+
}
165+
return s;
156166
}
157167

158168
String Matroska::Tag::artist() const

taglib/matroska/matroskatag.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ namespace TagLib {
9898
friend class EBML::MkTags;
9999
class TagPrivate;
100100

101+
void setSegmentTitle(const String &title);
102+
101103
// private Element implementation
102104
ByteVector renderInternal() override;
103105

0 commit comments

Comments
 (0)