Skip to content

Commit 0f60410

Browse files
committed
revamp image read/write
1 parent 7cd71fc commit 0f60410

File tree

5 files changed

+198
-102
lines changed

5 files changed

+198
-102
lines changed

taglib.cpp

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@ TagLib::String to_string(const char *s) {
1414
return TagLib::String(s, TagLib::String::UTF8);
1515
}
1616

17-
// size must come first so that we know how much of data to read
18-
struct ByteData {
19-
unsigned int length;
20-
char *data;
21-
};
22-
2317
__attribute__((export_name("malloc"))) void *exported_malloc(size_t size) {
2418
return malloc(size);
2519
}
@@ -83,30 +77,61 @@ taglib_file_write_tags(const char *filename, const char **tags, uint8_t opts) {
8377
return file.save();
8478
}
8579

86-
__attribute__((export_name("taglib_file_audioproperties"))) int *
80+
struct FileProperties {
81+
unsigned int lengthInMilliseconds;
82+
unsigned int channels;
83+
unsigned int sampleRate;
84+
unsigned int bitrate;
85+
char **imageMetadata;
86+
};
87+
88+
__attribute__((export_name("taglib_file_read_properties"))) FileProperties *
8789
taglib_file_audioproperties(const char *filename) {
8890
TagLib::FileRef file(filename);
8991
if (file.isNull() || !file.audioProperties())
9092
return nullptr;
9193

92-
int *arr = static_cast<int *>(malloc(4 * sizeof(int)));
93-
if (!arr)
94+
FileProperties *props = static_cast<FileProperties *>(malloc(sizeof(FileProperties)));
95+
if (!props)
9496
return nullptr;
9597

9698
auto audioProperties = file.audioProperties();
97-
arr[0] = audioProperties->lengthInMilliseconds();
98-
arr[1] = audioProperties->channels();
99-
arr[2] = audioProperties->sampleRate();
100-
arr[3] = audioProperties->bitrate();
99+
props->lengthInMilliseconds = audioProperties->lengthInMilliseconds();
100+
props->channels = audioProperties->channels();
101+
props->sampleRate = audioProperties->sampleRate();
102+
props->bitrate = audioProperties->bitrate();
101103

102104
const auto &pictures = file.complexProperties("PICTURE");
103-
arr[4] = pictures.isEmpty() ? 0 : 1;
104105

105-
return arr;
106+
props->imageMetadata = nullptr;
107+
if (!pictures.isEmpty()) {
108+
size_t len = pictures.size();
109+
char **imageMetadata = static_cast<char **>(malloc(sizeof(char *) * (len + 1)));
110+
if (imageMetadata) {
111+
size_t i = 0;
112+
for (const auto &p : pictures) {
113+
TagLib::String type = p["pictureType"].toString();
114+
TagLib::String desc = p["description"].toString();
115+
TagLib::String mime = p["mimeType"].toString();
116+
TagLib::String row = type + "\t" + desc + "\t" + mime;
117+
imageMetadata[i] = to_char_array(row);
118+
i++;
119+
}
120+
imageMetadata[len] = nullptr;
121+
props->imageMetadata = imageMetadata;
122+
}
123+
}
124+
125+
return props;
106126
}
107127

128+
struct ByteData {
129+
unsigned int length;
130+
char *data;
131+
};
132+
108133
__attribute__((export_name("taglib_file_read_image"))) ByteData *
109-
taglib_file_read_image(const char *filename) {
134+
taglib_file_read_image(const char *filename, int index) {
110135
TagLib::FileRef file(filename);
111136
if (file.isNull())
112137
return nullptr;
@@ -115,29 +140,24 @@ taglib_file_read_image(const char *filename) {
115140
if (pictures.isEmpty())
116141
return nullptr;
117142

118-
ByteData *bd = (ByteData *)malloc(sizeof(ByteData));
119-
for (const auto &p : pictures) {
120-
const auto pictureType = p["pictureType"].toString();
121-
if (pictureType == "Front Cover") {
122-
auto v = p["data"].toByteVector();
123-
if (!v.isEmpty()) {
124-
bd->length = unsigned(v.size());
125-
bd->data = v.data();
126-
return bd;
127-
}
128-
}
129-
}
143+
if (index < 0 || index >= static_cast<int>(pictures.size()))
144+
return nullptr;
130145

131-
// if we couldn't find a front cover, pick a random cover
132-
auto v = pictures.front()["data"].toByteVector();
146+
ByteData *bd = static_cast<ByteData *>(malloc(sizeof(ByteData)));
147+
if (!bd)
148+
return nullptr;
149+
150+
auto v = pictures[index]["data"].toByteVector();
133151
bd->length = unsigned(v.size());
134152
bd->data = v.data();
135153
return bd;
136154
}
137155

138156
__attribute__((export_name("taglib_file_write_image"))) bool
139-
taglib_file_write_image(const char *filename, const char *mimeType,
140-
const char *buf, unsigned int length) {
157+
taglib_file_write_image(const char *filename, const char *buf,
158+
unsigned int length, int index,
159+
const char *pictureType, const char *description,
160+
const char *mimeType) {
141161
TagLib::FileRef file(filename);
142162
if (file.isNull())
143163
return false;
@@ -149,11 +169,23 @@ taglib_file_write_image(const char *filename, const char *mimeType,
149169
return file.save();
150170
}
151171

152-
file.setComplexProperties("PICTURE",
153-
{{{"data", TagLib::ByteVector(buf, length)},
154-
{"pictureType", "Front Cover"},
155-
{"mimeType", to_string(mimeType)},
156-
{"description", "Added by go-taglib"}}});
172+
auto pictures = file.complexProperties("PICTURE");
173+
174+
TagLib::VariantMap newPicture;
175+
newPicture["data"] = TagLib::ByteVector(buf, length);
176+
newPicture["pictureType"] = to_string(pictureType);
177+
newPicture["description"] = to_string(description);
178+
newPicture["mimeType"] = to_string(mimeType);
179+
180+
// Replace image at index, or append if index is out of range
181+
if (index >= 0 && index < static_cast<int>(pictures.size())) {
182+
pictures[index] = newPicture;
183+
} else {
184+
pictures.append(newPicture);
185+
}
186+
187+
if (!file.setComplexProperties("PICTURE", pictures))
188+
return false;
157189

158190
return file.save();
159191
}

0 commit comments

Comments
 (0)