4 #include "../exceptions.h" 6 #include <c++utilities/conversion/conversionexception.h> 28 return TagType::Id3v1Tag;
31 const char *Id3v1Tag::typeName()
const 38 return Tag::canEncodingBeUsed(encoding);
49 void Id3v1Tag::parse(std::istream &stream,
bool autoSeek)
52 static const string context(
"parsing ID3v1 tag");
54 stream.seekg(-128, ios_base::end);
57 stream.read(buffer, 128);
60 && buffer[2] == 0x47) {
62 readValue(m_title, 30, buffer + 3);
63 readValue(m_artist, 30, buffer + 33);
64 readValue(m_album, 30, buffer + 63);
65 readValue(m_year, 4, buffer + 93);
66 if(buffer[125] == 0) {
67 readValue(m_comment, 28, buffer + 97);
70 readValue(m_comment, 30, buffer + 97);
73 readValue(m_comment, buffer[125] == 0 ? 28 : 30, buffer + 97);
74 if(buffer[125] == 0) {
75 m_trackPos.assignPosition(
PositionInSet(*reinterpret_cast<char *>(buffer + 126), 0));
77 m_genre.assignStandardGenreIndex(*reinterpret_cast<unsigned char *>(buffer + 127));
79 addNotification(NotificationType::Critical,
"\"TAG\" identifier not found.", context);
91 void Id3v1Tag::parse(std::iostream &stream)
93 return parse(stream,
false);
103 void Id3v1Tag::make(ostream &stream)
106 static const string context(
"making ID3v1 tag");
111 stream.write(buffer, 3);
113 writeValue(m_title, 30, buffer, stream);
114 writeValue(m_artist, 30, buffer, stream);
115 writeValue(m_album, 30, buffer, stream);
116 writeValue(m_year, 4, buffer, stream);
117 writeValue(m_comment, 28, buffer, stream);
124 if(!m_trackPos.isEmpty() && m_trackPos.type() == TagDataType::PositionInSet)
125 buffer[1] = m_trackPos.toPositionInSet().position();
126 }
catch(
const ConversionException &) {
127 addNotification(NotificationType::Warning,
"Track position field can not be set because given value can not be converted appropriately.", context);
131 buffer[2] = m_genre.toStandardGenreIndex();
132 }
catch(
const ConversionException &) {
133 addNotification(NotificationType::Warning,
"Genre field can not be set because given value can not be converted appropriately.", context);
135 stream.write(buffer, 3);
157 return TagValue::empty();
193 return setValue(field, value);
200 return !m_title.isEmpty();
202 return !m_artist.isEmpty();
204 return !m_album.isEmpty();
206 return !m_year.isEmpty();
208 return !m_comment.isEmpty();
210 return !m_trackPos.isEmpty();
212 return !m_genre.isEmpty();
218 void Id3v1Tag::removeAllFields()
220 m_title.clearDataAndMetadata();
221 m_artist.clearDataAndMetadata();
222 m_album.clearDataAndMetadata();
223 m_year.clearDataAndMetadata();
224 m_comment.clearDataAndMetadata();
225 m_trackPos.clearDataAndMetadata();
226 m_genre.clearDataAndMetadata();
229 unsigned int Id3v1Tag::fieldCount()
const 232 for(
const auto &value : {m_title, m_artist, m_album,
233 m_year, m_comment, m_trackPos, m_genre}) {
234 if(!value.isEmpty()) {
257 void Id3v1Tag::ensureTextValuesAreProperlyEncoded()
259 m_title.convertDataEncodingForTag(
this);
260 m_artist.convertDataEncodingForTag(
this);
261 m_album.convertDataEncodingForTag(
this);
262 m_year.convertDataEncodingForTag(
this);
263 m_comment.convertDataEncodingForTag(
this);
264 m_trackPos.convertDataEncodingForTag(
this);
265 m_genre.convertDataEncodingForTag(
this);
271 void Id3v1Tag::readValue(
TagValue &value,
size_t maxLength,
const char *buffer)
273 const char *end = buffer + maxLength - 1;
274 while((*end == 0x0 || *end ==
' ') && end >= buffer) {
278 value.
assignData(buffer, maxLength, TagDataType::Text, TagTextEncoding::Latin1);
285 void Id3v1Tag::writeValue(
const TagValue &value,
size_t length,
char *buffer, ostream &targetStream)
287 memset(buffer, 0, length);
289 value.
toString().copy(buffer, length);
290 }
catch(
const ConversionException &) {
291 addNotification(NotificationType::Warning,
"Field can not be set because given value can not be converted appropriately.",
"making ID3v1 tag field");
293 targetStream.write(buffer, length);