Skip to content

Commit 6d019a8

Browse files
complexlogicufleisch
authored andcommitted
Initial attachments support
1 parent 6342f00 commit 6d019a8

30 files changed

Lines changed: 983 additions & 158 deletions

examples/matroskareader.cpp

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,42 @@
22
#include "matroskafile.h"
33
#include "matroskatag.h"
44
#include "matroskasimpletag.h"
5+
#include "matroskaattachments.h"
6+
#include "matroskaattachedfile.h"
57
#include "tstring.h"
68
#include "tutils.h"
79
#include "tbytevector.h"
810
#define GREEN_TEXT(s) "" s ""
9-
#define PRINT_PRETTY(label, value) printf("" GREEN_TEXT(label) ": %s\n", value)
11+
#define PRINT_PRETTY(label, value) printf(" " GREEN_TEXT(label) ": %s\n", value)
1012

1113
int main(int argc, char *argv[])
1214
{
13-
if (argc != 2) {
15+
if(argc != 2) {
1416
printf("Usage: matroskareader FILE\n");
1517
return 1;
1618
}
1719
TagLib::Matroska::File file(argv[1]);
18-
if (!file.isValid()) {
20+
if(!file.isValid()) {
1921
printf("File is not valid\n");
2022
return 1;
2123
}
2224
auto tag = dynamic_cast<TagLib::Matroska::Tag*>(file.tag());
23-
if (!tag) {
25+
if(!tag) {
2426
printf("File has no tag\n");
2527
return 0;
2628
}
2729

2830
const TagLib::Matroska::SimpleTagsList &list = tag->simpleTagsList();
29-
printf("Found %i tags:\n\n", list.size());
31+
printf("Found %u tag(s):\n", list.size());
3032

31-
for (TagLib::Matroska::SimpleTag *t : list) {
33+
for(TagLib::Matroska::SimpleTag *t : list) {
3234
PRINT_PRETTY("Tag Name", t->name().toCString(true));
3335

3436
TagLib::Matroska::SimpleTagString *tString = nullptr;
3537
TagLib::Matroska::SimpleTagBinary *tBinary = nullptr;
36-
if ((tString = dynamic_cast<TagLib::Matroska::SimpleTagString*>(t)))
38+
if((tString = dynamic_cast<TagLib::Matroska::SimpleTagString*>(t)))
3739
PRINT_PRETTY("Tag Value", tString->value().toCString(true));
38-
else if ((tBinary = dynamic_cast<TagLib::Matroska::SimpleTagBinary*>(t)))
40+
else if((tBinary = dynamic_cast<TagLib::Matroska::SimpleTagBinary*>(t)))
3941
PRINT_PRETTY("Tag Value",
4042
TagLib::Utils::formatString("Binary with size %i", tBinary->value().size()).toCString(false)
4143
);
@@ -50,5 +52,26 @@ int main(int argc, char *argv[])
5052
printf("\n");
5153
}
5254

55+
TagLib::Matroska::Attachments *attachments = file.attachments();
56+
if(attachments) {
57+
const TagLib::Matroska::Attachments::AttachedFileList &list = attachments->attachedFileList();
58+
printf("Found %u attachment(s)\n", list.size());
59+
for(auto attachedFile : list) {
60+
PRINT_PRETTY("Filename", attachedFile->fileName().toCString(true));
61+
const TagLib::String &description = attachedFile->description();
62+
PRINT_PRETTY("Description", !description.isEmpty() ? description.toCString(true) : "None");
63+
const TagLib::String &mediaType = attachedFile->mediaType();
64+
PRINT_PRETTY("Media Type", !mediaType.isEmpty() ? mediaType.toCString(false) : "None");
65+
PRINT_PRETTY("Data Size",
66+
TagLib::Utils::formatString("%u byte(s)",attachedFile->data().size()).toCString(false)
67+
);
68+
PRINT_PRETTY("UID",
69+
TagLib::Utils::formatString("%llu",attachedFile->uid()).toCString(false)
70+
);
71+
}
72+
}
73+
else
74+
printf("File has no attachments\n");
75+
5376
return 0;
5477
}

examples/matroskawriter.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22
#include "matroskafile.h"
33
#include "matroskatag.h"
44
#include "matroskasimpletag.h"
5+
#include "matroskaattachments.h"
6+
#include "matroskaattachedfile.h"
7+
#include "tfilestream.h"
58
#include "tstring.h"
69
#include "tutils.h"
710

811
int main(int argc, char *argv[])
912
{
10-
if (argc != 2) {
11-
printf("Usage: matroskawriter FILE\n");
13+
if(argc != 3) {
14+
printf("Usage: matroskawriter FILE ARTWORK\n");
1215
return 1;
1316
}
1417
TagLib::Matroska::File file(argv[1]);
15-
if (!file.isValid()) {
18+
if(!file.isValid()) {
1619
printf("File is not valid\n");
1720
return 1;
1821
}
@@ -31,6 +34,19 @@ int main(int argc, char *argv[])
3134
simpleTag->setTargetTypeValue(TagLib::Matroska::SimpleTag::TargetTypeValue::Album);
3235
simpleTag->setValue("Test Value 2");
3336
tag->addSimpleTag(simpleTag);
37+
tag->setTitle("Test title");
38+
tag->setArtist("Test artist");
39+
tag->setYear(1969);
40+
41+
TagLib::FileStream image(argv[2]);
42+
auto data = image.readBlock(image.length());
43+
auto attachments = file.attachments(true);
44+
auto attachedFile = new TagLib::Matroska::AttachedFile();
45+
attachedFile->setFileName("cover.jpg");
46+
attachedFile->setMediaType("image/jpeg");
47+
attachedFile->setData(data);
48+
//attachedFile->setUID(5081000385627515072ull);
49+
attachments->addAttachedFile(attachedFile);
3450

3551
file.save();
3652

taglib/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,12 @@ set(tag_PUBLIC_HDRS
9292
toolkit/tpropertymap.h
9393
toolkit/tdebuglistener.h
9494
toolkit/tversionnumber.h
95+
matroska/matroskaattachedfile.h
96+
matroska/matroskaattachments.h
9597
matroska/matroskafile.h
9698
matroska/matroskatag.h
9799
matroska/matroskasimpletag.h
100+
matroska/matroskaelement.h
98101
mpeg/mpegfile.h
99102
mpeg/mpegproperties.h
100103
mpeg/mpegheader.h
@@ -227,8 +230,10 @@ if(WITH_SHORTEN)
227230
endif()
228231

229232
set(tag_PRIVATE_HDRS
233+
matroska/ebml/ebmlbinaryelement.h
230234
matroska/ebml/ebmlelement.h
231235
matroska/ebml/ebmlmasterelement.h
236+
matroska/ebml/ebmlmkattachments.h
232237
matroska/ebml/ebmlmksegment.h
233238
matroska/ebml/ebmlmktags.h
234239
matroska/ebml/ebmlstringelement.h
@@ -239,14 +244,19 @@ set(tag_PRIVATE_HDRS
239244
set(tag_HDRS ${tag_PUBLIC_HDRS} ${tag_PRIVATE_HDRS})
240245

241246
set(matroska_SRCS
247+
matroska/matroskaattachedfile.cpp
248+
matroska/matroskaattachments.cpp
249+
matroska/matroskaelement.cpp
242250
matroska/matroskafile.cpp
243251
matroska/matroskasimpletag.cpp
244252
matroska/matroskatag.cpp
245253
)
246254

247255
set(ebml_SRCS
256+
matroska/ebml/ebmlbinaryelement.cpp
248257
matroska/ebml/ebmlelement.cpp
249258
matroska/ebml/ebmlmasterelement.cpp
259+
matroska/ebml/ebmlmkattachments.cpp
250260
matroska/ebml/ebmlmksegment.cpp
251261
matroska/ebml/ebmlmktags.cpp
252262
matroska/ebml/ebmlstringelement.cpp
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/***************************************************************************
2+
* This library is free software; you can redistribute it and/or modify *
3+
* it under the terms of the GNU Lesser General Public License version *
4+
* 2.1 as published by the Free Software Foundation. *
5+
* *
6+
* This library is distributed in the hope that it will be useful, but *
7+
* WITHOUT ANY WARRANTY; without even the implied warranty of *
8+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
9+
* Lesser General Public License for more details. *
10+
* *
11+
* You should have received a copy of the GNU Lesser General Public *
12+
* License along with this library; if not, write to the Free Software *
13+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
14+
* 02110-1301 USA *
15+
* *
16+
* Alternatively, this file is available under the Mozilla Public *
17+
* License Version 1.1. You may obtain a copy of the License at *
18+
* http://www.mozilla.org/MPL/ *
19+
***************************************************************************/
20+
21+
#include "ebmlbinaryelement.h"
22+
#include "tfile.h"
23+
#include "tbytevector.h"
24+
#include "tdebug.h"
25+
#include <string>
26+
27+
using namespace TagLib;
28+
29+
bool EBML::BinaryElement::read(TagLib::File &file)
30+
{
31+
value = file.readBlock(dataSize);
32+
if(value.size() != dataSize) {
33+
debug("Failed to read binary element");
34+
return false;
35+
}
36+
return true;
37+
}
38+
39+
ByteVector EBML::BinaryElement::render()
40+
{
41+
ByteVector buffer = renderId();
42+
dataSize = value.size();
43+
buffer.append(renderVINT(dataSize, 0));
44+
buffer.append(value);
45+
return buffer;
46+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/***************************************************************************
2+
* This library is free software; you can redistribute it and/or modify *
3+
* it under the terms of the GNU Lesser General Public License version *
4+
* 2.1 as published by the Free Software Foundation. *
5+
* *
6+
* This library is distributed in the hope that it will be useful, but *
7+
* WITHOUT ANY WARRANTY; without even the implied warranty of *
8+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
9+
* Lesser General Public License for more details. *
10+
* *
11+
* You should have received a copy of the GNU Lesser General Public *
12+
* License along with this library; if not, write to the Free Software *
13+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
14+
* 02110-1301 USA *
15+
* *
16+
* Alternatively, this file is available under the Mozilla Public *
17+
* License Version 1.1. You may obtain a copy of the License at *
18+
* http://www.mozilla.org/MPL/ *
19+
***************************************************************************/
20+
21+
#ifndef TAGLIB_EBMLBINARYELEMENT_H
22+
#define TAGLIB_EBMLBINARYELEMENT_H
23+
#ifndef DO_NOT_DOCUMENT
24+
25+
#include <cstdint>
26+
#include "ebmlelement.h"
27+
#include "ebmlutils.h"
28+
#include "tbytevector.h"
29+
30+
namespace TagLib {
31+
class File;
32+
namespace EBML {
33+
class BinaryElement : public Element
34+
{
35+
public:
36+
BinaryElement(Id id, int sizeLength, offset_t dataSize)
37+
: Element(id, sizeLength, dataSize)
38+
{}
39+
BinaryElement(Id id)
40+
: Element(id, 0, 0)
41+
{}
42+
const ByteVector& getValue() const { return value; }
43+
void setValue(const ByteVector &value) { this->value = value; }
44+
bool read(File &file) override;
45+
ByteVector render() override;
46+
47+
private:
48+
ByteVector value;
49+
};
50+
}
51+
}
52+
53+
#endif
54+
#endif

taglib/matroska/ebml/ebmlelement.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020

2121
#include "ebmlelement.h"
2222
#include "ebmlmasterelement.h"
23+
#include "ebmlbinaryelement.h"
2324
#include "ebmlmksegment.h"
2425
#include "ebmlmktags.h"
26+
#include "ebmlmkattachments.h"
2527
#include "ebmlstringelement.h"
2628
#include "ebmluintelement.h"
2729
#include "ebmlutils.h"
@@ -36,15 +38,16 @@ using namespace TagLib;
3638
EBML::Element* EBML::Element::factory(File &file)
3739
{
3840
// Get the element ID
41+
offset_t offset = file.tell();
3942
Id id = readId(file);
40-
if (!id) {
43+
if(!id) {
4144
debug("Failed to parse EMBL ElementID");
4245
return nullptr;
4346
}
4447

4548
// Get the size length and data length
4649
const auto& [sizeLength, dataSize] = readVINT<offset_t>(file);
47-
if (!sizeLength)
50+
if(!sizeLength)
4851
return nullptr;
4952

5053
// Return the subclass
@@ -53,26 +56,37 @@ EBML::Element* EBML::Element::factory(File &file)
5356
return new Element(id, sizeLength, dataSize);
5457

5558
case ElementIDs::MkSegment:
56-
return new MkSegment(sizeLength, dataSize);
59+
return new MkSegment(sizeLength, dataSize, offset);
5760

5861
case ElementIDs::MkTags:
59-
return new MkTags(sizeLength, dataSize);
62+
return new MkTags(sizeLength, dataSize, offset);
63+
64+
case ElementIDs::MkAttachments:
65+
return new MkAttachments(sizeLength, dataSize, offset);
6066

6167
case ElementIDs::MkTag:
6268
case ElementIDs::MkTagTargets:
6369
case ElementIDs::MkSimpleTag:
64-
return new MasterElement(id, sizeLength, dataSize);
70+
case ElementIDs::MkAttachedFile:
71+
return new MasterElement(id, sizeLength, dataSize, offset);
6572

6673
case ElementIDs::MkTagName:
6774
case ElementIDs::MkTagString:
75+
case ElementIDs::MkAttachedFileName:
76+
case ElementIDs::MkAttachedFileDescription:
6877
return new UTF8StringElement(id, sizeLength, dataSize);
6978

7079
case ElementIDs::MkTagLanguage:
80+
case ElementIDs::MkAttachedFileMediaType:
7181
return new Latin1StringElement(id, sizeLength, dataSize);
7282

7383
case ElementIDs::MkTagTargetTypeValue:
84+
case ElementIDs::MkAttachedFileUID:
7485
return new UIntElement(id, sizeLength, dataSize);
7586

87+
case ElementIDs::MkAttachedFileData:
88+
return new BinaryElement(id, sizeLength, dataSize);
89+
7690
default:
7791
return new Element(id, sizeLength, dataSize);
7892
}
@@ -83,16 +97,16 @@ EBML::Element* EBML::Element::factory(File &file)
8397
EBML::Element::Id EBML::Element::readId(File &file)
8498
{
8599
auto buffer = file.readBlock(1);
86-
if (buffer.size() != 1) {
100+
if(buffer.size() != 1) {
87101
debug("Failed to read VINT size");
88102
return 0;
89103
}
90104
unsigned int nb_bytes = VINTSizeLength<4>(*buffer.begin());
91-
if (!nb_bytes)
105+
if(!nb_bytes)
92106
return 0;
93-
if (nb_bytes > 1)
107+
if(nb_bytes > 1)
94108
buffer.append(file.readBlock(nb_bytes - 1));
95-
if (buffer.size() != nb_bytes) {
109+
if(buffer.size() != nb_bytes) {
96110
debug("Failed to read VINT data");
97111
return 0;
98112
}

0 commit comments

Comments
 (0)