Tag Parser  8.2.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
mediafileinfo.cpp
Go to the documentation of this file.
1 #include "./helper.h"
2 
3 #include "../abstracttrack.h"
4 #include "../mediafileinfo.h"
5 #include "../tag.h"
6 
7 #include <c++utilities/io/catchiofailure.h>
8 #include <c++utilities/tests/testutils.h>
9 using namespace TestUtilities;
10 
11 #include <cppunit/TestFixture.h>
12 #include <cppunit/extensions/HelperMacros.h>
13 
14 #include <cstdio>
15 
16 using namespace std;
17 using namespace TagParser;
18 using namespace IoUtilities;
19 using namespace TestUtilities::Literals;
20 
21 using namespace CPPUNIT_NS;
22 
27 class MediaFileInfoTests : public TestFixture {
28  CPPUNIT_TEST_SUITE(MediaFileInfoTests);
29  CPPUNIT_TEST(testInitialStatus);
30  CPPUNIT_TEST(testFileSystemMethods);
31  CPPUNIT_TEST(testParsingUnsupportedFile);
32  CPPUNIT_TEST(testFullParseAndFurtherProperties);
33  CPPUNIT_TEST_SUITE_END();
34 
35 public:
36  void setUp();
37  void tearDown();
38 
39  void testInitialStatus();
40  void testFileSystemMethods();
41  void testParsingUnsupportedFile();
42  void testPartialParsingAndTagCreationOfMp4File();
43 
44  void testFullParseAndFurtherProperties();
45 };
46 
48 
50 {
51 }
52 
54 {
55 }
56 
58 {
59  const MediaFileInfo file;
60  CPPUNIT_ASSERT(!file.areTagsSupported());
61  CPPUNIT_ASSERT(!file.areTracksSupported());
62  CPPUNIT_ASSERT(!file.areChaptersSupported());
63  CPPUNIT_ASSERT(!file.areAttachmentsSupported());
64  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.containerParsingStatus());
65  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.tagsParsingStatus());
66  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.tracksParsingStatus());
67  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.chaptersParsingStatus());
68  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.attachmentsParsingStatus());
69  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown, file.containerFormat());
70 }
71 
73 {
74  MediaFileInfo file("/usr/bin/unsupported.bin");
75  CPPUNIT_ASSERT_EQUAL("/usr/bin"s, file.containingDirectory());
76  CPPUNIT_ASSERT_EQUAL("unsupported.bin"s, file.fileName());
77  CPPUNIT_ASSERT_EQUAL("unsupported"s, file.fileName(true));
78  CPPUNIT_ASSERT_EQUAL("/usr/bin/unsupported"s, file.pathWithoutExtension());
79  CPPUNIT_ASSERT_EQUAL(".bin"s, file.extension());
80  CPPUNIT_ASSERT_EQUAL(static_cast<uint64>(0), file.size());
81  file.reportPathChanged(testFilePath("unsupported.bin"));
82  file.open(true);
83  CPPUNIT_ASSERT(file.isOpen());
84  CPPUNIT_ASSERT(file.isReadOnly());
85  CPPUNIT_ASSERT_EQUAL(static_cast<uint64>(41), file.size());
86 }
87 
89 {
90  Diagnostics diag;
91  MediaFileInfo file(testFilePath("unsupported.bin"));
92  file.parseContainerFormat(diag);
93  file.parseTags(diag);
94  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotSupported, file.containerParsingStatus());
95  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotSupported, file.tagsParsingStatus());
96  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.tracksParsingStatus());
97  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.chaptersParsingStatus());
98  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.attachmentsParsingStatus());
99  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Unknown, file.containerFormat());
100  file.invalidate();
101 }
102 
104 {
105  Diagnostics diag;
106  MediaFileInfo file(testFilePath("mtx-test-data/aac/he-aacv2-ps.m4a"));
107  file.open(true);
108  file.parseContainerFormat(diag);
109  file.parseTags(diag);
110  file.parseAttachments(diag);
111  file.close();
112  try {
113  file.parseTracks(diag);
114  CPPUNIT_FAIL("expected std::ios_base::failure because file has been closed");
115  } catch (...) {
116  catchIoFailure();
117  }
118  CPPUNIT_ASSERT(file.areTagsSupported());
119  CPPUNIT_ASSERT(file.areTracksSupported());
120  CPPUNIT_ASSERT(!file.areChaptersSupported());
121  CPPUNIT_ASSERT(!file.areAttachmentsSupported());
122  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.containerParsingStatus());
123  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.tagsParsingStatus());
124  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.tracksParsingStatus());
125  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotParsedYet, file.chaptersParsingStatus());
126  CPPUNIT_ASSERT_EQUAL(ParsingStatus::NotSupported, file.attachmentsParsingStatus());
127  CPPUNIT_ASSERT_EQUAL(0_st, file.trackCount());
128  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, file.containerFormat());
129  CPPUNIT_ASSERT_EQUAL(Diagnostics({ DiagMessage(DiagLevel::Information,
130  "Parsing attachments is not implemented for the container format of the file.", "parsing attachments") }),
131  diag);
132  CPPUNIT_ASSERT_EQUAL(DiagLevel::Information, diag.level());
133 
134  // create/remove tag
135  CPPUNIT_ASSERT_EQUAL(0_st, file.matroskaTags().size());
136  CPPUNIT_ASSERT(!file.id3v1Tag());
137  CPPUNIT_ASSERT_EQUAL(0_st, file.id3v2Tags().size());
138  CPPUNIT_ASSERT(!file.vorbisComment());
139  CPPUNIT_ASSERT(!file.mp4Tag());
140  // NOTE: Maybe it should not be possible to create ID3 tags for MP4 file? It will be ignored anyways.
141  CPPUNIT_ASSERT(file.createId3v1Tag());
142  CPPUNIT_ASSERT(file.id3v1Tag());
143  CPPUNIT_ASSERT(file.createId3v2Tag());
144  CPPUNIT_ASSERT_EQUAL(1_st, file.id3v2Tags().size());
145  CPPUNIT_ASSERT(!file.createVorbisComment());
146  CPPUNIT_ASSERT(!file.vorbisComment());
147  CPPUNIT_ASSERT(!file.removeVorbisComment());
148  file.createAppropriateTags();
149  CPPUNIT_ASSERT(file.mp4Tag());
150 }
151 
153 {
154  Diagnostics diag;
155  MediaFileInfo file(testFilePath("matroska_wave1/test1.mkv"));
156  file.open(true);
157  file.parseEverything(diag);
158  // calling parse methods twice should not do anything (and hence can not fail anymore because the file has already been closed)
159  file.close();
160  file.parseEverything(diag);
161  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.containerParsingStatus());
162  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.tagsParsingStatus());
163  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.tracksParsingStatus());
164  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.chaptersParsingStatus());
165  CPPUNIT_ASSERT_EQUAL(ParsingStatus::Ok, file.attachmentsParsingStatus());
166  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Matroska, file.containerFormat());
167 
168  // general info
169  CPPUNIT_ASSERT(file.container());
170  CPPUNIT_ASSERT(file.areTagsSupported());
171  CPPUNIT_ASSERT(file.hasAnyTag());
172  CPPUNIT_ASSERT_EQUAL(1_st, file.tags().size());
173  CPPUNIT_ASSERT_EQUAL(1_st, file.matroskaTags().size());
174  CPPUNIT_ASSERT(!file.mp4Tag());
175  CPPUNIT_ASSERT(!file.vorbisComment());
176  CPPUNIT_ASSERT(file.areTracksSupported());
177  CPPUNIT_ASSERT_EQUAL(2_st, file.trackCount());
178  CPPUNIT_ASSERT(file.areChaptersSupported());
179  CPPUNIT_ASSERT_EQUAL(0_st, file.chapters().size());
180  CPPUNIT_ASSERT(file.areAttachmentsSupported());
181  CPPUNIT_ASSERT_EQUAL(0_st, file.attachments().size());
182 
183  // notifications
184  CPPUNIT_ASSERT_EQUAL(Diagnostics(), diag);
185  CPPUNIT_ASSERT_EQUAL(DiagLevel::None, diag.level());
186  diag.emplace_back(DiagLevel::Warning, "warning", "test");
187  CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, diag.level());
188  diag.emplace_back(DiagLevel::Critical, "error", "test");
189  CPPUNIT_ASSERT_EQUAL(DiagLevel::Critical, diag.level());
190 
191  // track info / available languages
192  file.tracks().back()->setLanguage("eng");
193  CPPUNIT_ASSERT_EQUAL(unordered_set<string>({ "eng" }), file.availableLanguages());
194  CPPUNIT_ASSERT_EQUAL(unordered_set<string>({}), file.availableLanguages(MediaType::Text));
195  CPPUNIT_ASSERT_EQUAL("ID: 2422994868, type: Video"s, file.tracks()[0]->label());
196  CPPUNIT_ASSERT_EQUAL("ID: 3653291187, type: Audio, language: \"eng\""s, file.tracks()[1]->label());
197  CPPUNIT_ASSERT_EQUAL("MS-MPEG-4-480p / MP3-2ch-eng"s, file.technicalSummary());
198 }
void parseEverything(Diagnostics &diag)
Parses the container format, the tracks and the tag information of the current file.
static std::string containingDirectory(const std::string &path)
Returns the path of the directory containing the given file.
void open(bool readOnly=false)
Opens a std::fstream for the current file.
const std::vector< std::unique_ptr< MatroskaTag > > & matroskaTags() const
Returns pointers to the assigned Matroska tags.
void testParsingUnsupportedFile()
Id3v1Tag * createId3v1Tag()
Creates an ID3v1 tag for the current file.
std::unordered_set< std::string > availableLanguages(TagParser::MediaType type=TagParser::MediaType::Audio) const
Determines the available languages for specified media type (by default MediaType::Audio).
Id3v1Tag * id3v1Tag() const
Returns a pointer to the assigned ID3v1 tag or nullptr if none is assigned.
VorbisComment * createVorbisComment()
Creates a Vorbis comment for the current file.
ParsingStatus tagsParsingStatus() const
Returns an indication whether tag information has been parsed yet.
std::size_t trackCount() const
Returns the number of tracks that could be parsed.
bool hasAnyTag() const
Returns an indication whether a tag of any format is assigned.
ParsingStatus attachmentsParsingStatus() const
Returns whether the attachments have been parsed yet.
const std::vector< std::unique_ptr< Id3v2Tag > > & id3v2Tags() const
Returns pointers to the assigned ID3v2 tags.
ParsingStatus chaptersParsingStatus() const
Returns whether the chapters have been parsed yet.
CPPUNIT_TEST_SUITE_REGISTRATION(MediaFileInfoTests)
void tags(std::vector< Tag * > &tags) const
Stores all tags assigned to the current file in the specified vector.
void testFullParseAndFurtherProperties()
void invalidate()
Invalidates the file info manually.
void testPartialParsingAndTagCreationOfMp4File()
The MediaFileInfo class allows to read and write tag information providing a container/tag format ind...
Definition: mediafileinfo.h:44
ContainerFormat containerFormat() const
Returns the container format of the current file.
void parseAttachments(Diagnostics &diag)
Parses the attachments of the current file.
bool areTagsSupported() const
Returns an indication whether this library supports the tag format of the current file.
VorbisComment * vorbisComment() const
Returns a pointer to the first assigned Vorbis comment or nullptr if none is assigned.
bool removeVorbisComment()
Removes all assigned Vorbis comment from the current file.
bool isReadOnly() const
Indicates whether the last open()/reopen() call was read-only.
Definition: basicfileinfo.h:71
static std::string fileName(const std::string &path, bool cutExtension=false)
Returns the file name of the given file.
void parseTags(Diagnostics &diag)
Parses the tag(s) of the current file.
Contains utility classes helping to read and write streams.
bool areChaptersSupported() const
Returns an indication whether this library supports parsing the chapters of the current file.
DiagLevel level() const
Returns the worst diag level present in the container.
Definition: diagnostics.cpp:53
static std::string extension(const std::string &path)
Returns the extension of the given file.
bool createAppropriateTags(const TagCreationSettings &settings=TagCreationSettings())
Ensures appropriate tags are created according the given settings.
The DiagMessage class holds an information, warning or error gathered during parsing or making.
Definition: diagnostics.h:41
static std::string pathWithoutExtension(const std::string &fullPath)
Returns a copy of the given path without the extension/suffix.
void reportPathChanged(const std::string &newPath)
Call this function to report that the path changed.
std::vector< AbstractChapter * > chapters() const
Returns all chapters assigned to the current file.
void close()
A possibly opened std::fstream will be closed.
void parseTracks(Diagnostics &diag)
Parses the tracks of the current file.
ParsingStatus tracksParsingStatus() const
Returns an indication whether tracks have been parsed yet.
std::string technicalSummary() const
Generates a short technical summary about the file's tracks.
The MediaFileInfoTests tests convenience methods provided by TagParser::MediaFileInfo.
AbstractContainer * container() const
Returns the container for the current file.
void parseContainerFormat(Diagnostics &diag)
Parses the container format of the current file.
Mp4Tag * mp4Tag() const
Returns a pointer to the assigned MP4 tag or nullptr if none is assigned.
ParsingStatus containerParsingStatus() const
Returns an indication whether the container format has been parsed yet.
uint64 size() const
Returns size of the current file in bytes.
bool areAttachmentsSupported() const
Returns an indication whether this library supports attachment format of the current file.
std::vector< AbstractAttachment * > attachments() const
Returns all attachments assigned to the current file.
bool areTracksSupported() const
Returns an indication whether this library supports parsing the tracks information of the current fil...
Id3v2Tag * createId3v2Tag()
Creates an ID3v2 tag for the current file.
bool isOpen() const
Indicates whether a std::fstream is open for the current file.
Definition: basicfileinfo.h:63
std::vector< AbstractTrack * > tracks() const
Returns the tracks for the current file.
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:9
The Diagnostics class is a container for DiagMessage.
Definition: diagnostics.h:156