Files
id3_editor/metadata/id3v1.v
T
2026-07-11 20:46:19 +03:00

111 lines
2.9 KiB
V

module metadata
import os { File }
import encoding.iconv
import utils
// Определить кодировку utf-8 или cp-1251
@[inline]
fn decode_bytes(bytes []u8) string {
format := if utils.is_utf8(bytes) { "UTF-8" } else { "CP1251" }
text := iconv.encoding_to_vstring(bytes, format) or { "Can't decode" }
return text
}
// Извлечение метаданных из ID3 v1
pub fn (mut tag ID3v1) get_metadata(last_bytes []u8) {
tag.title = decode_bytes(last_bytes[3..33])
tag.artist = decode_bytes(last_bytes[33..63])
tag.album = decode_bytes(last_bytes[63..92])
tag.year = decode_bytes(last_bytes[93..97])
tag.comment = decode_bytes(last_bytes[97..125])
tag.track = if last_bytes[125] == u8(0) {last_bytes[126].str()} else { "" }
genre := Genre.from(last_bytes[127..128][0]) or { Genre.unknown }
tag.genre = genre.str()}
// Конвертировать ID3 v2.3 в ID3 v1
pub fn (id3v1 ID3v1) to_v23() ID3v23 {
return ID3v23{
tcon: metadata.Frame{
text: id3v1.genre
}
tit2: metadata.Frame{
text: id3v1.title
}
tpe2: metadata.Frame{
text: id3v1.artist
}
talb: metadata.Frame{
text: id3v1.album
}
trck: metadata.Frame{
text: id3v1.track
}
tyer: metadata.Frame{
text: id3v1.year
}
comment: metadata.Frame{
text: id3v1.comment
}
}
}
// По ситуации отрезаем или добиваем нулями
@[inline]
fn cut_or_trim(data string, capacity i8) []u8 {
mut final_data := []u8{len: capacity, init: 0}
bytes_data := iconv.vstring_to_encoding(data, "CP1251") or { []u8{len: capacity} }
diff := capacity - bytes_data.len
if diff > 0 {
for i, d in bytes_data {
final_data[i] = d
}
} else {
final_data = bytes_data.clone()[..capacity]
}
return final_data
}
// Перевести тэг в байты
pub fn (id3v1 ID3v1) to_bytes() []u8 {
mut bytes := []u8{cap: 128}
bytes << "TAG".bytes()
bytes << cut_or_trim(id3v1.title, i8(30))
bytes << cut_or_trim(id3v1.artist, i8(30))
bytes << cut_or_trim(id3v1.album, i8(30))
bytes << cut_or_trim(id3v1.year, i8(4))
bytes << cut_or_trim(id3v1.comment, i8(28))
// bytes << cut_or_trim(id3v1.track, i8(2))
bytes << if id3v1.track.len != 0 { [u8(0), id3v1.track.u8()]} else { [u8(1), u8(0)] }
id_genre := Genre.from(id3v1.genre) or { Genre.unknown }
bytes << u8(id_genre) // cut_or_trim([u8(id_genre)], i8(2))
return bytes
}
// Добавление изменённого тэга
pub fn (id3v1 ID3v1) insert(mut audio File, position i8) []u8 {
bytes_tag := id3v1.to_bytes()
// Уcтановка указателя на последний байт
audio.seek(0, os.SeekMode.end) or { panic(err) }
// Положение указателя
size := audio.tell() or { panic(err) }
// Чтение всех байта, кроме последних 128
mut all_bytes := audio.read_bytes(int(size))#[..position]
all_bytes << bytes_tag
return all_bytes
}