Skip to content

Commit 47e9b9a

Browse files
complexlogicufleisch
authored andcommitted
Initial matroska support
1 parent 8c7d336 commit 47e9b9a

24 files changed

Lines changed: 1567 additions & 2 deletions

examples/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ include_directories(
22
${CMAKE_CURRENT_SOURCE_DIR}/../taglib
33
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit
44
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
5+
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/matroska
56
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg
67
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
78
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
@@ -38,6 +39,11 @@ target_link_libraries(framelist tag)
3839
add_executable(strip-id3v1 strip-id3v1.cpp)
3940
target_link_libraries(strip-id3v1 tag)
4041

42+
########### next target ###############
43+
44+
add_executable(matroskareader matroskareader.cpp)
45+
target_link_libraries(matroskareader tag)
46+
4147
install(TARGETS tagreader tagreader_c tagwriter framelist strip-id3v1
4248
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
4349
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

examples/matroskareader.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <cstdio>
2+
#include "matroskafile.h"
3+
#include "matroskatag.h"
4+
#include "matroskasimpletag.h"
5+
#include "tstring.h"
6+
#include "tutils.h"
7+
#include "tbytevector.h"
8+
#define GREEN_TEXT(s) "" s ""
9+
#define PRINT_PRETTY(label, value) printf("" GREEN_TEXT(label) ": %s\n", value)
10+
11+
int main(int argc, char *argv[])
12+
{
13+
if (argc != 2) {
14+
printf("Usage: matroskareader FILE\n");
15+
return 1;
16+
}
17+
TagLib::Matroska::File file(argv[1]);
18+
if (!file.isValid()) {
19+
printf("File is not valid\n");
20+
return 1;
21+
}
22+
auto tag = dynamic_cast<TagLib::Matroska::Tag*>(file.tag());
23+
if (!tag) {
24+
printf("File has no tag\n");
25+
return 0;
26+
}
27+
28+
const TagLib::Matroska::SimpleTagsList &list = tag->simpleTagsList();
29+
printf("Found %i tags:\n\n", list.size());
30+
31+
for (TagLib::Matroska::SimpleTag *t : list) {
32+
PRINT_PRETTY("Tag Name", t->name().toCString(true));
33+
34+
TagLib::Matroska::SimpleTagString *tString = nullptr;
35+
TagLib::Matroska::SimpleTagBinary *tBinary = nullptr;
36+
if ((tString = dynamic_cast<TagLib::Matroska::SimpleTagString*>(t)))
37+
PRINT_PRETTY("Tag Value", tString->value().toCString(true));
38+
else if ((tBinary = dynamic_cast<TagLib::Matroska::SimpleTagBinary*>(t)))
39+
PRINT_PRETTY("Tag Value",
40+
TagLib::Utils::formatString("Binary with size %i", tBinary->value().size()).toCString(false)
41+
);
42+
43+
auto targetTypeValue = static_cast<unsigned int>(t->targetTypeValue());
44+
PRINT_PRETTY("Target Type Value",
45+
targetTypeValue == 0 ? "None" : TagLib::Utils::formatString("%i", targetTypeValue).toCString(false)
46+
);
47+
48+
printf("\n");
49+
}
50+
51+
return 0;
52+
}

taglib/CMakeLists.txt

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ set(tag_HDR_DIRS
55
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2
66
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2/frames
77
${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v1
8+
${CMAKE_CURRENT_SOURCE_DIR}/matroska
9+
${CMAKE_CURRENT_SOURCE_DIR}/matroska/ebml
810
)
911
if(WITH_ASF)
1012
set(tag_HDR_DIRS ${tag_HDR_DIRS}
@@ -66,7 +68,7 @@ if(WITH_SHORTEN)
6668
endif()
6769
include_directories(${tag_HDR_DIRS})
6870

69-
set(tag_HDRS
71+
set(tag_PUBLIC_HDRS
7072
tag.h
7173
fileref.h
7274
audioproperties.h
@@ -90,6 +92,9 @@ set(tag_HDRS
9092
toolkit/tpropertymap.h
9193
toolkit/tdebuglistener.h
9294
toolkit/tversionnumber.h
95+
matroska/matroskafile.h
96+
matroska/matroskatag.h
97+
matroska/matroskasimpletag.h
9398
mpeg/mpegfile.h
9499
mpeg/mpegproperties.h
95100
mpeg/mpegheader.h
@@ -221,6 +226,34 @@ if(WITH_SHORTEN)
221226
)
222227
endif()
223228

229+
set(tag_PRIVATE_HDRS
230+
matroska/ebml/ebmlelement.h
231+
matroska/ebml/ebmlmasterelement.h
232+
matroska/ebml/ebmlmksegment.h
233+
matroska/ebml/ebmlmktags.h
234+
matroska/ebml/ebmlstringelement.h
235+
matroska/ebml/ebmluintelement.h
236+
matroska/ebml/ebmlutils.h
237+
)
238+
239+
set(tag_HDRS ${tag_PUBLIC_HDRS} ${tag_PRIVATE_HDRS})
240+
241+
set(matroska_SRCS
242+
matroska/matroskafile.cpp
243+
matroska/matroskasimpletag.cpp
244+
matroska/matroskatag.cpp
245+
)
246+
247+
set(ebml_SRCS
248+
matroska/ebml/ebmlelement.cpp
249+
matroska/ebml/ebmlmasterelement.cpp
250+
matroska/ebml/ebmlmksegment.cpp
251+
matroska/ebml/ebmlmktags.cpp
252+
matroska/ebml/ebmlstringelement.cpp
253+
matroska/ebml/ebmluintelement.cpp
254+
matroska/ebml/ebmlutils.cpp
255+
)
256+
224257
set(mpeg_SRCS
225258
mpeg/mpegfile.cpp
226259
mpeg/mpegproperties.cpp
@@ -429,7 +462,7 @@ set(toolkit_SRCS
429462
)
430463

431464
set(tag_LIB_SRCS
432-
${mpeg_SRCS} ${id3v1_SRCS} ${id3v2_SRCS} ${frames_SRCS} ${ogg_SRCS}
465+
${matroska_SRCS} ${ebml_SRCS} ${mpeg_SRCS} ${id3v1_SRCS} ${id3v2_SRCS} ${frames_SRCS} ${ogg_SRCS}
433466
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
434467
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
435468
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
@@ -458,8 +491,13 @@ set_target_properties(tag PROPERTIES
458491
SOVERSION ${TAGLIB_SOVERSION_MAJOR}
459492
INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}
460493
DEFINE_SYMBOL MAKE_TAGLIB_LIB
494+
<<<<<<< HEAD
461495
INTERFACE_LINK_LIBRARIES "${ZLIB_INTERFACE_LINK_LIBRARIES}"
462496
PUBLIC_HEADER "${tag_HDRS}"
497+
=======
498+
LINK_INTERFACE_LIBRARIES ""
499+
PUBLIC_HEADER "${tag_PUBLIC_HDRS}"
500+
>>>>>>> 770c1012 (Initial matroska support)
463501
)
464502
if(NOT BUILD_SHARED_LIBS)
465503
target_compile_definitions(tag PUBLIC TAGLIB_STATIC)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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 "ebmlelement.h"
22+
#include "ebmlmasterelement.h"
23+
#include "ebmlmksegment.h"
24+
#include "ebmlmktags.h"
25+
#include "ebmlstringelement.h"
26+
#include "ebmluintelement.h"
27+
#include "ebmlutils.h"
28+
#include "tfile.h"
29+
#include "tdebug.h"
30+
#include "tutils.h"
31+
32+
using namespace TagLib;
33+
34+
EBML::Element* EBML::Element::factory(File &file)
35+
{
36+
// Get the element ID
37+
Id id = readId(file);
38+
if (!id) {
39+
debug("Failed to parse EMBL ElementID");
40+
return nullptr;
41+
}
42+
43+
// Get the size length and data length
44+
const auto& [sizeLength, dataSize] = readVINT<offset_t>(file);
45+
if (!sizeLength)
46+
return nullptr;
47+
48+
// Return the subclass
49+
switch(id) {
50+
case EBML_ID_HEAD:
51+
return new Element(id, sizeLength, dataSize);
52+
53+
case EBML_ID_MK_SEGMENT:
54+
return new MkSegment(sizeLength, dataSize);
55+
56+
case EBML_ID_MK_TAGS:
57+
return new MkTags(sizeLength, dataSize);
58+
59+
case EBML_ID_MK_TAG:
60+
case EBML_ID_MK_TAG_TARGETS:
61+
case EBML_ID_MK_SIMPLE_TAG:
62+
return new MasterElement(id, sizeLength, dataSize);
63+
64+
case EBML_ID_MK_TAG_NAME:
65+
case EBML_ID_MK_TAG_STRING:
66+
return new UTF8StringElement(id, sizeLength, dataSize);
67+
68+
case EBML_ID_MK_TAG_LANGUAGE:
69+
return new Latin1StringElement(id, sizeLength, dataSize);
70+
71+
case EBML_ID_MK_TARGET_TYPE_VALUE:
72+
return new UIntElement(id, sizeLength, dataSize);
73+
74+
default:
75+
return new Element(id, sizeLength, dataSize);
76+
}
77+
78+
return nullptr;
79+
}
80+
81+
void EBML::Element::skipData(File &file)
82+
{
83+
file.seek(dataSize, File::Position::Current);
84+
}

taglib/matroska/ebml/ebmlelement.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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_EBMLELEMENT_H
22+
#define TAGLIB_EBMLELEMENT_H
23+
#ifndef DO_NOT_DOCUMENT
24+
25+
#include "tfile.h"
26+
#include "ebmlutils.h"
27+
#include "taglib.h"
28+
29+
namespace TagLib {
30+
namespace EBML {
31+
class Element
32+
{
33+
public:
34+
Element(Id id, int sizeLength, offset_t dataSize)
35+
: id(id), sizeLength(sizeLength), dataSize(dataSize)
36+
{}
37+
virtual ~Element() = default;
38+
virtual bool isMaster() const { return false; }
39+
virtual bool read(File &file) {
40+
skipData(file);
41+
return true;
42+
}
43+
void skipData(File &file);
44+
Id getId() const { return id; }
45+
int getSizeLength() const { return sizeLength; }
46+
int64_t getDataSize() const { return dataSize; }
47+
static Element* factory(File &file);
48+
49+
protected:
50+
Id id;
51+
int sizeLength;
52+
offset_t dataSize;
53+
};
54+
}
55+
}
56+
57+
58+
#endif
59+
#endif
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 "ebmlmasterelement.h"
22+
#include "ebmlutils.h"
23+
#include "matroskafile.h"
24+
25+
#include "tfile.h"
26+
#include "tdebug.h"
27+
#include "tutils.h"
28+
29+
using namespace TagLib;
30+
31+
EBML::MasterElement::~MasterElement()
32+
{
33+
for (auto element : elements)
34+
delete element;
35+
}
36+
37+
bool EBML::MasterElement::read(File &file)
38+
{
39+
offset_t maxOffset = file.tell() + dataSize;
40+
Element *element = nullptr;
41+
while ((element = findNextElement(file, maxOffset))) {
42+
if (!element->read(file))
43+
return false;
44+
elements.append(element);
45+
}
46+
return file.tell() == maxOffset;
47+
}

0 commit comments

Comments
 (0)