4 #include "../diagnostics.h" 5 #include "../exceptions.h" 7 #include <c++utilities/conversion/conversionexception.h> 30 return TagType::Id3v1Tag;
33 const char *Id3v1Tag::typeName()
const 40 return Tag::canEncodingBeUsed(encoding);
53 stream.read(buffer, 128);
54 if (buffer[0] != 0x54 || buffer[1] != 0x41 || buffer[2] != 0x47) {
58 readValue(m_title, 30, buffer + 3);
59 readValue(m_artist, 30, buffer + 33);
60 readValue(m_album, 30, buffer + 63);
61 readValue(m_year, 4, buffer + 93);
62 if (buffer[125] == 0) {
63 readValue(m_comment, 28, buffer + 97);
66 readValue(m_comment, 30, buffer + 97);
69 readValue(m_comment, buffer[125] == 0 ? 28 : 30, buffer + 97);
70 if (buffer[125] == 0) {
71 m_trackPos.assignPosition(
PositionInSet(*reinterpret_cast<char *>(buffer + 126), 0));
73 m_genre.assignStandardGenreIndex(*reinterpret_cast<unsigned char *>(buffer + 127));
85 static const string context(
"making ID3v1 tag");
90 stream.write(buffer, 3);
93 writeValue(m_title, 30, buffer, stream, diag);
94 writeValue(m_artist, 30, buffer, stream, diag);
95 writeValue(m_album, 30, buffer, stream, diag);
96 writeValue(m_year, 4, buffer, stream, diag);
97 writeValue(m_comment, 28, buffer, stream, diag);
105 if (!m_trackPos.isEmpty()) {
107 const auto position(m_trackPos.toPositionInSet().position());
108 if (position < 0x00 || position > 0xFF) {
109 throw ConversionException();
111 buffer[1] =
static_cast<char>(position);
112 }
catch (
const ConversionException &) {
114 DiagLevel::Warning,
"Track position field can not be set because given value can not be converted appropriately.", context);
120 const auto genreIndex(m_genre.toStandardGenreIndex());
121 if (genreIndex < 0x00 || genreIndex > 0xFF) {
122 throw ConversionException();
124 buffer[2] =
static_cast<char>(genreIndex);
125 }
catch (
const ConversionException &) {
126 diag.emplace_back(DiagLevel::Warning,
127 "Genre field can not be set because given value can not be converted to a standard genre number supported by ID3v1.", context);
130 stream.write(buffer, 3);
152 return TagValue::empty();
188 return setValue(field, value);
195 return !m_title.isEmpty();
197 return !m_artist.isEmpty();
199 return !m_album.isEmpty();
201 return !m_year.isEmpty();
203 return !m_comment.isEmpty();
205 return !m_trackPos.isEmpty();
207 return !m_genre.isEmpty();
213 void Id3v1Tag::removeAllFields()
215 m_title.clearDataAndMetadata();
216 m_artist.clearDataAndMetadata();
217 m_album.clearDataAndMetadata();
218 m_year.clearDataAndMetadata();
219 m_comment.clearDataAndMetadata();
220 m_trackPos.clearDataAndMetadata();
221 m_genre.clearDataAndMetadata();
224 unsigned int Id3v1Tag::fieldCount()
const 226 unsigned int count = 0;
227 for (
const auto &value : { m_title, m_artist, m_album, m_year, m_comment, m_trackPos, m_genre }) {
228 if (!value.isEmpty()) {
251 void Id3v1Tag::ensureTextValuesAreProperlyEncoded()
253 m_title.convertDataEncodingForTag(
this);
254 m_artist.convertDataEncodingForTag(
this);
255 m_album.convertDataEncodingForTag(
this);
256 m_year.convertDataEncodingForTag(
this);
257 m_comment.convertDataEncodingForTag(
this);
258 m_trackPos.convertDataEncodingForTag(
this);
259 m_genre.convertDataEncodingForTag(
this);
265 void Id3v1Tag::readValue(
TagValue &value,
size_t maxLength,
const char *buffer)
267 const char *end = buffer + maxLength - 1;
268 while ((*end == 0x0 || *end ==
' ') && end >= buffer) {
272 value.
assignData(buffer, maxLength, TagDataType::Text, TagTextEncoding::Latin1);
278 void Id3v1Tag::writeValue(
const TagValue &value,
size_t length,
char *buffer, ostream &targetStream, Diagnostics &diag)
280 memset(buffer, 0, length);
282 value.toString().copy(buffer, length);
283 }
catch (
const ConversionException &) {
285 DiagLevel::Warning,
"Field can not be set because given value can not be converted appropriately.",
"making ID3v1 tag field");
287 targetStream.write(buffer, length);
The PositionInSet class describes the position of an element in a set which consists of a certain num...
KnownField
Specifies the field.
The exception that is thrown when the data to be parsed holds no parsable information.
void assignData(const char *data, std::size_t length, TagDataType type=TagDataType::Binary, TagTextEncoding encoding=TagTextEncoding::Latin1)
The TagValue class wraps values of different types.
TagType
Specifies the tag type.
TagTextEncoding
Specifies the text encoding.
Contains all classes and functions of the TagInfo library.
The Diagnostics class is a container for DiagMessage.