Tag Parser  9.1.1
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
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"
7 #include "../mpegaudio/mpegaudioframe.h"
8 
9 #include <regex>
10 
11 namespace Mp3TestFlags {
12 enum TestFlag {
13  ForceRewring = 0x1,
16  Id3v1Only = 0x8,
18  UseId3v24 = 0x10,
19 };
20 }
21 
25 void 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::Year).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;
79  case TagStatus::Removed:
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 
100 void 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) {
117  case TagStatus::Original:
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::RecordLabel).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;
186  case TagStatus::Removed:
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 
216 void 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 
285 void 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 
307 void 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 
349 void 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 }
TagStatus::TestMetaDataPresent
TagParser::Mp4TagAtomIds::Album
Definition: mp4ids.h:86
TagParser::RawDataType::Utf8
Definition: mp4tagfield.h:21
TagParser::Id3v1Tag::value
const TagValue & value(KnownField value) const override
Returns the value of the specified field.
Definition: id3v1tag.cpp:145
TagParser::Id3v1Tag::ensureTextValuesAreProperlyEncoded
void ensureTextValuesAreProperlyEncoded() override
Ensures the encoding of all assigned text values is supported by the tag by converting the character ...
Definition: id3v1tag.cpp:262
Mp3TestFlags::UseId3v24
Definition: overallmp3.cpp:18
TagStatus::Original
TagParser::FieldMapBasedTag::setValues
bool setValues(const IdentifierType &id, const std::vector< TagValue > &values)
Assigns the given values to the field with the specified id.
Definition: fieldbasedtag.h:240
Mp3TestFlags
Definition: overallmp3.cpp:11
TagParser::MediaFileInfo::tracks
std::vector< AbstractTrack * > tracks() const
Returns the tracks for the current file.
Definition: mediafileinfo.cpp:806
TagParser::MediaFileInfo::tags
void tags(std::vector< Tag * > &tags) const
Stores all tags assigned to the current file in the specified vector.
Definition: mediafileinfo.cpp:1447
TagParser::FieldMapBasedTag::value
const TagValue & value(const IdentifierType &id) const
Returns the value of the field with the specified id.
Definition: fieldbasedtag.h:150
TagParser::TagValue::descriptionEncoding
TagTextEncoding descriptionEncoding() const
Returns the description encoding.
Definition: tagvalue.h:613
TagParser::TagValue::toPositionInSet
PositionInSet toPositionInSet() const
Converts the value of the current TagValue object to its equivalent PositionInSet representation.
Definition: tagvalue.cpp:403
TagParser::SubFormats::Mpeg1Layer3
Definition: mediaformat.h:112
TagParser::FieldMapBasedTag::values
std::vector< const TagValue * > values(const IdentifierType &id) const
Returns the values of the field with the specified id.
Definition: fieldbasedtag.h:164
TagParser::Tag
The Tag class is used to store, read and write tag information.
Definition: tag.h:98
TagParser::MediaFileInfo::id3v1Tag
Id3v1Tag * id3v1Tag() const
Returns a pointer to the assigned ID3v1 tag or nullptr if none is assigned.
Definition: mediafileinfo.h:330
TagParser::Mp4TagAtomIds::TrackPosition
Definition: mp4ids.h:116
OverallTests::testMp3Making
void testMp3Making()
Tests the MP3 maker via MediaFileInfo.
Definition: overallmp3.cpp:378
Mp3TestFlags::Id3v2AndId3v1
Definition: overallmp3.cpp:14
overall.h
Mp3TestFlags::ForceRewring
Definition: overallmp3.cpp:13
TagParser::MatroskaIds::Title
Definition: matroskaid.h:54
TagParser::TagValue::description
const std::string & description() const
Returns the description.
Definition: tagvalue.h:511
TagParser::Mpeg4ElementaryStreamObjectIds::Mpeg1Audio
Definition: mp4ids.h:465
TagParser::Id3v2FrameIds::lGenre
Definition: id3v2frameids.h:18
TagParser::Mp4TagAtomIds::Year
Definition: mp4ids.h:122
TagParser::MediaFileInfo::setForceFullParse
void setForceFullParse(bool forceFullParse)
Sets whether forcing a full parse is enabled.
Definition: mediafileinfo.h:455
TagParser::Mp4TagAtomIds::Lyricist
Definition: mp4ids.h:104
TagParser::Mp4TagAtomIds::Genre
Definition: mp4ids.h:101
TagParser::DiagMessage
The DiagMessage class holds an information, warning or error gathered during parsing or making.
Definition: diagnostics.h:41
TagParser::Id3v2Tag
Implementation of TagParser::Tag for ID3v2 tags.
Definition: id3v2tag.h:61
TagParser::Id3v1Tag
Implementation of TagParser::Tag for ID3v1 tags.
Definition: id3v1tag.h:10
Mp3TestFlags::TestFlag
TestFlag
Definition: overallmp3.cpp:12
TagParser::MediaFileInfo::id3v2Tags
const std::vector< std::unique_ptr< Id3v2Tag > > & id3v2Tags() const
Returns pointers to the assigned ID3v2 tags.
Definition: mediafileinfo.h:342
TagParser::PositionInSet::position
constexpr std::int32_t position() const
Returns the element position of the current instance.
Definition: positioninset.h:78
TagParser::MpegAudioFrames
Definition: signature.cpp:91
TagStatus::Removed
TagParser::TagValue
The TagValue class wraps values of different types. It is meant to be assigned to a tag field.
Definition: tagvalue.h:75
Mp3TestFlags::RemoveTag
Definition: overallmp3.cpp:17
OverallTests::testMp3Parsing
void testMp3Parsing()
Tests the MP3 parser via MediaFileInfo.
Definition: overallmp3.cpp:365
TagParser::Mp4TagAtomIds::Artist
Definition: mp4ids.h:88
TagParser::Id3v2Tag::setVersion
void setVersion(std::uint8_t majorVersion, std::uint8_t revisionVersion)
Sets the version to the specified majorVersion and the specified revisionVersion.
Definition: id3v2tag.cpp:503
TagParser::Mp4TagAtomIds::RecordLabel
Definition: mp4ids.h:114
helper.h
TagParser::TagValue::dataEncoding
TagTextEncoding dataEncoding() const
Returns the data encoding.
Definition: tagvalue.h:603
TagParser::MediaFileInfo::containerFormat
ContainerFormat containerFormat() const
Returns the container format of the current file.
Definition: mediafileinfo.h:211
Mp3TestFlags::PaddingConstraints
Definition: overallmp3.cpp:15
TagParser::Mp4TagAtomIds::DiskPosition
Definition: mp4ids.h:96
TagParser::Mp4TagAtomIds::Comment
Definition: mp4ids.h:91
Mp3TestFlags::Id3v1Only
Definition: overallmp3.cpp:16
TagParser::MatroskaTrackType::Audio
Definition: matroskaid.h:403