@@ -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 *
8789taglib_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