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);
55 stream.read(buffer, 128);
56 if (buffer[0] != 0x54 || buffer[1] != 0x41 || buffer[2] != 0x47) {
60 readValue(m_title, 30, buffer + 3);
61 readValue(m_artist, 30, buffer + 33);
62 readValue(m_album, 30, buffer + 63);
63 readValue(m_year, 4, buffer + 93);
64 if (buffer[125] == 0) {
65 readValue(m_comment, 28, buffer + 97);
68 readValue(m_comment, 30, buffer + 97);
71 readValue(m_comment, buffer[125] == 0 ? 28 : 30, buffer + 97);
72 if (buffer[125] == 0) {
73 m_trackPos.assignPosition(
PositionInSet(*reinterpret_cast<char *>(buffer + 126), 0));
75 m_genre.assignStandardGenreIndex(*reinterpret_cast<unsigned char *>(buffer + 127));
87 static const string context(
"making ID3v1 tag");
92 stream.write(buffer, 3);
95 writeValue(m_title, 30, buffer, stream, diag);
96 writeValue(m_artist, 30, buffer, stream, diag);
97 writeValue(m_album, 30, buffer, stream, diag);
98 writeValue(m_year, 4, buffer, stream, diag);
99 writeValue(m_comment, 28, buffer, stream, diag);
107 if (!m_trackPos.isEmpty()) {
109 const auto position(m_trackPos.toPositionInSet().position());
110 if (position < 0x00 || position > 0xFF) {
111 throw ConversionException();
113 buffer[1] =
static_cast<char>(position);
114 }
catch (
const ConversionException &) {
116 DiagLevel::Warning,
"Track position field can not be set because given value can not be converted appropriately.", context);
122 const auto genreIndex(m_genre.toStandardGenreIndex());
123 if (genreIndex < 0x00 || genreIndex > 0xFF) {
124 throw ConversionException();
126 buffer[2] =
static_cast<char>(genreIndex);
127 }
catch (
const ConversionException &) {
128 diag.emplace_back(DiagLevel::Warning,
129 "Genre field can not be set because given value can not be converted to a standard genre number supported by ID3v1.", context);
132 stream.write(buffer, 3);
154 return TagValue::empty();
190 return setValue(field, value);
197 return !m_title.isEmpty();
199 return !m_artist.isEmpty();
201 return !m_album.isEmpty();
203 return !m_year.isEmpty();
205 return !m_comment.isEmpty();
207 return !m_trackPos.isEmpty();
209 return !m_genre.isEmpty();
215 void Id3v1Tag::removeAllFields()
217 m_title.clearDataAndMetadata();
218 m_artist.clearDataAndMetadata();
219 m_album.clearDataAndMetadata();
220 m_year.clearDataAndMetadata();
221 m_comment.clearDataAndMetadata();
222 m_trackPos.clearDataAndMetadata();
223 m_genre.clearDataAndMetadata();
226 unsigned int Id3v1Tag::fieldCount()
const 228 unsigned int count = 0;
229 for (
const auto &value : { m_title, m_artist, m_album, m_year, m_comment, m_trackPos, m_genre }) {
230 if (!value.isEmpty()) {
253 void Id3v1Tag::ensureTextValuesAreProperlyEncoded()
255 m_title.convertDataEncodingForTag(
this);
256 m_artist.convertDataEncodingForTag(
this);
257 m_album.convertDataEncodingForTag(
this);
258 m_year.convertDataEncodingForTag(
this);
259 m_comment.convertDataEncodingForTag(
this);
260 m_trackPos.convertDataEncodingForTag(
this);
261 m_genre.convertDataEncodingForTag(
this);
267 void Id3v1Tag::readValue(
TagValue &value,
size_t maxLength,
const char *buffer)
269 const char *end = buffer + maxLength - 1;
270 while ((*end == 0x0 || *end ==
' ') && end >= buffer) {
274 value.
assignData(buffer, maxLength, TagDataType::Text, TagTextEncoding::Latin1);
280 void Id3v1Tag::writeValue(
const TagValue &value,
size_t length,
char *buffer, ostream &targetStream, Diagnostics &diag)
282 memset(buffer, 0, length);
284 value.toString().copy(buffer, length);
285 }
catch (
const ConversionException &) {
287 DiagLevel::Warning,
"Field can not be set because given value can not be converted appropriately.",
"making ID3v1 tag field");
289 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.