Tag Parser 12.3.1
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
Loading...
Searching...
No Matches
overallmp3.cpp
Go to the documentation of this file.
1#include "./helper.h"
2#include "./overall.h"
3
4#include "../abstracttrack.h"
5#include "../id3/id3v1tag.h"
6#include "../id3/id3v2tag.h"
8
9#include <regex>
10
21
25void OverallTests::checkMp3Testfile1()
26{
27 CPPUNIT_ASSERT_EQUAL(ContainerFormat::MpegAudioFrames, m_fileInfo.containerFormat());
28 const auto tracks = m_fileInfo.tracks();
29 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
30 for (const auto &track : tracks) {
31 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
32 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Mpeg1Audio, track->format().general);
33 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::Mpeg1Layer3), track->format().sub);
34 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(2), track->channelCount());
35 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(MpegChannelMode::JointStereo), track->channelConfig());
36 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
37 CPPUNIT_ASSERT_EQUAL(3, track->duration().seconds());
38 }
39 const auto tags = m_fileInfo.tags();
40 switch (m_tagStatus) {
42 CPPUNIT_ASSERT(m_fileInfo.id3v1Tag());
43 CPPUNIT_ASSERT_EQUAL(1_st, m_fileInfo.id3v2Tags().size());
44 CPPUNIT_ASSERT_EQUAL(2_st, tags.size());
45 for (const auto &tag : tags) {
46 CPPUNIT_ASSERT_EQUAL(4, tag->value(KnownField::TrackPosition).toPositionInSet().position());
47 CPPUNIT_ASSERT_EQUAL("1984"s, tag->value(KnownField::RecordDate).toString());
48 switch (tag->type()) {
49 case TagType::Id3v1Tag:
50 CPPUNIT_ASSERT_EQUAL("Cohesion"s, tag->value(KnownField::Title).toString());
51 CPPUNIT_ASSERT_EQUAL("Minutemen"s, tag->value(KnownField::Artist).toString());
52 CPPUNIT_ASSERT_EQUAL("Double Nickels On The Dime"s, tag->value(KnownField::Album).toString());
53 CPPUNIT_ASSERT_EQUAL("Punk Rock"s, tag->value(KnownField::Genre).toString());
54 CPPUNIT_ASSERT_EQUAL("ExactAudioCopy v0.95b4"s, tag->value(KnownField::Comment).toString());
55 break;
56 case TagType::Id3v2Tag:
57 CPPUNIT_ASSERT_EQUAL(TagTextEncoding::Utf16LittleEndian, tag->value(KnownField::Title).dataEncoding());
58 CPPUNIT_ASSERT_EQUAL(u"Cohesion"s, tag->value(KnownField::Title).toWString());
59 CPPUNIT_ASSERT_EQUAL("Cohesion"s, tag->value(KnownField::Title).toString(TagTextEncoding::Utf8));
60 CPPUNIT_ASSERT_EQUAL(u"Minutemen"s, tag->value(KnownField::Artist).toWString());
61 CPPUNIT_ASSERT_EQUAL("Minutemen"s, tag->value(KnownField::Artist).toString(TagTextEncoding::Utf8));
62 CPPUNIT_ASSERT_EQUAL(u"Double Nickels On The Dime"s, tag->value(KnownField::Album).toWString());
63 CPPUNIT_ASSERT_EQUAL("Double Nickels On The Dime"s, tag->value(KnownField::Album).toString(TagTextEncoding::Utf8));
64 CPPUNIT_ASSERT_EQUAL(u"Punk Rock"s, tag->value(KnownField::Genre).toWString());
65 CPPUNIT_ASSERT_EQUAL("Punk Rock"s, tag->value(KnownField::Genre).toString(TagTextEncoding::Utf8));
66 CPPUNIT_ASSERT_EQUAL(u"ExactAudioCopy v0.95b4"s, tag->value(KnownField::Comment).toWString());
67 CPPUNIT_ASSERT_EQUAL("ExactAudioCopy v0.95b4"s, tag->value(KnownField::Comment).toString(TagTextEncoding::Utf8));
68 CPPUNIT_ASSERT_EQUAL(43, tag->value(KnownField::TrackPosition).toPositionInSet().total());
69 CPPUNIT_ASSERT(tag->value(KnownField::Length).toTimeSpan().isNull());
70 CPPUNIT_ASSERT(tag->value(KnownField::Lyricist).isEmpty());
71 break;
72 default:;
73 }
74 }
75 break;
77 checkMp3TestMetaData();
78 break;
80 CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
81 }
82
83 auto warningAboutEncoding = false;
84 for (auto &msg : m_diag) {
85 if (msg.message() == "The used encoding is unlikely to be supported by other software.") {
86 CPPUNIT_ASSERT_EQUAL(DiagLevel::Warning, msg.level());
87 warningAboutEncoding = true;
88 msg = DiagMessage(DiagLevel::Information, string(), string());
89 }
90 }
91 const auto encodingWarningExpected
93 CPPUNIT_ASSERT_EQUAL(encodingWarningExpected, warningAboutEncoding);
94 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
95}
96
100void OverallTests::checkMp3Testfile2()
101{
102 CPPUNIT_ASSERT_EQUAL(ContainerFormat::MpegAudioFrames, m_fileInfo.containerFormat());
103 const auto tracks = m_fileInfo.tracks();
104 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
105 for (const auto &track : tracks) {
106 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
107 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Mpeg1Audio, track->format().general);
108 CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::Mpeg1Layer3), track->format().sub);
109 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(2), track->channelCount());
110 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint8_t>(MpegChannelMode::Stereo), track->channelConfig());
111 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
112 CPPUNIT_ASSERT_EQUAL(20, track->duration().seconds());
113 }
114 const auto tags = m_fileInfo.tags();
115 const bool expectId3v24 = m_tagStatus == TagStatus::Original || m_mode & Mp3TestFlags::UseId3v24;
116 switch (m_tagStatus) {
119 CPPUNIT_ASSERT(!m_fileInfo.id3v1Tag());
120 CPPUNIT_ASSERT_EQUAL(1_st, m_fileInfo.id3v2Tags().size());
121 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
122 for (const auto &tag : tags) {
123 if (tag->type() != TagType::Id3v2Tag) {
124 CPPUNIT_FAIL(argsToString("no ", tag->typeName(), " tag expected"));
125 }
126 const auto *const id3v2Tag = static_cast<const Id3v2Tag *>(tag);
127
128 // check values as usual
129 CPPUNIT_ASSERT_EQUAL(expectId3v24 ? 4 : 3, static_cast<int>(id3v2Tag->majorVersion()));
130 CPPUNIT_ASSERT_EQUAL(
131 expectId3v24 ? TagTextEncoding::Utf8 : TagTextEncoding::Utf16LittleEndian, tag->value(KnownField::Title).dataEncoding());
132 CPPUNIT_ASSERT_EQUAL("Infinite (Original Mix)"s, tag->value(KnownField::Title).toString(TagTextEncoding::Utf8));
133 CPPUNIT_ASSERT_EQUAL("B-Front"s, tag->value(KnownField::Artist).toString(TagTextEncoding::Utf8));
134 CPPUNIT_ASSERT_EQUAL("Infinite"s, tag->value(KnownField::Album).toString(TagTextEncoding::Utf8));
135 CPPUNIT_ASSERT_EQUAL(m_tagStatus == TagStatus::TestMetaDataPresent ? "Test"s : "Hardstyle"s,
136 tag->value(KnownField::Genre).toString(TagTextEncoding::Utf8));
137 CPPUNIT_ASSERT_EQUAL("Lavf57.83.100"s, tag->value(KnownField::EncoderSettings).toString(TagTextEncoding::Utf8));
138 CPPUNIT_ASSERT_EQUAL("Roughstate"s, tag->value(KnownField::Publisher).toString(TagTextEncoding::Utf8));
139 CPPUNIT_ASSERT_EQUAL("2017"s, tag->value(KnownField::RecordDate).toString(TagTextEncoding::Utf8));
140 CPPUNIT_ASSERT_EQUAL(1, tag->value(KnownField::TrackPosition).toPositionInSet().position());
141 CPPUNIT_ASSERT(tag->value(KnownField::Length).toTimeSpan().isNull());
142 CPPUNIT_ASSERT(tag->value(KnownField::Lyricist).isEmpty());
143
144 // check additional text frame values
145 const auto &fields = id3v2Tag->fields();
146 auto genreFields = fields.equal_range(Id3v2FrameIds::lGenre);
147 CPPUNIT_ASSERT_MESSAGE("genre field present"s, genreFields.first != genreFields.second);
148 const auto &genreField = genreFields.first->second;
149 const auto &additionalValues = genreField.additionalValues();
150 if (m_tagStatus == TagStatus::TestMetaDataPresent) {
151 CPPUNIT_ASSERT_EQUAL("Test"s, tag->value(KnownField::Genre).toString(TagTextEncoding::Utf8));
152 CPPUNIT_ASSERT_EQUAL(1_st, additionalValues.size());
153 CPPUNIT_ASSERT_EQUAL("Example"s, additionalValues[0].toString(TagTextEncoding::Utf8));
154 } else {
155 CPPUNIT_ASSERT_EQUAL("Hardstyle"s, tag->value(KnownField::Genre).toString(TagTextEncoding::Utf8));
156 CPPUNIT_ASSERT_EQUAL(3_st, additionalValues.size());
157 CPPUNIT_ASSERT_EQUAL("Test"s, additionalValues[0].toString(TagTextEncoding::Utf8));
158 CPPUNIT_ASSERT_EQUAL("Example"s, additionalValues[1].toString(TagTextEncoding::Utf8));
159 CPPUNIT_ASSERT_EQUAL("Hard Dance"s, additionalValues[2].toString(TagTextEncoding::Utf8));
160 }
161 CPPUNIT_ASSERT_MESSAGE("exactly one genre field present"s, ++genreFields.first == genreFields.second);
162
163 // check whether additional text frame values are returned correctly by values()
164 const auto artists = id3v2Tag->values(KnownField::Artist);
165 CPPUNIT_ASSERT_EQUAL(m_tagStatus == TagStatus::TestMetaDataPresent ? 3_st : 2_st, artists.size());
166 CPPUNIT_ASSERT_EQUAL("B-Front"s, artists[0]->toString(TagTextEncoding::Utf8));
167 CPPUNIT_ASSERT_EQUAL("Second Artist Example"s, artists[1]->toString(TagTextEncoding::Utf8));
168 if (m_tagStatus == TagStatus::TestMetaDataPresent) {
169 CPPUNIT_ASSERT_EQUAL("3rd Artist Example"s, artists[2]->toString(TagTextEncoding::Utf8));
170 }
171
172 const auto genres = id3v2Tag->values(KnownField::Genre);
173 if (m_tagStatus == TagStatus::TestMetaDataPresent) {
174 CPPUNIT_ASSERT_EQUAL(2_st, genres.size());
175 CPPUNIT_ASSERT_EQUAL("Test"s, genres[0]->toString(TagTextEncoding::Utf8));
176 CPPUNIT_ASSERT_EQUAL("Example"s, genres[1]->toString(TagTextEncoding::Utf8));
177 } else {
178 CPPUNIT_ASSERT_EQUAL(4_st, genres.size());
179 CPPUNIT_ASSERT_EQUAL("Hardstyle"s, genres[0]->toString(TagTextEncoding::Utf8));
180 CPPUNIT_ASSERT_EQUAL("Test"s, genres[1]->toString(TagTextEncoding::Utf8));
181 CPPUNIT_ASSERT_EQUAL("Example"s, genres[2]->toString(TagTextEncoding::Utf8));
182 CPPUNIT_ASSERT_EQUAL("Hard Dance"s, genres[3]->toString(TagTextEncoding::Utf8));
183 }
184 }
185 break;
187 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
188 }
189
190 if (expectId3v24 || m_tagStatus == TagStatus::Removed) {
191 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
192 return;
193 }
194
195 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Warning);
196 int warningCount = 0;
197 for (const auto &msg : m_diag) {
198 if (msg.level() != DiagLevel::Warning) {
199 continue;
200 }
201 ++warningCount;
202 TESTUTILS_ASSERT_LIKE("context", "(parsing|making) (TPE1|TCON)( frame)?", msg.context());
203 TESTUTILS_ASSERT_LIKE("message",
204 "Multiple strings (found|assigned) .*"
205 "Additional (values \"Second Artist Example\" and \"3rd Artist Example\" are|"
206 "value \"Example\" is) "
207 "supposed to be ignored.",
208 msg.message());
209 }
210 CPPUNIT_ASSERT_EQUAL_MESSAGE("exactly 4 warnings present", 4, warningCount);
211}
212
216void OverallTests::checkMp3TestMetaData()
217{
218 using namespace Mp3TestFlags;
219
220 // check whether tags are assigned according to the current test mode
221 Id3v1Tag *id3v1Tag = nullptr;
222 Id3v2Tag *id3v2Tag = nullptr;
223 if (m_mode & Id3v2AndId3v1) {
224 CPPUNIT_ASSERT(id3v1Tag = m_fileInfo.id3v1Tag());
225 CPPUNIT_ASSERT(id3v2Tag = m_fileInfo.id3v2Tags().at(0).get());
226 } else if (m_mode & Id3v1Only) {
227 CPPUNIT_ASSERT(id3v1Tag = m_fileInfo.id3v1Tag());
228 CPPUNIT_ASSERT(m_fileInfo.id3v2Tags().empty());
229 } else {
230 CPPUNIT_ASSERT(!m_fileInfo.id3v1Tag());
231 CPPUNIT_ASSERT(id3v2Tag = m_fileInfo.id3v2Tags().at(0).get());
232 }
233
234 // check common test meta data
235 if (id3v1Tag) {
236 CPPUNIT_ASSERT_EQUAL(TagTextEncoding::Latin1, id3v1Tag->value(KnownField::Title).dataEncoding());
237 CPPUNIT_ASSERT_EQUAL(m_testTitle, id3v1Tag->value(KnownField::Title));
238 CPPUNIT_ASSERT_EQUAL(m_testCommentWithoutDescription, id3v1Tag->value(KnownField::Comment));
239 CPPUNIT_ASSERT_EQUAL(m_testAlbum, id3v1Tag->value(KnownField::Album));
240 CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), id3v1Tag->value(KnownField::Artist));
241 m_preservedMetaData.pop();
242 }
243 if (id3v2Tag) {
244 const TagValue &titleValue = id3v2Tag->value(KnownField::Title);
245 const TagValue &commentValue = id3v2Tag->value(KnownField::Comment);
246
247 if (m_mode & UseId3v24) {
248 CPPUNIT_ASSERT_EQUAL(TagTextEncoding::Utf8, titleValue.dataEncoding());
249 CPPUNIT_ASSERT_EQUAL(m_testTitle, titleValue);
250 CPPUNIT_ASSERT_EQUAL(m_testComment, commentValue);
251 CPPUNIT_ASSERT_EQUAL(m_testAlbum, id3v2Tag->value(KnownField::Album));
252 CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), id3v2Tag->value(KnownField::Artist));
253 // TODO: check more fields
254 } else {
255 CPPUNIT_ASSERT_EQUAL_MESSAGE("not attempted to use UTF-8 in ID3v2.3", TagTextEncoding::Utf16LittleEndian, titleValue.dataEncoding());
256 CPPUNIT_ASSERT_EQUAL(m_testTitle, titleValue);
257 CPPUNIT_ASSERT_EQUAL_MESSAGE("not attempted to use UTF-8 in ID3v2.3", TagTextEncoding::Utf16LittleEndian, commentValue.dataEncoding());
258 CPPUNIT_ASSERT_EQUAL_MESSAGE(
259 "not attempted to use UTF-8 in ID3v2.3", TagTextEncoding::Utf16LittleEndian, commentValue.descriptionEncoding());
260 CPPUNIT_ASSERT_EQUAL(m_testComment, commentValue);
261 CPPUNIT_ASSERT_EQUAL_MESSAGE(
262 "description is also converted to UTF-16", "s\0o\0m\0e\0 \0d\0e\0s\0c\0r\0i\0p\0t\0i\0\xf3\0n\0"s, commentValue.description());
263 CPPUNIT_ASSERT_EQUAL(m_testAlbum, id3v2Tag->value(KnownField::Album));
264 CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), id3v2Tag->value(KnownField::Artist));
265 // TODO: check more fields
266 }
267
268 m_preservedMetaData.pop();
269 }
270
271 // test ID3v1 specific test meta data
272 if (id3v1Tag) {
273 CPPUNIT_ASSERT_EQUAL(m_testPosition.toPositionInSet().position(), id3v1Tag->value(KnownField::TrackPosition).toPositionInSet().position());
274 }
275 // test ID3v2 specific test meta data
276 if (id3v2Tag) {
277 CPPUNIT_ASSERT_EQUAL(m_testPosition, id3v2Tag->value(KnownField::TrackPosition));
278 CPPUNIT_ASSERT_EQUAL(m_testPosition, id3v2Tag->value(KnownField::DiskPosition));
279 }
280}
281
285void OverallTests::checkMp3PaddingConstraints()
286{
287 using namespace Mp3TestFlags;
288
289 if (!(m_mode & Id3v1Only)) {
290 if (m_mode & PaddingConstraints) {
291 if (m_mode & ForceRewring) {
292 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint64_t>(4096), m_fileInfo.paddingSize());
293 } else {
294 CPPUNIT_ASSERT(m_fileInfo.paddingSize() >= 1024);
295 CPPUNIT_ASSERT(m_fileInfo.paddingSize() <= (4096 + 1024));
296 }
297 }
298 } else {
299 // adding padding is not possible if no ID3v2 tag is present
300 }
301 // TODO: check rewriting behaviour
302}
303
307void OverallTests::setMp3TestMetaData1()
308{
309 using namespace Mp3TestFlags;
310
311 // ensure tags are assigned according to the current test mode
312 Id3v1Tag *id3v1Tag = nullptr;
313 Id3v2Tag *id3v2Tag = nullptr;
314 if (m_mode & Id3v2AndId3v1) {
315 id3v1Tag = m_fileInfo.createId3v1Tag();
316 id3v2Tag = m_fileInfo.createId3v2Tag();
317 } else if (m_mode & Id3v1Only) {
318 id3v1Tag = m_fileInfo.createId3v1Tag();
319 m_fileInfo.removeAllId3v2Tags();
320 } else {
321 m_fileInfo.removeId3v1Tag();
322 id3v2Tag = m_fileInfo.createId3v2Tag();
323 }
324 if (!(m_mode & Id3v1Only) && m_mode & UseId3v24) {
325 id3v2Tag->setVersion(4, 0);
326 }
327
328 // assign some test meta data
329 for (Tag *const tag : initializer_list<Tag *>{ id3v1Tag, id3v2Tag }) {
330 if (!tag) {
331 continue;
332 }
333 tag->setValue(KnownField::Title, m_testTitle);
334 tag->setValue(KnownField::Comment, m_testComment);
335 tag->setValue(KnownField::Album, m_testAlbum);
336 m_preservedMetaData.push(tag->value(KnownField::Artist));
337 tag->setValue(KnownField::TrackPosition, m_testPosition);
338 tag->setValue(KnownField::DiskPosition, m_testPosition);
339 // TODO: set more fields
340 }
341 if (id3v1Tag) {
343 }
344}
345
349void OverallTests::setMp3TestMetaData2()
350{
351 using namespace Mp3TestFlags;
352
353 CPPUNIT_ASSERT_EQUAL(1_st, m_fileInfo.id3v2Tags().size());
354 auto &id3v2Tag(m_fileInfo.id3v2Tags().front());
355 id3v2Tag->setVersion((m_mode & UseId3v24) ? 4 : 3, 0);
356 const auto artists = id3v2Tag->values(KnownField::Artist);
357 CPPUNIT_ASSERT_EQUAL(2_st, artists.size());
358 id3v2Tag->setValues(KnownField::Artist, { *artists[0], *artists[1], TagValue("3rd Artist Example") });
359 id3v2Tag->setValues(KnownField::Genre, { TagValue("Test"), TagValue("Example") });
360}
361
366{
367 cerr << endl << "MP3 parser" << endl;
368 m_fileInfo.setForceFullParse(false);
369 m_tagStatus = TagStatus::Original;
370 parseFile(testFilePath("mtx-test-data/mp3/id3-tag-and-xing-header.mp3"), &OverallTests::checkMp3Testfile1);
371 parseFile(testFilePath("misc/multiple_id3v2_4_values.mp3"), &OverallTests::checkMp3Testfile2);
372}
373
379{
380 // full parse is required to determine padding
381 m_fileInfo.setForceFullParse(true);
382
383 // do the test under different conditions
384 for (m_mode = 0; m_mode != 0x20; ++m_mode) {
385 using namespace Mp3TestFlags;
386
387 // setup test conditions
388 m_fileInfo.setForceRewrite(m_mode & ForceRewring);
389 if (m_mode & UseId3v24) {
390 if (m_mode & Id3v1Only) {
391 continue;
392 }
393 }
394 m_fileInfo.setTagPosition(ElementPosition::Keep);
395 m_fileInfo.setIndexPosition(ElementPosition::Keep);
396 m_fileInfo.setPreferredPadding(m_mode & PaddingConstraints ? 4096 : 0);
397 m_fileInfo.setMinPadding(m_mode & PaddingConstraints ? 1024 : 0);
398 m_fileInfo.setMaxPadding(m_mode & PaddingConstraints ? (4096 + 1024) : numeric_limits<size_t>::max());
399 m_fileInfo.setForceTagPosition(false);
400 m_fileInfo.setForceIndexPosition(false);
401
402 // print test conditions
403 list<string> testConditions;
404 if (m_mode & ForceRewring) {
405 testConditions.emplace_back("forcing rewrite");
406 }
407 if (m_mode & Id3v2AndId3v1) {
408 if (m_mode & RemoveTag) {
409 testConditions.emplace_back("removing tag");
410 } else {
411 testConditions.emplace_back("ID3v1 and ID3v2");
412 }
413 } else if (m_mode & Id3v1Only) {
414 testConditions.emplace_back("ID3v1 only");
415 } else {
416 testConditions.emplace_back("ID3v2 only");
417 }
418 if (m_mode & PaddingConstraints) {
419 testConditions.emplace_back("padding constraints");
420 }
421 if (m_mode & UseId3v24) {
422 testConditions.emplace_back("use ID3v2.4");
423 }
424 cerr << endl << "MP3 maker - testmode " << m_mode << ": " << joinStrings(testConditions, ", ") << endl;
425
426 // do actual tests
427 m_tagStatus = (m_mode & RemoveTag) ? TagStatus::Removed : TagStatus::TestMetaDataPresent;
428 makeFile(workingCopyPath("mtx-test-data/mp3/id3-tag-and-xing-header.mp3"),
429 (m_mode & RemoveTag) ? &OverallTests::removeAllTags : &OverallTests::setMp3TestMetaData1, &OverallTests::checkMp3Testfile1);
430 makeFile(workingCopyPath("misc/multiple_id3v2_4_values.mp3"),
431 (m_mode & RemoveTag) ? &OverallTests::removeAllTags : &OverallTests::setMp3TestMetaData2, &OverallTests::checkMp3Testfile2);
432 }
433}
void testMp3Parsing()
Tests the MP3 parser via MediaFileInfo.
void testMp3Making()
Tests the MP3 maker via MediaFileInfo.
The DiagMessage class holds an information, warning or error gathered during parsing or making.
Definition diagnostics.h:41
const TagValue & value(const IdentifierType &id) const
Returns the value of the field with the specified id.
std::vector< const TagValue * > values(const IdentifierType &id) const
Returns the values of the field with the specified id.
bool setValues(const IdentifierType &id, const std::vector< TagValue > &values)
Assigns the given values to the field with the specified id.
Implementation of TagParser::Tag for ID3v1 tags.
void ensureTextValuesAreProperlyEncoded() override
Ensures the encoding of all assigned text values is supported by the tag by converting the character ...
Definition id3v1tag.cpp:260
const TagValue & value(KnownField value) const override
Returns the value of the specified field.
Definition id3v1tag.cpp:144
Implementation of TagParser::Tag for ID3v2 tags.
void setVersion(std::uint8_t majorVersion, std::uint8_t revisionVersion)
Sets the version to the specified majorVersion and the specified revisionVersion.
Definition id3v2tag.cpp:628
const std::vector< std::unique_ptr< Id3v2Tag > > & id3v2Tags() const
Returns pointers to the assigned ID3v2 tags.
std::uint64_t paddingSize() const
Returns the padding size.
std::vector< AbstractTrack * > tracks() const
Returns the tracks for the current file.
void setForceRewrite(bool forceRewrite)
Sets whether forcing rewriting (when applying changes) is enabled.
bool removeId3v1Tag()
Removes a possibly assigned ID3v1 tag from the current file.
void setMaxPadding(std::size_t maxPadding)
Sets the maximum padding to be written before the data blocks when applying changes.
void setMinPadding(std::size_t minPadding)
Sets the minimum padding to be written before the data blocks when applying changes.
Id3v1Tag * id3v1Tag() const
Returns a pointer to the assigned ID3v1 tag or nullptr if none is assigned.
void setForceTagPosition(bool forceTagPosition)
Sets whether tagPosition() is forced.
Id3v2Tag * createId3v2Tag()
Creates an ID3v2 tag for the current file.
void setForceFullParse(bool forceFullParse)
Sets whether forcing a full parse is enabled.
void tags(std::vector< Tag * > &tags) const
Stores all tags assigned to the current file in the specified vector.
Id3v1Tag * createId3v1Tag()
Creates an ID3v1 tag for the current file.
void setTagPosition(ElementPosition tagPosition)
Sets the position (in the output file) where the tag information is written when applying changes.
bool removeAllId3v2Tags()
Removes all assigned ID3v2 tags from the current file.
ContainerFormat containerFormat() const
Returns the container format of the current file.
void setIndexPosition(ElementPosition indexPosition)
Sets the position (in the output file) where the index is written when applying changes.
void setPreferredPadding(std::size_t preferredPadding)
Sets the padding to be written before the data block when applying changes and the file needs to be r...
void setForceIndexPosition(bool forceTagPosition)
Sets whether indexPosition() is forced.
constexpr std::int32_t position() const
Returns the element position of the current instance.
The TagValue class wraps values of different types.
TagTextEncoding dataEncoding() const
Returns the data encoding.
Definition tagvalue.h:718
PositionInSet toPositionInSet() const
Converts the value of the current TagValue object to its equivalent PositionInSet representation.
Definition tagvalue.cpp:675
TagTextEncoding descriptionEncoding() const
Returns the description encoding.
Definition tagvalue.h:728
const std::string & description() const
Returns the description.
Definition tagvalue.h:561
The Tag class is used to store, read and write tag information.
@ TestMetaDataPresent