Update code for checking input parameter
[platform/core/api/metadata-editor.git] / src / metadata_editor.cpp
1 /*
2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <metadata_editor.h>
18 #include <metadata_editor_private.h>
19 #include <aul.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <glib.h>
25
26 static int __ID3_getTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value);
27 static int __ID3_setTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value);
28 static int __ID3_getFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value);
29 static int __ID3_setFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value);
30 static int __ID3_getNumberOfPictures(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value);
31 static int __ID3_getLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value);
32 static int __ID3_setTwixCommentFrame(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* value);
33 static int __ID3_setLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* value);
34 static int __MP4_getStringItem(metadata_editor_s* _metadata, const char* itemname, char** value);
35 static int __MP4_getIntegerItem(metadata_editor_s* _metadata, const char* itemname, char** value);
36 static int __MP4_updateStringItem(metadata_editor_s* _metadata, const char* itemname, const char* value);
37 static int __MP4_updateIntegerItem(metadata_editor_s* _metadata, const char* itemname, const char* value);
38 static int __MP4_getNumberOfPictures(metadata_editor_s* _metadata, char** value);
39 #if 0
40 static int __xiph_getFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, char** value);
41 static int __xiph_updateFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, const char* value);
42 static int __FLAC_getNumberOfPictures(metadata_editor_s* _metadata, char** value);
43 #endif
44 typedef enum {
45         METADATA_EDITOR_FORMAT_MP3 = 0,                 /**< MP3 File */
46         METADATA_EDITOR_FORMAT_MP4,                             /**< MP4 File */
47         METADATA_EDITOR_FORMAT_FLAC,                            /**< FLAC File */
48         METADATA_EDITOR_FORMAT_OGG_VORBIS,                      /**< Vorbis Audio in Ogg container */
49         METADATA_EDITOR_FORMAT_OGG_FLAC,                        /**< FLAC Audio in Ogg container */
50         METADATA_EDITOR_FORMAT_WAV,                             /**< WAV file */
51         METADATA_EDITOR_FORMAT_NOTYPE = 0xFF            /**< Error type. File type is not correct or not specified */
52 } metadata_editor_format_e;
53
54 static int __check_metadata_parameter(metadata_editor_s *metadata)
55 {
56         metadata_editor_retvm_if(!metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
57         metadata_editor_retvm_if(!metadata->file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
58         metadata_editor_retvm_if(!metadata->isOpen, METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File does not exist or you have no rights to open it");
59
60         return METADATA_EDITOR_ERROR_NONE;
61 }
62
63 static int __check_metadata_set_parameter(metadata_editor_s *metadata)
64 {
65         int ret = METADATA_EDITOR_ERROR_NONE;
66
67         ret = __check_metadata_parameter(metadata);
68         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_parameter");
69
70         metadata_editor_retvm_if(metadata->isReadOnly, METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File is readonly. Unable to modify");
71
72         return METADATA_EDITOR_ERROR_NONE;
73 }
74
75 static int __check_metadata_get_parameter(metadata_editor_s *metadata, char **value)
76 {
77         int ret = METADATA_EDITOR_ERROR_NONE;
78
79         ret = __check_metadata_parameter(metadata);
80         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_parameter");
81
82         metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
83
84         return METADATA_EDITOR_ERROR_NONE;
85 }
86
87 // *** This is an auxiliary function that is used to get the frame value *** //
88 // *** It operates with frames that exists both in ID3v1 and ID3v2 tags *** //
89 static int __ID3_getTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value) {
90         int ret = METADATA_EDITOR_ERROR_NONE;
91
92         ret = __check_metadata_get_parameter(_metadata, value);
93         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
94         metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
95
96         *value = NULL;
97
98         // Check if the frame is empty (nothing to read) or ID3v2 tag does not exist
99         if (!tag2 || tag2->frameListMap()[frameID].isEmpty()) {
100                 metadata_editor_info("The frame %s in ID3v2 tag is empty", frameID);
101                 // Check if the tag ID3v1 is also empty or does not exist
102                 if (!tag1 || tag1->isEmpty()) {
103                         metadata_editor_info("The frame %s in ID3v1 tag is empty as well", frameID);
104                         return METADATA_EDITOR_ERROR_NONE;
105                 } else {        // if not - read the frame you need there
106                         metadata_editor_info("Reading data from ID3v1 tag");
107
108                         TagLib::String str;
109                         uint length;
110                         bool found = false;
111
112                         if (!strcmp(frameID, "TPE1")) {                 /* artist */
113                                 str = tag1->artist();
114                                 found = true;
115                         } else if (!strcmp(frameID, "TALB")) {  /* album */
116                                 str = tag1->album();
117                                 found = true;
118                         } else if (!strcmp(frameID, "COMM")) {  /* comment */
119                                 str = tag1->comment();
120                                 found = true;
121                         } else if (!strcmp(frameID, "TCON")) {  /* genre */
122                                 str = tag1->genre();
123                                 found = true;
124                         } else if (!strcmp(frameID, "TIT2")) {          /* title */
125                                 str = tag1->title();
126                                 found = true;
127                         }
128
129                         /* Check if we have already found the frame */
130                         if (found) {
131                                 bool isUTF = false;
132                                 if (!str.isLatin1()) isUTF = true;
133                                 metadata_editor_info("String is %sUTF", (isUTF ? "" : "not "));
134                                 length = strlen(str.toCString(isUTF));
135                                 metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
136                                 *value = strndup(str.toCString(isUTF), length);
137                                 return METADATA_EDITOR_ERROR_NONE;
138                         }
139
140                         char buf[META_MAX_BUF_LEN] = {0, };
141
142                         if (!strcmp(frameID, "TRCK")) {                 /* track */
143                                 snprintf(buf, META_MAX_BUF_LEN, "%u", tag1->track());
144                                 found = true;
145                         } else if (!strcmp(frameID, "TDRC")) {  /* data (year) */
146                                 snprintf(buf, META_MAX_BUF_LEN, "%u", tag1->year());
147                                 found = true;
148                         }
149
150                         if (found) {
151                                 length = strlen(buf);
152                                 metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
153                                 *value = strndup(buf, length);
154                                 return METADATA_EDITOR_ERROR_NONE;
155                         }
156
157                         /* The desired frame was not found */
158                         return METADATA_EDITOR_ERROR_OPERATION_FAILED;
159                 }
160         } else {                // or frame has data to read
161                 metadata_editor_info("The frame %s exists in ID3v2 tag", frameID);
162
163                 // This string is used to copy the value in the frame
164                 TagLib::String str = tag2->frameListMap()[frameID][0]->toString();
165                 bool isUTF = false;
166
167                 if (!str.isLatin1()) isUTF = true;
168                 metadata_editor_info("String is %sUTF", (isUTF ? "" : "not "));
169                 uint length = strlen(str.toCString(isUTF));
170                 metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
171
172                 *value = strndup(str.toCString(isUTF), length);
173
174                 return METADATA_EDITOR_ERROR_NONE;
175         }
176 }
177
178 // *** This is an auxiliary function that is used to write the new value to the frame *** //
179 // *** It operates with frames that exists both in ID3v1 and ID3v2 tags *** //
180 static int __ID3_setTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value) {
181         int ret = METADATA_EDITOR_ERROR_NONE;
182
183         ret = __check_metadata_set_parameter(_metadata);
184         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
185         metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
186         metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
187
188         // If the pointer is NULL or c-string is empty - handle as request for deletion
189         if (!value || (*value == '\0')) {
190                 metadata_editor_info("Request for frame %s deletion", frameID);
191                 tag2->removeFrames(frameID);
192                 if (tag1 && !tag1->isEmpty()) {
193                         if (!strcmp(frameID, "TPE1"))
194                                 tag1->setArtist("");
195                         else if (!strcmp(frameID, "TALB"))
196                                 tag1->setAlbum("");
197                         else if (!strcmp(frameID, "TCON"))
198                                 tag1->setGenre("");
199                         else if (!strcmp(frameID, "TIT2"))
200                                 tag1->setTitle("");
201                         else if (!strcmp(frameID, "TRCK"))
202                                 tag1->setTrack(0);
203                         else if (!strcmp(frameID, "TDRC"))
204                                 tag1->setYear(0);
205                 }
206
207                 return METADATA_EDITOR_ERROR_NONE;
208         }
209
210         // Check if the frame is empty (must create the frame before writing the data)
211         if (tag2->frameListMap()[frameID].isEmpty()) {
212                 metadata_editor_info("The frame %s does not exist. Creating", frameID);
213                 // This is a common frame type for textural frames except comment frame
214                 TagLib::ID3v2::TextIdentificationFrame* fr = new TagLib::ID3v2::TextIdentificationFrame(frameID);
215                 metadata_editor_retvm_if(fr == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
216
217                 fr->setTextEncoding(TagLib::String::UTF8);
218                 fr->setText(TagLib::String(value, TagLib::String::UTF8));
219                 tag2->addFrame(fr);
220         } else {                // if not - just modify the data in the existing frame
221                 metadata_editor_info("The frame %s exists. Changing", frameID);
222                 tag2->frameListMap()[frameID][0]->setText(TagLib::String(value, TagLib::String::UTF8));
223         }
224
225         if (tag1 && !tag1->isEmpty()) {                         // Check if ID3v1 tag exists. Must copy data if yes.
226                 metadata_editor_info("ID3v1 tag also exists. Copying frame");
227                 if (!strcmp(frameID, "TPE1"))
228                                 tag1->setArtist(value);
229                 else if (!strcmp(frameID, "TALB"))
230                                 tag1->setAlbum(value);
231                 else if (!strcmp(frameID, "TCON"))              // Genre in ID3v1 is enumeration, so can not write it with "value"
232                                 tag1->setGenre("");
233                 else if (!strcmp(frameID, "TIT2"))
234                                 tag1->setTitle(value);
235                 else if (!strcmp(frameID, "TRCK"))
236                                 tag1->setTrack(atoi(value));
237                 else if (!strcmp(frameID, "TDRC"))
238                                 tag1->setYear(atoi(value));
239         }
240
241         return METADATA_EDITOR_ERROR_NONE;
242 }
243
244 // *** This function reads frames that exist only in ID3v2 tag *** //
245 static int __ID3_getFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value) {
246         int ret = METADATA_EDITOR_ERROR_NONE;
247
248         ret = __check_metadata_get_parameter(_metadata, value);
249         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
250         metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
251
252         *value = NULL;
253
254         // Check if the frame is empty (nothing to read) or ID3v2 tag does not exist
255         metadata_editor_retvm_if(!tag2 || tag2->frameListMap()[frameID].isEmpty(), METADATA_EDITOR_ERROR_NONE, "The frame %s does not exist", frameID);
256
257         metadata_editor_info("The frame %s exists", frameID);
258         // This string is used to copy the value in the frame
259         TagLib::String str = tag2->frameListMap()[frameID][0]->toString();
260         bool isUTF = false;
261         if (!str.isLatin1()) isUTF = true;
262         metadata_editor_info("String is %sUTF", (isUTF ? "" : "not "));
263
264         uint length = strlen(str.toCString(isUTF));
265         metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
266
267         *value = strndup(str.toCString(isUTF), length);
268
269         return METADATA_EDITOR_ERROR_NONE;
270 }
271
272 // *** This function writes frames that exist only in ID3v2 tag *** //
273 static int __ID3_setFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value) {
274         int ret = METADATA_EDITOR_ERROR_NONE;
275
276         ret = __check_metadata_set_parameter(_metadata);
277         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
278         metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
279         metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
280
281         // If the pointer is NULL or c-string is empty - handle as request for deletion
282         if (!value || (*value == '\0')) {
283                 metadata_editor_info("Request for frame %s deletion", frameID);
284                 tag2->removeFrames(frameID);
285                 return METADATA_EDITOR_ERROR_NONE;
286         }
287
288         // Check if the ID3v2 tag exists
289         if (tag2->frameListMap()[frameID].isEmpty()) {
290                 metadata_editor_info("The frame %s does not exist. Creating", frameID);
291                 // This is a common frame type for textural frames except comment frame
292                 TagLib::ID3v2::TextIdentificationFrame* fr = new TagLib::ID3v2::TextIdentificationFrame(frameID);
293                 metadata_editor_retvm_if(fr == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
294
295                 fr->setTextEncoding(TagLib::String::UTF8);
296                 fr->setText(TagLib::String(value, TagLib::String::UTF8));
297                 tag2->addFrame(fr);
298         } else {                // if not - just modify the data in the existing frame
299                 metadata_editor_info("The frame %s exists. Changing", frameID);
300                 tag2->frameListMap()[frameID][0]->setText(TagLib::String(value, TagLib::String::UTF8));
301         }
302
303         return METADATA_EDITOR_ERROR_NONE;
304 }
305
306 // *** This function is used to receive the number of pictures stored in ID3v2 tag of file *** //
307 static int __ID3_getNumberOfPictures(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value) {
308         int ret = METADATA_EDITOR_ERROR_NONE;
309
310         ret = __check_metadata_get_parameter(_metadata, value);
311         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
312         metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag does not exist. Can not process further");
313
314         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];            // link to picture frames in tag
315         // Check if the frames exist
316         metadata_editor_retvm_if(lst.isEmpty(), METADATA_EDITOR_ERROR_NONE, "No pictures in file");
317
318         metadata_editor_info("APIC frames exist in file");
319         char buf[META_MAX_BUF_LEN] = {0, };
320         // Convert the number of frames (lst.size()) to c-string
321         snprintf(buf, META_MAX_BUF_LEN, "%u", lst.size());
322         *value = strndup(buf, strlen(buf));
323         return METADATA_EDITOR_ERROR_NONE;
324 }
325
326 // *** This function is used to receive unsynchronized lyrics from ID3v2 tag in file *** //
327 // *** This frame differs from other string-type frames and uses UnsynchronizedLyricsFrame instead of TextIdentificationFrame *** //
328 static int __ID3_getLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value) {
329         int ret = METADATA_EDITOR_ERROR_NONE;
330
331         ret = __check_metadata_get_parameter(_metadata, value);
332         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
333         metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag does not exist. Can not process further");
334
335         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["USLT"];            // link to unsynchronized lyric frames in tag
336         // Check if frames exist in file
337         metadata_editor_retvm_if(lst.isEmpty(), METADATA_EDITOR_ERROR_NONE, "The frame USLT does not exist");
338
339         metadata_editor_info("The frame USLT exists");
340         TagLib::ID3v2::FrameList::Iterator it = lst.begin();
341         TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = static_cast<TagLib::ID3v2::UnsynchronizedLyricsFrame*>(*it);
342         TagLib::String str = frame->text();
343         bool isUTF = false;
344         if (!str.isLatin1()) isUTF = true;
345         metadata_editor_info("String is %sUTF", (isUTF ? "" : "not "));
346         uint length = strlen(str.toCString(isUTF));
347         metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
348         *value = strndup(str.toCString(isUTF), length);
349         return METADATA_EDITOR_ERROR_NONE;
350 }
351
352 // *** This function is used to set text in comment frame. It processes both ID3v1 and ID3v2 tags *** //
353 // *** Comment frame is different from other string-type frames. It uses CommentsFrame instead of TextIdentificationFrame *** //
354 static int __ID3_setTwixCommentFrame(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* value) {
355         int ret = METADATA_EDITOR_ERROR_NONE;
356
357         ret = __check_metadata_set_parameter(_metadata);
358         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
359         metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
360
361         // If the pointer is NULL or c-string is empty - handle as request for deletion
362         if (!value || (*value == '\0')) {
363                 metadata_editor_info("Request for frame COMM deletion");
364                 tag2->removeFrames("COMM");
365                 if (tag1 && !tag1->isEmpty())
366                         tag1->setComment("");
367                 return METADATA_EDITOR_ERROR_NONE;
368         }
369         // If the comment frame is empty - create the frame and add it to the list
370         if (tag2->frameListMap()["COMM"].isEmpty()) {
371                 metadata_editor_info("The frame COMM does not exist. Creating");
372                 TagLib::ID3v2::CommentsFrame* fr = new TagLib::ID3v2::CommentsFrame;
373                 metadata_editor_retvm_if(fr == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
374                 fr->setText(TagLib::String(value, TagLib::String::UTF8));
375                 fr->setTextEncoding(TagLib::String::UTF8);
376                 tag2->addFrame(fr);
377         } else {                                                // If the frame already exists - just modify its value
378                 metadata_editor_info("The frame COMM exists. Changing");
379                 tag2->frameListMap()["COMM"][0]->setText(TagLib::String(value, TagLib::String::UTF8));
380         }
381
382         if (tag1 && !tag1->isEmpty()) {                 // Copy the value to ID3v1 tag comment
383                 metadata_editor_info("ID3v1 tag also exists. Copying frame");
384                 tag1->setComment(value);
385         }
386
387         return METADATA_EDITOR_ERROR_NONE;
388 }
389
390 // *** This function is used to set text in Lyrics frame *** //
391 // *** Lyrics frame is different from other string-type frames and uses UnsynchronizedLyricsFrame instead of TextIdentificationFrame *** //
392 static int __ID3_setLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* value) {
393         int ret = METADATA_EDITOR_ERROR_NONE;
394
395         ret = __check_metadata_set_parameter(_metadata);
396         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
397         metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
398
399         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["USLT"];    // link to unsynchronized lyric frames in tag
400         // If the pointer is NULL or c-string is empty - handle as request for deletion
401         if (!value || (*value == '\0')) {
402                 metadata_editor_info("Request for frame USLT deletion");
403                 tag2->removeFrames("USLT");
404                 return METADATA_EDITOR_ERROR_NONE;
405         }
406         // Check if lyrics frames exist
407         if (lst.isEmpty()) {
408                 // No lyrics - create the frame and add it to the ID3v2 tag
409                 metadata_editor_info("The frame USLT does not exist. Creating");
410                 TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame;
411                 metadata_editor_retvm_if(frame == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
412
413                 frame->setTextEncoding(TagLib::String::UTF8);
414                 frame->setText(TagLib::String(value, TagLib::String::UTF8));
415                 tag2->addFrame(frame);
416         } else {                                                                        // the lyrics frames exist - change the existing one
417                 metadata_editor_info("USLT frames exist in file. Changing");
418                 TagLib::ID3v2::FrameList::Iterator it = lst.begin();
419                 TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = static_cast<TagLib::ID3v2::UnsynchronizedLyricsFrame*>(*it);
420                 frame->setTextEncoding(TagLib::String::UTF8);
421                 frame->setText(TagLib::String(value, TagLib::String::UTF8));
422         }
423
424         return METADATA_EDITOR_ERROR_NONE;
425 }
426
427 // *** This function extracts string values from tag in MP4 file *** //
428 static int __MP4_getStringItem(metadata_editor_s* _metadata, const char* itemname, char **value) {
429         int ret = METADATA_EDITOR_ERROR_NONE;
430
431         ret = __check_metadata_get_parameter(_metadata, value);
432         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
433         metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid  itemname");
434
435         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
436         TagLib::MP4::Tag* tag = _file->tag();
437         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag does not exist");
438
439         // Get map of items directly from tag and launch a search of specific item
440         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
441         TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find(itemname);
442         if (it != itemMap.end()) {                                                              // Item was found
443                 TagLib::String str = it->second.toStringList()[0];                      // Get the first string in item
444                 // Check the encoding of the string (1252 or not)
445                 bool isUTF = false;
446                 if (!str.isLatin1()) isUTF = true;
447                 metadata_editor_info("String is %sUTF", (isUTF ? "" : "not "));
448                 // Get the length of the string and check if it is empty or not
449                 uint length = strlen(str.toCString(isUTF));
450                 metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
451                 *value = strndup(str.toCString(isUTF), length);
452                 return METADATA_EDITOR_ERROR_NONE;
453         } else {                                                                                // Item was not found
454                 metadata_editor_info("No item <%s> in file", itemname);
455                 return METADATA_EDITOR_ERROR_NONE;
456         }
457 }
458
459 // *** This function extracts integer value from item in MP4 tag *** //
460 static int __MP4_getIntegerItem(metadata_editor_s* _metadata, const char* itemname, char** value) {
461         int ret = METADATA_EDITOR_ERROR_NONE;
462
463         ret = __check_metadata_get_parameter(_metadata, value);
464         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
465         metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid itemname");
466
467         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
468         TagLib::MP4::Tag* tag = _file->tag();
469         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag does not exist");
470
471         // Get map of items directly from tag and launch a search of specific item
472         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
473         TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find(itemname);
474         if (it != itemMap.end()) {                                                              // Item was found
475                 char buf[META_MAX_BUF_LEN] = {0, };
476                 int num = it->second.toInt();                                           // Get integer value in item
477                 snprintf(buf, META_MAX_BUF_LEN, "%u", num);                                             // Convert int into char[]
478                 // Determine the length of created c-string and copy it into the output variable
479                 int length = strlen(buf);
480                 metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
481                 *value = strndup(buf, length);
482                 return METADATA_EDITOR_ERROR_NONE;
483         } else {                                                                                // Item was not found
484                 metadata_editor_info("No item <%s> in file", itemname);
485                 return METADATA_EDITOR_ERROR_NONE;
486         }
487 }
488
489 // *** This function adds (or changes) string item of itemname type *** //
490 static int __MP4_updateStringItem(metadata_editor_s* _metadata, const char* itemname, const char* value) {
491         int ret = METADATA_EDITOR_ERROR_NONE;
492
493         ret = __check_metadata_set_parameter(_metadata);
494         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
495         metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid itemname");
496
497         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
498         TagLib::MP4::Tag* tag = _file->tag();
499         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag was not created");
500
501         // Get map of items directly from tag and launch a search of specific item
502         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
503         // Check if it is a request for deletion
504         if ((value == NULL) || value[0] == '\0') {
505                 metadata_editor_info("Request for deleting of item <%s>", itemname);
506                 TagLib::MP4::ItemListMap::Iterator it = itemMap.find(itemname);
507                 if (it != itemMap.end())
508                         itemMap.erase(it);
509                 return METADATA_EDITOR_ERROR_NONE;
510         }
511         metadata_editor_info("The item <%s> will be added", itemname);
512         itemMap[itemname] = TagLib::MP4::Item(TagLib::String(value, TagLib::String::UTF8));
513
514         return METADATA_EDITOR_ERROR_NONE;
515 }
516
517 // *** This function adds (or changes) integer item of itemname type *** //
518 static int __MP4_updateIntegerItem(metadata_editor_s* _metadata, const char* itemname, const char* value) {
519         int ret = METADATA_EDITOR_ERROR_NONE;
520
521         ret = __check_metadata_set_parameter(_metadata);
522         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
523         metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid itemname");
524
525         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
526         TagLib::MP4::Tag* tag = _file->tag();
527         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag was not created");
528
529         // Get map of items directly from tag and launch a search of specific item
530         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
531         // Check if it is a request for deletion
532         if ((value == NULL) || value[0] == '\0') {
533                 metadata_editor_info("Request for deleting of item <%s>", itemname);
534                 TagLib::MP4::ItemListMap::Iterator it = itemMap.find(itemname);
535                 if (it != itemMap.end())
536                         itemMap.erase(it);
537                 return METADATA_EDITOR_ERROR_NONE;
538         }
539         // Check if the value is integer string then it can be successfully converted into integer
540         if (isdigit(value[0])) {
541                 metadata_editor_info("The item <%s> will be added", itemname);
542                 int number = atoi(value);
543                 itemMap[itemname] = TagLib::MP4::Item(number);
544                 return METADATA_EDITOR_ERROR_NONE;
545         } else {                                                                                // Notify that string is not a number to process
546                 metadata_editor_error("Error. String does not contain a number");
547                 return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
548         }
549 }
550
551 // *** This function is used to find the number of pictures stored in MP4 file *** //
552 static int __MP4_getNumberOfPictures(metadata_editor_s* _metadata, char** value) {
553         int ret = METADATA_EDITOR_ERROR_NONE;
554
555         ret = __check_metadata_get_parameter(_metadata, value);
556         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
557
558         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
559         TagLib::MP4::Tag* tag = _file->tag();
560         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag does not exist");
561
562         // Get map of items directly from tag and launch a search of specific item
563         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
564         TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
565         if (it != itemMap.end()) {                                                              // Item was found
566                 char buf[META_MAX_BUF_LEN] = {0, };
567                 snprintf(buf, META_MAX_BUF_LEN, "%u", it->second.toCoverArtList().size());      // Convert integer value of size to its c-string representation
568                 if (strlen(buf) > 0)
569                         *value = g_strdup(buf);
570                 return METADATA_EDITOR_ERROR_NONE;
571         } else {                                                                                // Item was not found
572                 metadata_editor_info("No item <covr> in file");
573                 return METADATA_EDITOR_ERROR_NONE;
574         }
575 }
576 #if 0
577 // *** This function is used to extract string from Xiph Comment field *** //
578 static int __xiph_getFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, char** value) {
579         int ret = METADATA_EDITOR_ERROR_NONE;
580
581         ret = __check_metadata_get_parameter(_metadata, value);
582         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
583         metadata_editor_retvm_if(!fieldname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid fieldname");
584         metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag does not exist");
585
586         const TagLib::Ogg::FieldListMap& fieldMap = xtag->fieldListMap();
587         TagLib::Ogg::FieldListMap::ConstIterator it = fieldMap.find(fieldname);
588
589         if ((xtag->contains(fieldname)) && (it != fieldMap.end())) {                    // Field was found
590                 metadata_editor_info("Field %s was found. Extracting", fieldname);
591                 TagLib::String str = it->second[0];                                     // Get the first string in xiph field
592                 // Check the encoding of the string (1252 or not)
593                 bool isUTF = false;
594                 if (!str.isLatin1()) isUTF = true;
595                 metadata_editor_info("String is %sUTF", (isUTF ? "" : "not "));
596                 // Get the length of the string and check if it is empty or not
597                 uint length = strlen(str.toCString(isUTF));
598                 metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
599                 *value = strndup(str.toCString(isUTF), length);
600                 return METADATA_EDITOR_ERROR_NONE;
601         } else {                                                                                // Field was not found
602                 metadata_editor_info("No field %s in Xiph Comment", fieldname);
603                 return METADATA_EDITOR_ERROR_NONE;
604         }
605 }
606
607 // *** This function is used to write string into Xiph Comment fields *** //
608 static int __xiph_updateFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, const char* value) {
609         int ret = METADATA_EDITOR_ERROR_NONE;
610
611         ret = __check_metadata_set_parameter(_metadata);
612         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
613         metadata_editor_retvm_if(!fieldname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid fieldname");
614         metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag does not exist");
615
616         // Check if it is a request for deletion
617         if ((value == NULL) || value[0] == '\0') {
618                 metadata_editor_info("Request for deleting of field %s", fieldname);
619                 xtag->removeField(fieldname);
620                 return METADATA_EDITOR_ERROR_NONE;
621         }
622         metadata_editor_info("The field %s will be added", fieldname);
623         // "true" is used to remove other strings of the same "fieldname" first
624         xtag->addField(fieldname, TagLib::String(value, TagLib::String::UTF8), true);
625         return METADATA_EDITOR_ERROR_NONE;
626 }
627
628 // *** This function is used to receive the number of pictures in FLAC file *** //
629 static int __FLAC_getNumberOfPictures(metadata_editor_s* _metadata, char** value) {
630         int ret = METADATA_EDITOR_ERROR_NONE;
631
632         ret = __check_metadata_get_parameter(_metadata, value);
633         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
634
635         TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
636         if (_file->pictureList().isEmpty()) {
637                 metadata_editor_info("No pictures in FLAC file");
638                 return METADATA_EDITOR_ERROR_NONE;
639         }
640         uint number = _file->pictureList().size();
641         metadata_editor_info("There are %u picture(s) in file", number);
642         char buf[META_MAX_BUF_LEN] = {0, };
643         snprintf(buf, META_MAX_BUF_LEN, "%u", number);                                          // Convert integer value of size to its c-string representation
644         uint length = strlen(buf);
645         metadata_editor_retvm_if(length == 0, METADATA_EDITOR_ERROR_NONE, "Empty string");
646         *value = strndup(buf, length);
647         return METADATA_EDITOR_ERROR_NONE;
648 }
649 #endif
650 int __metadata_editor_get_file_ext(const char *file_path, char *file_ext, int max_len) {
651         int i = 0;
652         unsigned int path_len = strlen(file_path);
653
654         for (i = (int)path_len; i >= 0; i--) {
655                 if ((file_path[i] == '.') && (i < (int)path_len)) {
656                         strncpy(file_ext, &file_path[i + 1], max_len);
657                         return 0;
658                 }
659
660                 /* meet the dir. no ext */
661                 if (file_path[i] == '/')
662                         return -1;
663         }
664
665         return -1;
666 }
667
668 int __metadata_editor_get_file_type(const char *path) {
669         int ret = 0;
670         char mimetype[255] = {0, };
671
672         /* get content type and mime type from file. */
673         ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype));
674         if (ret < 0) {
675                 metadata_editor_debug("aul_get_mime_from_file fail.. Now trying to get type by extension");
676
677                 char ext[255] = { 0 };
678                 int ret = __metadata_editor_get_file_ext(path, ext, sizeof(ext));
679                 metadata_editor_retvm_if(ret < 0, METADATA_EDITOR_FORMAT_NOTYPE, "__metadata_editor_get_file_ext failed");
680
681                 if (strcasecmp(ext, "MP3") == 0)
682                         return METADATA_EDITOR_FORMAT_MP3;
683                 else if (strcasecmp(ext, "MP4") == 0)
684                         return METADATA_EDITOR_FORMAT_MP4;
685                 else
686                         return METADATA_EDITOR_FORMAT_NOTYPE;
687         }
688
689         metadata_editor_debug("mime type : %s", mimetype);
690
691         /* categorize from mimetype */
692         if (strstr(mimetype, "mpeg") != NULL)
693                 return METADATA_EDITOR_FORMAT_MP3;
694         else if (strstr(mimetype, "mp4") != NULL)
695                 return METADATA_EDITOR_FORMAT_MP4;
696
697         return METADATA_EDITOR_FORMAT_NOTYPE;
698 }
699
700 int __metadata_editor_get_picture_type(const char *path, char **type) {
701         int ret = 0;
702         char mimetype[255] = {0, };
703         const char *type_jpeg = "image/jpeg";
704         const char *type_png = "image/png";
705
706         /* get content type and mime type from file. */
707         ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype));
708         if (ret < 0) {
709                 metadata_editor_debug("aul_get_mime_from_file fail.. Now trying to get type by extension");
710
711                 char ext[255] = { 0 };
712                 int ret = __metadata_editor_get_file_ext(path, ext, sizeof(ext));
713                 metadata_editor_retvm_if(ret < 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "__metadata_editor_get_file_ext failed");
714
715                 if (strcasecmp(ext, "JPG") == 0 || strcasecmp(ext, "JPEG") == 0) {
716                         *type = strndup(type_jpeg, strlen(type_jpeg));
717                         return METADATA_EDITOR_ERROR_NONE;
718                 } else if (strcasecmp(ext, "PNG") == 0) {
719                         *type = strndup(type_png, strlen(type_png));
720                         return METADATA_EDITOR_ERROR_NONE;
721                 } else {
722                         return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
723                 }
724         }
725
726         metadata_editor_debug("mime type : %s", mimetype);
727
728         /* categorize from mimetype */
729         if (strstr(mimetype, "jpeg") != NULL) {
730                 *type = strndup(mimetype, strlen(mimetype));
731                 return METADATA_EDITOR_ERROR_NONE;
732         } else if (strstr(mimetype, "png") != NULL) {
733                 *type = strndup(mimetype, strlen(mimetype));
734                 return METADATA_EDITOR_ERROR_NONE;
735         }
736
737         return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
738 }
739
740 int __metadata_editor_get_picture_info(const char *path, void **picture, int *size, char **type) {
741         int ret;
742
743         ret = __metadata_editor_get_picture_type(path, type);
744         if (ret != METADATA_EDITOR_ERROR_NONE)
745                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
746
747         //IF ok.. read file
748         FILE* fin = fopen(path, "rb");
749         size_t file_size = 0;
750
751         if (fin) {
752                 while (fgetc(fin) != EOF)
753                         file_size++;
754
755                 fclose(fin);
756                 char picture_buffer[file_size] = {0, };
757                 memset(picture_buffer, 0, file_size * sizeof(char));
758                 fin = fopen(path, "rb");
759                 if (fin) {
760                         if(file_size != fread(picture_buffer, 1, file_size, fin)) {
761                                 metadata_editor_error("fread error");
762                                 fclose(fin);
763                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
764                         }
765                         fclose(fin);
766                 }
767                 if (*picture == NULL) {
768                         *picture = malloc(file_size * sizeof(char));
769                         memset(*picture, 0, file_size * sizeof(char));
770                         memcpy(*picture, picture_buffer, file_size);
771                         *size = file_size;
772                 }
773         }
774
775         return METADATA_EDITOR_ERROR_NONE;
776 }
777
778 // *** This function is used to allocate the metadata_editor_s in memory                *** //
779 // *** The structure metadata_editor_s contains all information about the file  *** //
780 extern "C" int metadata_editor_create(metadata_editor_h *metadata) {
781         metadata_editor_retvm_if(metadata == NULL, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
782
783         metadata_editor_s *_metadata = new metadata_editor_s;           // Allocate a structure for handler
784         metadata_editor_retvm_if(_metadata == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
785
786         _metadata->file = NULL;
787         _metadata->filetype = METADATA_EDITOR_FORMAT_NOTYPE;                    // Specify file type out of range
788         _metadata->isOpen = false;                                              // File is not opened yet
789         _metadata->isReadOnly = true;                                           // Handle unexisting file as readonly
790
791         // Save the structure in the metadata
792         *metadata = (metadata_editor_h)_metadata;
793
794         return METADATA_EDITOR_ERROR_NONE;
795 }
796
797 // *** This function is used to open the file. It creates the instance that is responsible for connection with file *** //
798 extern "C" int metadata_editor_set_path(metadata_editor_h metadata, const char *path) {
799         // Check if we have valid arguments to work with
800         metadata_editor_retvm_if(!metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
801         metadata_editor_retvm_if(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
802
803         int exist;
804
805         /* check the file exits actually */
806         exist = open(path, O_RDONLY);
807         if(exist < 0) {
808                 if (errno == EACCES || errno == EPERM) {
809                         metadata_editor_error("Permission denied");
810                         return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
811                 } else {
812                         metadata_editor_error("Not exist file");
813                         return METADATA_EDITOR_ERROR_FILE_EXISTS;
814                 }
815         }
816
817         close(exist);
818
819         metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
820         int media_type = METADATA_EDITOR_FORMAT_NOTYPE;
821
822         media_type = __metadata_editor_get_file_type(path);
823
824         switch (media_type) {                                                   // Parse file according the specified type
825                 case METADATA_EDITOR_FORMAT_MP3: {
826                         if (_metadata->file) {
827                                 TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
828                                 metadata_editor_info("file free [%p]", _metadata->file);
829                                 delete _file;
830                                 _metadata->file = NULL;
831                                 _metadata->filetype = METADATA_EDITOR_FORMAT_NOTYPE;
832                                 _metadata->isOpen = false;
833                                 _metadata->isReadOnly = true;
834                         }
835
836                         // Allocate the file object in memory to work with it later on
837                         TagLib::MPEG::File* _file = new TagLib::MPEG::File(path);
838
839                         metadata_editor_retvm_if(_file == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
840
841                         _metadata->file = _file;                                // Copy file pointer to the structure
842
843                         _metadata->filetype = METADATA_EDITOR_FORMAT_MP3;
844
845                         if (_file->isOpen()) {                                  // Check if the file was opened successfully
846                                 metadata_editor_info("The file is successfully opened. Address is %p", _metadata->file);
847                                 _metadata->isOpen = true;
848                         } else {                                                        // The file does not exist or you have no permission to process it
849                                 metadata_editor_error("The file was not found. Pointer address is %p", _metadata->file);
850                                 _metadata->isOpen = false;
851                                 return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
852                         }
853
854                         if (_file->readOnly()) {                                        // Check if the file is readonly
855                                 metadata_editor_info("File is readonly");
856                                 _metadata->isReadOnly = true;
857                         } else {                                                        // or not
858                                 metadata_editor_info("The file is writable");
859                                 _metadata->isReadOnly = false;
860                         }
861
862                         return METADATA_EDITOR_ERROR_NONE;
863                 }
864                 case METADATA_EDITOR_FORMAT_MP4: {
865                         if (_metadata->file) {
866                                 TagLib::MP4::File* _file = (TagLib::MP4::File*)_metadata->file;
867                                 metadata_editor_info("file free [%p]", _metadata->file);
868                                 delete _file;
869                                 _metadata->file = NULL;
870                                 _metadata->filetype = METADATA_EDITOR_FORMAT_NOTYPE;
871                                 _metadata->isOpen = false;
872                                 _metadata->isReadOnly = true;
873                         }
874
875                         // Allocate the file object in memory to work with it later on
876                         TagLib::MP4::File* _file = new TagLib::MP4::File(path);
877
878                         metadata_editor_retvm_if(_file == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
879
880                         _metadata->file = _file;                                // Copy file pointer to the structure
881
882                         _metadata->filetype = METADATA_EDITOR_FORMAT_MP4;
883
884                         if (_file->isOpen()) {                                  // Check if the file was opened successfully
885                                 metadata_editor_info("The file is successfully opened. Address is %p", _metadata->file);
886                                 _metadata->isOpen = true;
887                         } else {                                                        // The file does not exist or you have no permission to process it
888                                 metadata_editor_error("The file was not found. Pointer address is %p", _metadata->file);
889                                 _metadata->isOpen = false;
890                                 return METADATA_EDITOR_ERROR_FILE_EXISTS;
891                         }
892                         if (_file->readOnly()) {                                        // Check if the file is readonly
893                                 metadata_editor_info("File is readonly");
894                                 _metadata->isReadOnly = true;
895                         } else {                                                        // or not
896                                 metadata_editor_info("The file is writable");
897                                 _metadata->isReadOnly = false;
898                         }
899                         return METADATA_EDITOR_ERROR_NONE;
900                 }
901 #if 0
902                 case METADATA_EDITOR_FORMAT_FLAC: {
903                         // Allocate the file object in memory to work with it later on
904                         TagLib::FLAC::File* _file = new TagLib::FLAC::File(path);
905
906                         metadata_editor_retvm_if(_file == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
907
908                         _metadata->file = _file;                                // Copy file pointer to the structure
909
910                         _metadata->filetype = METADATA_EDITOR_FORMAT_FLAC;
911
912                         if (_file->isOpen()) {                          // Check if the file was opened successfully
913                                 metadata_editor_info("The file is successfully opened. Address is %p", _metadata->file);
914                                 _metadata->isOpen = true;
915                         } else {                                                        // The file does not exist or you have no permission to process it
916                                 metadata_editor_error("The file was not found. Pointer address is %p", _metadata->file);
917                                 _metadata->isOpen = false;
918                                 return METADATA_EDITOR_ERROR_FILE_EXISTS;
919                         }
920                         if (_file->readOnly()) {                                        // Check if the file is readonly
921                                 metadata_editor_info("File is readonly");
922                                 _metadata->isReadOnly = true;
923                         } else {                                                        // or not
924                                 metadata_editor_info("The file is writable");
925                                 _metadata->isReadOnly = false;
926                         }
927                         return METADATA_EDITOR_ERROR_NONE;
928                 }
929                 case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
930                         // Allocate the file object in memory to work with it later on
931                         TagLib::Ogg::Vorbis::File* _file = new TagLib::Ogg::Vorbis::File(path);
932
933                         metadata_editor_retvm_if(_file == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
934
935                         _metadata->file = _file;                                // Copy file pointer to the structure
936
937                         _metadata->filetype = METADATA_EDITOR_FORMAT_OGG_VORBIS;
938
939                         if (_file->isOpen()) {                          // Check if the file was opened successfully
940                                 metadata_editor_info("The file is successfully opened. Address is %p", _metadata->file);
941                                 _metadata->isOpen = true;
942                         } else {                                                        // The file does not exist or you have no permission to process it
943                                 metadata_editor_error("The file was not found. Pointer address is %p", _metadata->file);
944                                 _metadata->isOpen = false;
945                                 return METADATA_EDITOR_ERROR_FILE_EXISTS;
946                         }
947                         if (_file->readOnly()) {                                        // Check if the file is readonly
948                                 metadata_editor_info("File is readonly");
949                                 _metadata->isReadOnly = true;
950                         } else {                                                        // or not
951                                 metadata_editor_info("The file is writable");
952                                 _metadata->isReadOnly = false;
953                         }
954                         return METADATA_EDITOR_ERROR_NONE;
955                 }
956                 case METADATA_EDITOR_FORMAT_OGG_FLAC: {
957                         // Allocate the file object in memory to work with it later on
958                         TagLib::Ogg::FLAC::File* _file = new TagLib::Ogg::FLAC::File(path);
959
960                         metadata_editor_retvm_if(_file == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
961
962                         _metadata->file = _file;                                // Copy file pointer to the structure
963
964                         _metadata->filetype = METADATA_EDITOR_FORMAT_OGG_FLAC;
965
966                         if (_file->isOpen()) {                                  // Check if the file was opened successfully
967                                 metadata_editor_info("The file is successfully opened. Address is %p", _metadata->file);
968                                 _metadata->isOpen = true;
969                         } else {                                                        // The file does not exist or you have no permission to process it
970                                 metadata_editor_error("The file was not found. Pointer address is %p", _metadata->file);
971                                 _metadata->isOpen = false;
972                                 return METADATA_EDITOR_ERROR_FILE_EXISTS;
973                         }
974                         if (_file->readOnly()) {                                        // Check if the file is readonly
975                                 metadata_editor_info("File is readonly");
976                                 _metadata->isReadOnly = true;
977                         } else {                                                        // or not
978                                 metadata_editor_info("The file is writable");
979                                 _metadata->isReadOnly = false;
980                         }
981                         return METADATA_EDITOR_ERROR_NONE;
982                 }
983                 case METADATA_EDITOR_FORMAT_WAV: {
984                         // Allocate the file object in memory to work with it later on
985                         TagLib::RIFF::WAV::File* _file = new TagLib::RIFF::WAV::File(path);
986
987                         metadata_editor_retvm_if(_file == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
988
989                         _metadata->file = _file;                                // Copy file pointer to the structure
990
991                         _metadata->filetype = METADATA_EDITOR_FORMAT_WAV;
992
993                         if (_file->isOpen()) {                                  // Check if the file was opened successfully
994                                 metadata_editor_info("The file is successfully opened. Address is %p", _metadata->file);
995                                 _metadata->isOpen = true;
996                         } else {                                                        // The file does not exist or you have no permission to process it
997                                 metadata_editor_error("The file was not found. Pointer address is %p", _metadata->file);
998                                 _metadata->isOpen = false;
999                                 return METADATA_EDITOR_ERROR_FILE_EXISTS;
1000                         }
1001                         if (_file->readOnly()) {                                        // Check if the file is readonly
1002                                 metadata_editor_info("File is readonly");
1003                                 _metadata->isReadOnly = true;
1004                         } else {                                                        // or not
1005                                 metadata_editor_info("The file is writable");
1006                                 _metadata->isReadOnly = false;
1007                         }
1008                         return METADATA_EDITOR_ERROR_NONE;
1009                 }
1010 #endif
1011                 default:
1012                         metadata_editor_error("Wrong file type");
1013                         return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
1014         }
1015 }
1016
1017 static int __metadata_editor_get_mp3_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
1018 {
1019         int ret = METADATA_EDITOR_ERROR_NONE;
1020
1021         ret = __check_metadata_get_parameter(metadata, value);
1022         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1023
1024         // Bring the pointer to actual file type and make tag pointers
1025         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)metadata->file;
1026         TagLib::ID3v1::Tag* tag1 = _file->ID3v1Tag();
1027         TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag();
1028
1029         switch (attribute) {                                    // Check which one of frame types was given to the function for processing
1030                 case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_getTwixFrameByName(metadata, tag1, tag2, "TPE1", value);
1031                 case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_getTwixFrameByName(metadata, tag1, tag2, "TIT2", value);
1032                 case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_getTwixFrameByName(metadata, tag1, tag2, "TALB", value);
1033                 case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_getTwixFrameByName(metadata, tag1, tag2, "TCON", value);
1034                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_getFrameByName(metadata, tag2, "TCOM", value);
1035                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __ID3_getFrameByName(metadata, tag2, "TCOP", value);
1036                 case METADATA_EDITOR_ATTR_DATE:                 return __ID3_getTwixFrameByName(metadata, tag1, tag2, "TDRC", value);
1037                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_getFrameByName(metadata, tag2, "TIT3", value);
1038                 case METADATA_EDITOR_ATTR_COMMENT:                      return __ID3_getTwixFrameByName(metadata, tag1, tag2, "COMM", value);
1039                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __ID3_getTwixFrameByName(metadata, tag1, tag2, "TRCK", value);
1040                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __ID3_getFrameByName(metadata, tag2, "TPE3", value);
1041                 case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __ID3_getNumberOfPictures(metadata, tag2, value);
1042                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_getLyricsFrame(metadata, tag2, value);
1043                 default:
1044                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1045         }
1046 }
1047
1048 static int __metadata_editor_get_mp4_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
1049 {
1050         int ret = METADATA_EDITOR_ERROR_NONE;
1051
1052         ret = __check_metadata_get_parameter(metadata, value);
1053         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1054
1055         switch (attribute) {                                    // Check which one of frame types was given to the function for processing
1056         case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_getStringItem(metadata, "\xA9""ART", value);
1057         case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_getStringItem(metadata, "\xA9""nam", value);
1058         case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_getStringItem(metadata, "\xA9""alb", value);
1059         case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_getStringItem(metadata, "\xA9""gen", value);
1060         case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_getStringItem(metadata, "\xA9""wrt", value);
1061         case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __MP4_getStringItem(metadata, "cprt", value);
1062         case METADATA_EDITOR_ATTR_DATE:                 return __MP4_getStringItem(metadata, "\xA9""day", value);
1063         case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_getStringItem(metadata, "desc", value);
1064         case METADATA_EDITOR_ATTR_COMMENT:                      return __MP4_getStringItem(metadata, "\xA9""cmt", value);
1065         case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __MP4_getIntegerItem(metadata, "trkn", value);
1066         case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __MP4_getStringItem(metadata, "cond", value);
1067         case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __MP4_getStringItem(metadata, "\xA9""lyr", value);
1068         case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __MP4_getNumberOfPictures(metadata, value);
1069         default:
1070                 return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1071 }
1072 }
1073
1074 #if 0
1075 static int __metadata_editor_get_flac_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
1076 {
1077         int ret = METADATA_EDITOR_ERROR_NONE;
1078
1079         ret = __check_metadata_get_parameter(metadata, value);
1080         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1081
1082         // Bring the pointer to actual file type and make tags pointers
1083         TagLib::FLAC::File* _file = (TagLib::FLAC::File*)metadata->file;
1084         TagLib::Ogg::XiphComment* xtag = _file->xiphComment(false);
1085         if (!xtag) {                                                                    // Check if we have a valid tag for processing
1086                 metadata_editor_error("Tag does not exist");
1087                 *value = NULL;
1088                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1089         }
1090         switch (attribute) {                                    // Check which one of frame types was given to the function for processing
1091                 case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(metadata, xtag, "ARTIST", value);
1092                 case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(metadata, xtag, "TITLE", value);
1093                 case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(metadata, xtag, "ALBUM", value);
1094                 case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(metadata, xtag, "GENRE", value);
1095                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(metadata, xtag, "COMPOSER", value);
1096                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(metadata, xtag, "COPYRIGHT", value);
1097                 case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(metadata, xtag, "DATE", value);
1098                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(metadata, xtag, "DESCRIPTION", value);
1099                 case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(metadata, xtag, "COMMENT", value);
1100                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(metadata, xtag, "TRACKNUMBER", value);
1101                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(metadata, xtag, "CONDUCTOR", value);
1102                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(metadata, xtag, "LYRICS", value);
1103                 case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __FLAC_getNumberOfPictures(metadata, value);
1104                 default:
1105                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1106         }
1107 }
1108
1109 static int __metadata_editor_get_ogg_vorbis_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
1110 {
1111         int ret = METADATA_EDITOR_ERROR_NONE;
1112
1113         ret = __check_metadata_get_parameter(metadata, value);
1114         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1115
1116         // Bring the pointer to actual file type and make tags pointers
1117         TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)metadata->file;
1118         TagLib::Ogg::XiphComment* xtag = _file->tag();
1119         if (!xtag) {                                                                    // Check if we have a valid tag for processing
1120                 metadata_editor_error("Tag does not exist");
1121                 *value = NULL;
1122                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1123         }
1124         switch (attribute) {                                    // Check which one of frame types was given to the function for processing
1125                 case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(metadata, xtag, "ARTIST", value);
1126                 case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(metadata, xtag, "TITLE", value);
1127                 case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(metadata, xtag, "ALBUM", value);
1128                 case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(metadata, xtag, "GENRE", value);
1129                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(metadata, xtag, "COMPOSER", value);
1130                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(metadata, xtag, "COPYRIGHT", value);
1131                 case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(metadata, xtag, "DATE", value);
1132                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(metadata, xtag, "DESCRIPTION", value);
1133                 case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(metadata, xtag, "COMMENT", value);
1134                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(metadata, xtag, "TRACKNUMBER", value);
1135                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(metadata, xtag, "CONDUCTOR", value);
1136                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(metadata, xtag, "LYRICS", value);
1137                 default:
1138                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1139         }
1140 }
1141
1142 static int __metadata_editor_get_ogg_flac_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
1143 {
1144         int ret = METADATA_EDITOR_ERROR_NONE;
1145
1146         ret = __check_metadata_get_parameter(metadata, value);
1147         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1148
1149         // Bring the pointer to actual file type and make tags pointers
1150         TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)metadata->file;
1151         TagLib::Ogg::XiphComment* xtag = _file->tag();
1152         if (!xtag) {                                                                    // Check if we have a valid tag for processing
1153                 metadata_editor_error("Tag does not exist");
1154                 *value = NULL;
1155                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1156         }
1157         switch (attribute) {                                    // Check which one of frame types was given to the function for processing
1158                 case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(metadata, xtag, "ARTIST", value);
1159                 case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(metadata, xtag, "TITLE", value);
1160                 case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(metadata, xtag, "ALBUM", value);
1161                 case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(metadata, xtag, "GENRE", value);
1162                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(metadata, xtag, "COMPOSER", value);
1163                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(metadata, xtag, "COPYRIGHT", value);
1164                 case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(metadata, xtag, "DATE", value);
1165                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(metadata, xtag, "DESCRIPTION", value);
1166                 case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(metadata, xtag, "COMMENT", value);
1167                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(metadata, xtag, "TRACKNUMBER", value);
1168                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(metadata, xtag, "CONDUCTOR", value);
1169                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(metadata, xtag, "LYRICS", value);
1170                 default:
1171                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1172         }
1173 }
1174
1175 static int __metadata_editor_get_wav_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
1176 {
1177         int ret = METADATA_EDITOR_ERROR_NONE;
1178
1179         ret = __check_metadata_get_parameter(metadata, value);
1180         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1181
1182         // Bring the pointer to actual file type and make tag pointers
1183         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)metadata->file;
1184         TagLib::ID3v2::Tag* tag2 = _file->tag();
1185
1186         if (tag2 == NULL) {                                                             // Check if we have a valid tag for processing
1187                 metadata_editor_error("Error. ID3v2 tag does not exist. Can not proceed metadata extraction");
1188                 *value = NULL;
1189                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1190         }
1191
1192         switch (attribute) {                                    // Check which one of frame types was given to the function for processing
1193                 case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_getFrameByName(metadata, tag2, "TPE1", value);
1194                 case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_getFrameByName(metadata, tag2, "TIT2", value);
1195                 case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_getFrameByName(metadata, tag2, "TALB", value);
1196                 case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_getFrameByName(metadata, tag2, "TCON", value);
1197                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_getFrameByName(metadata, tag2, "TCOM", value);
1198                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __ID3_getFrameByName(metadata, tag2, "TCOP", value);
1199                 case METADATA_EDITOR_ATTR_DATE:                 return __ID3_getFrameByName(metadata, tag2, "TDRC", value);
1200                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_getFrameByName(metadata, tag2, "TIT3", value);
1201                 case METADATA_EDITOR_ATTR_COMMENT:                      return __ID3_getFrameByName(metadata, tag2, "COMM", value);
1202                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __ID3_getFrameByName(metadata, tag2, "TRCK", value);
1203                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __ID3_getFrameByName(metadata, tag2, "TPE3", value);
1204                 case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __ID3_getNumberOfPictures(metadata, tag2, value);
1205                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_getLyricsFrame(metadata, tag2, value);
1206                 default:
1207                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1208         }
1209 }
1210 #endif
1211
1212 // *** This function is used to get the tag frame (field, item - each tag has its own name for data unit) from file *** //
1213 extern "C" int metadata_editor_get_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, char **value) {
1214
1215         metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
1216         metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
1217
1218         switch (_metadata->filetype) {                          // Process the file according to the specified file type
1219                 case METADATA_EDITOR_FORMAT_MP3:
1220                         return __metadata_editor_get_mp3_metadata(_metadata, attribute, value);
1221
1222                 case METADATA_EDITOR_FORMAT_MP4:
1223                         return __metadata_editor_get_mp4_metadata(_metadata, attribute, value);
1224
1225 #if 0
1226                 case METADATA_EDITOR_FORMAT_FLAC: {
1227                         return __metadata_editor_get_flac_metadata(_metadata, attribute, value);
1228                 }
1229                 case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
1230                         return __metadata_editor_get_ogg_vorbis_metadata(_metadata, attribute, value);
1231                 }
1232                 case METADATA_EDITOR_FORMAT_OGG_FLAC: {
1233                         return __metadata_editor_get_ogg_flac_metadata(_metadata, attribute, value);
1234                 }
1235                 case METADATA_EDITOR_FORMAT_WAV: {
1236                         return __metadata_editor_get_wav_metadata(_metadata, attribute, value);
1237                 }
1238 #endif
1239                 default:
1240                         metadata_editor_error("Wrong file type [%d]", _metadata->filetype);
1241                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1242         }
1243 }
1244
1245 static int __metadata_editor_set_mp3_metadata(metadata_editor_s* metadata, metadata_editor_attr_e attribute, const char* value)
1246 {
1247         int ret = METADATA_EDITOR_ERROR_NONE;
1248
1249         ret = __check_metadata_set_parameter(metadata);
1250         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1251
1252         // Bring the pointer to actual file type and make tags pointers
1253         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)metadata->file;
1254         TagLib::ID3v1::Tag* tag1 = _file->ID3v1Tag();
1255         TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag(true);
1256
1257         metadata_editor_retvm_if(tag2 == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
1258
1259         switch (attribute) {                                    // Check which one of frame type was given for processing
1260                 case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_setTwixFrameByName(metadata, tag1, tag2, "TPE1", value);
1261                 case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_setTwixFrameByName(metadata, tag1, tag2, "TIT2", value);
1262                 case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_setTwixFrameByName(metadata, tag1, tag2, "TALB", value);
1263                 case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_setTwixFrameByName(metadata, tag1, tag2, "TCON", value);
1264                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_setFrameByName(metadata, tag2, "TCOM", value);
1265                 case METADATA_EDITOR_ATTR_COPYRIGHT:            return __ID3_setFrameByName(metadata, tag2, "TCOP", value);
1266                 case METADATA_EDITOR_ATTR_DATE:                 return __ID3_setTwixFrameByName(metadata, tag1, tag2, "TDRC", value);
1267                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_setFrameByName(metadata, tag2, "TIT3", value);
1268                 case METADATA_EDITOR_ATTR_TRACK_NUM:            return __ID3_setTwixFrameByName(metadata, tag1, tag2, "TRCK", value);
1269                 case METADATA_EDITOR_ATTR_CONDUCTOR:            return __ID3_setFrameByName(metadata, tag2, "TPE3", value);
1270                 case METADATA_EDITOR_ATTR_COMMENT:              return __ID3_setTwixCommentFrame(metadata, tag1, tag2, value);
1271                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS: return __ID3_setLyricsFrame(metadata, tag2, value);
1272                 default:
1273                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1274         }
1275 }
1276
1277 static int __metadata_editor_set_mp4_metadata(metadata_editor_s* metadata, metadata_editor_attr_e attribute, const char* value)
1278 {
1279         int ret = METADATA_EDITOR_ERROR_NONE;
1280
1281         ret = __check_metadata_set_parameter(metadata);
1282         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1283
1284         switch (attribute) {                                    // Check which one of frame type was given for processing
1285         case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_updateStringItem(metadata, "\xA9""ART", value);
1286         case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_updateStringItem(metadata, "\xA9""nam", value);
1287         case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_updateStringItem(metadata, "\xA9""alb", value);
1288         case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_updateStringItem(metadata, "\xA9""gen", value);
1289         case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_updateStringItem(metadata, "\xA9""wrt", value);
1290         case METADATA_EDITOR_ATTR_COPYRIGHT:            return __MP4_updateStringItem(metadata, "cprt", value);
1291         case METADATA_EDITOR_ATTR_DATE:                 return __MP4_updateStringItem(metadata, "\xA9""day", value);
1292         case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_updateStringItem(metadata, "desc", value);
1293         case METADATA_EDITOR_ATTR_COMMENT:              return __MP4_updateStringItem(metadata, "\xA9""cmt", value);
1294         case METADATA_EDITOR_ATTR_TRACK_NUM:            return __MP4_updateIntegerItem(metadata, "trkn", value);
1295         case METADATA_EDITOR_ATTR_CONDUCTOR:            return __MP4_updateStringItem(metadata, "cond", value);
1296         case METADATA_EDITOR_ATTR_UNSYNCLYRICS: return __MP4_updateStringItem(metadata, "\xA9""lyr", value);
1297         default:
1298                 return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1299         }
1300 }
1301
1302 #if 0
1303 static int __metadata_editor_set_flac_metadata(metadata_editor_s* metadata, metadata_editor_attr_e attribute, const char* value)
1304 {
1305         int ret = METADATA_EDITOR_ERROR_NONE;
1306
1307         ret = __check_metadata_set_parameter(metadata);
1308         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1309
1310         // Bring the pointer to actual file type and make tags pointers
1311         TagLib::FLAC::File* _file = (TagLib::FLAC::File*)metadata->file;
1312         TagLib::Ogg::XiphComment* xtag = _file->xiphComment(true);
1313         if (!xtag) {                                                            // Check if we have a valid tag for processing
1314                 metadata_editor_error("Error. Xiph Comment was not created. Can not proceed metadata updating");
1315                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1316         }
1317         switch (attribute) {                                    // Check which one of frame type was given for processing
1318                 case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(metadata, xtag, "ARTIST", value);
1319                 case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(metadata, xtag, "TITLE", value);
1320                 case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(metadata, xtag, "ALBUM", value);
1321                 case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(metadata, xtag, "GENRE", value);
1322                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(metadata, xtag, "COMPOSER", value);
1323                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(metadata, xtag, "COPYRIGHT", value);
1324                 case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(metadata, xtag, "DATE", value);
1325                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(metadata, xtag, "DESCRIPTION", value);
1326                 case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(metadata, xtag, "COMMENT", value);
1327                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(metadata, xtag, "TRACKNUMBER", value);
1328                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(metadata, xtag, "CONDUCTOR", value);
1329                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(metadata, xtag, "LYRICS", value);
1330                 default:
1331                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1332         }
1333 }
1334
1335 static int __metadata_editor_set_ogg_vorbis_metadata(metadata_editor_s* metadata, metadata_editor_attr_e attribute, const char* value)
1336 {
1337         int ret = METADATA_EDITOR_ERROR_NONE;
1338
1339         ret = __check_metadata_set_parameter(metadata);
1340         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1341
1342         // Bring the pointer to actual file type and make tags pointers
1343         TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)metadata->file;
1344         TagLib::Ogg::XiphComment* xtag = _file->tag();
1345         if (!xtag) {                                                            // Check if we have a valid tag for processing
1346                 metadata_editor_error("Error. Xiph Comment was not created. Can not proceed metadata updating");
1347                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1348         }
1349         switch (attribute) {                                    // Check which one of frame type was given for processing
1350                 case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(metadata, xtag, "ARTIST", value);
1351                 case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(metadata, xtag, "TITLE", value);
1352                 case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(metadata, xtag, "ALBUM", value);
1353                 case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(metadata, xtag, "GENRE", value);
1354                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(metadata, xtag, "COMPOSER", value);
1355                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(metadata, xtag, "COPYRIGHT", value);
1356                 case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(metadata, xtag, "DATE", value);
1357                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(metadata, xtag, "DESCRIPTION", value);
1358                 case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(metadata, xtag, "COMMENT", value);
1359                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(metadata, xtag, "TRACKNUMBER", value);
1360                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(metadata, xtag, "CONDUCTOR", value);
1361                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(metadata, xtag, "LYRICS", value);
1362                 default:
1363                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1364         }
1365 }
1366
1367 static int __metadata_editor_set_ogg_flac_metadata(metadata_editor_s* metadata, metadata_editor_attr_e attribute, const char* value)
1368 {
1369         int ret = METADATA_EDITOR_ERROR_NONE;
1370
1371         ret = __check_metadata_set_parameter(metadata);
1372         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1373
1374         // Bring the pointer to actual file type and make tags pointers
1375         TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)metadata->file;
1376         TagLib::Ogg::XiphComment* xtag = _file->tag();
1377         if (!xtag) {                                                    // Check if we have a valid tag for processing
1378                 metadata_editor_error("Error. Xiph Comment was not created. Can not proceed metadata updating");
1379                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1380         }
1381         switch (attribute) {                                    // Check which one of frame type was given for processing
1382                 case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(metadata, xtag, "ARTIST", value);
1383                 case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(metadata, xtag, "TITLE", value);
1384                 case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(metadata, xtag, "ALBUM", value);
1385                 case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(metadata, xtag, "GENRE", value);
1386                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(metadata, xtag, "COMPOSER", value);
1387                 case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(metadata, xtag, "COPYRIGHT", value);
1388                 case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(metadata, xtag, "DATE", value);
1389                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(metadata, xtag, "DESCRIPTION", value);
1390                 case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(metadata, xtag, "COMMENT", value);
1391                 case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(metadata, xtag, "TRACKNUMBER", value);
1392                 case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(metadata, xtag, "CONDUCTOR", value);
1393                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(metadata, xtag, "LYRICS", value);
1394                 default:
1395                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1396         }
1397 }
1398
1399 static int __metadata_editor_set_wav_metadata(metadata_editor_s* metadata, metadata_editor_attr_e attribute, const char* value)
1400 {
1401         int ret = METADATA_EDITOR_ERROR_NONE;
1402
1403         ret = __check_metadata_set_parameter(metadata);
1404         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1405
1406         // Bring the pointer to actual file type and make tags pointers
1407         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)metadata->file;
1408         TagLib::ID3v2::Tag* tag2 = _file->tag();
1409         // Check if the valid tag pointer exist
1410         if (tag2 == NULL) {
1411                 metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating");
1412                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1413         }
1414
1415         switch (attribute) {                                    // Check which one of frame type was given for processing
1416                 case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_setFrameByName(metadata, tag2, "TPE1", value);
1417                 case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_setFrameByName(metadata, tag2, "TIT2", value);
1418                 case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_setFrameByName(metadata, tag2, "TALB", value);
1419                 case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_setFrameByName(metadata, tag2, "TCON", value);
1420                 case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_setFrameByName(metadata, tag2, "TCOM", value);
1421                 case METADATA_EDITOR_ATTR_COPYRIGHT:            return __ID3_setFrameByName(metadata, tag2, "TCOP", value);
1422                 case METADATA_EDITOR_ATTR_DATE:                 return __ID3_setFrameByName(metadata, tag2, "TDRC", value);
1423                 case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_setFrameByName(metadata, tag2, "TIT3", value);
1424                 case METADATA_EDITOR_ATTR_TRACK_NUM:            return __ID3_setFrameByName(metadata, tag2, "TRCK", value);
1425                 case METADATA_EDITOR_ATTR_CONDUCTOR:            return __ID3_setFrameByName(metadata, tag2, "TPE3", value);
1426                 case METADATA_EDITOR_ATTR_COMMENT:              return __ID3_setTwixCommentFrame(metadata, NULL, tag2, value);
1427                 case METADATA_EDITOR_ATTR_UNSYNCLYRICS: return __ID3_setLyricsFrame(metadata, tag2, value);
1428                 default:
1429                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1430         }
1431 }
1432 #endif
1433
1434 // *** This function is used to modify the metadata (frame in tag). But it does not apply changes to file *** //
1435 extern "C" int metadata_editor_set_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, const char* value) {
1436
1437         metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
1438         metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
1439
1440         switch (_metadata->filetype) {                                          // Process the file according to the specified file type
1441                 case METADATA_EDITOR_FORMAT_MP3:
1442                         return __metadata_editor_set_mp3_metadata(_metadata, attribute, value);
1443
1444                 case METADATA_EDITOR_FORMAT_MP4:
1445                         return __metadata_editor_set_mp4_metadata(_metadata, attribute, value);
1446
1447 #if 0
1448                 case METADATA_EDITOR_FORMAT_FLAC:
1449                         return __metadata_editor_set_flac_metadata(_metadata, attribute, value);
1450
1451                 case METADATA_EDITOR_FORMAT_OGG_VORBIS:
1452                         return __metadata_editor_set_ogg_vorbis_metadata(_metadata, attribute, value);
1453
1454                 case METADATA_EDITOR_FORMAT_OGG_FLAC:
1455                         return __metadata_editor_set_ogg_flac_metadata(_metadata, attribute, value);
1456
1457                 case METADATA_EDITOR_FORMAT_WAV:
1458                         return __metadata_editor_set_wav_metadata(_metadata, attribute, value);
1459
1460 #endif
1461                 default:
1462                         metadata_editor_error("Wrong file type");
1463                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1464         }
1465 }
1466
1467 // *** This function apply all changes done in the tag(s) and update them to file *** //
1468 extern "C" int metadata_editor_update_metadata(metadata_editor_h metadata) {
1469         int ret = METADATA_EDITOR_ERROR_NONE;
1470         metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
1471
1472         ret = __check_metadata_set_parameter(_metadata);
1473         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1474
1475         switch (_metadata->filetype) {                                          // Process the file according to the specified file type
1476                 case METADATA_EDITOR_FORMAT_MP3: {
1477                         // Bring the pointer to actual file type
1478                         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
1479
1480                         TagLib::ID3v1::Tag* tag1 = _file->ID3v1Tag();
1481
1482                         if (!tag1 || tag1->isEmpty()) {                                                 // If no ID3v1 tag - prevent its creation
1483                                 if (_file->save(TagLib::MPEG::File::ID3v2 | TagLib::MPEG::File::APE))
1484                                         return METADATA_EDITOR_ERROR_NONE;
1485                         } else {                                                                                // otherwise - save all tags in file
1486                                 if (_file->save(TagLib::MPEG::File::AllTags))
1487                                         return METADATA_EDITOR_ERROR_NONE;
1488                         }
1489                         return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1490                 }
1491                 case METADATA_EDITOR_FORMAT_MP4: {
1492                         TagLib::MP4::File* _file = (TagLib::MP4::File*)_metadata->file;
1493                         if (_file->save())
1494                                 return METADATA_EDITOR_ERROR_NONE;
1495                         else
1496                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1497                 }
1498 #if 0
1499                 case METADATA_EDITOR_FORMAT_FLAC: {
1500                         TagLib::FLAC::File* _file = (TagLib::FLAC::File*)_metadata->file;
1501                         if (_file->save())
1502                                 return METADATA_EDITOR_ERROR_NONE;
1503                         else
1504                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1505                 }
1506                 case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
1507                         TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)_metadata->file;
1508                         if (_file->save())
1509                                 return METADATA_EDITOR_ERROR_NONE;
1510                         else
1511                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1512                 }
1513                 case METADATA_EDITOR_FORMAT_OGG_FLAC: {
1514                         TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)_metadata->file;
1515                         if (_file->save())
1516                                 return METADATA_EDITOR_ERROR_NONE;
1517                         else
1518                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1519                 }
1520                 case METADATA_EDITOR_FORMAT_WAV: {
1521                         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
1522                         if (_file->save())
1523                                 return METADATA_EDITOR_ERROR_NONE;
1524                         else
1525                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1526                 }
1527 #endif
1528                 default:
1529                         metadata_editor_error("Wrong file type");
1530                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1531         }
1532 }
1533
1534 // *** This function returns buffer with picture under the specified index and buffer's (picture's) size *** //
1535 extern "C" int metadata_editor_get_picture(metadata_editor_h metadata, int index, void **picture, int *size, char **mime_type) {
1536         const char *TYPE_JPEG = "image/jpeg";
1537         const char *TYPE_PNG = "image/png";
1538
1539         int ret = METADATA_EDITOR_ERROR_NONE;
1540
1541         metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
1542
1543         ret = __check_metadata_get_parameter(_metadata, mime_type);
1544         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
1545         metadata_editor_retvm_if(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
1546         metadata_editor_retvm_if(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
1547
1548         *picture = NULL;
1549         *size = 0;
1550         *mime_type = NULL;
1551
1552         switch (_metadata->filetype) {                                                                  // Process the file according to the specified file type
1553                 case METADATA_EDITOR_FORMAT_MP3: {
1554                         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;               // Bring the pointer to actual file type
1555                         TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag();
1556                         metadata_editor_retvm_if(tag2 == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. No ID3v2 tag in file.");
1557
1558                         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
1559                         // Check if there are pictures in the tag
1560                         if (lst.isEmpty()) {
1561                                 metadata_editor_error("No pictures in file");
1562                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1563                         } else {                // pictures exist in file
1564                                 // Check if index is correct or not
1565                                 if ((index < 0) || (lst.size() <= (uint)index)) {
1566                                         metadata_editor_error("Index of picture is out of range");
1567                                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1568                                 } else {                // everything is correct - begin extraction
1569                                         metadata_editor_info("There are %u pictures in file. Start of picture number %d extraction", lst.size(), index);
1570                                         int i = 0;
1571                                         // Among all frames we must choose that one with specified index. "i" will be counter
1572                                         for (TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i) {
1573                                                 if (i != index) continue;
1574                                                 TagLib::ID3v2::AttachedPictureFrame* pictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
1575                                                 uint pictureSize = pictureFrame->picture().size();
1576                                                 metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
1577                                                 META_MALLOC(*picture, pictureSize);
1578                                                 metadata_editor_retvm_if(*picture == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
1579
1580                                                 memcpy(*picture, pictureFrame->picture().data(), pictureSize);
1581                                                 *size = pictureSize;
1582                                                 TagLib::String mime = pictureFrame->mimeType();
1583                                                 if (!strcmp(mime.toCString(), "image/jpeg"))
1584                                                         *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
1585                                                 else if (!strcmp(mime.toCString(), "image/png"))
1586                                                         *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
1587                                                 else
1588                                                         *mime_type = NULL;
1589                                                 break;
1590                                         }
1591                                         return METADATA_EDITOR_ERROR_NONE;
1592                                 }
1593                         }
1594                 }
1595                 case METADATA_EDITOR_FORMAT_MP4: {
1596                         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
1597                         TagLib::MP4::Tag* tag = _file->tag();
1598                         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Tag does not exist");
1599
1600                         // Get map of items directly from tag and launch a search of specific item
1601                         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
1602                         TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
1603                         if (it != itemMap.end()) {                                                              // Item was found
1604                                 TagLib::MP4::CoverArtList lst = it->second.toCoverArtList();
1605                                 // Check if the index is in range of CoverArtList Item
1606                                 if ((index < 0) || ((uint)index >= lst.size())) {                               // it is not
1607                                         metadata_editor_error("Index of picture is out of range");
1608                                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1609                                 } else {                                                                        // index is in range
1610                                         int i = 0;
1611                                         for (TagLib::MP4::CoverArtList::ConstIterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i) {
1612                                                 if (i != index) continue;
1613                                                 int pictureSize = picIt->data().size();
1614                                                 metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
1615                                                 META_MALLOC(*picture, pictureSize);
1616                                                 metadata_editor_retvm_if(*picture == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
1617
1618                                                 memcpy(*picture, picIt->data().data(), pictureSize);
1619                                                 *size = pictureSize;
1620                                                 if (picIt->format() == TagLib::MP4::CoverArt::JPEG)     *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
1621                                                 else if (picIt->format() == TagLib::MP4::CoverArt::PNG) *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
1622                                                 else                                                    *mime_type = NULL;
1623                                                 break;
1624                                         }
1625                                         return METADATA_EDITOR_ERROR_NONE;
1626                                 }
1627                         } else {                                                                                // Item was not found - no pictures in file
1628                                 metadata_editor_error("No item <covr> in file. No pictures in file");
1629                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1630                         }
1631                 }
1632 #if 0
1633                 case METADATA_EDITOR_FORMAT_FLAC: {
1634                         TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
1635                         TagLib::List<TagLib::FLAC::Picture*> lst = _file->pictureList();
1636                         if (lst.isEmpty()) {
1637                                 metadata_editor_error("No pictures in FLAC file");
1638                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1639                         } else {
1640                                 // Check if the index is in range of CoverArtList Item
1641                                 if ((index < 0) || ((uint)index >= lst.size())) {                       // it is not
1642                                         metadata_editor_error("Index of picture is out of range");
1643                                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1644                                 } else {                                                                                                        // index is in range
1645                                         // Consecutive check of all pictures until the desired one is found
1646                                         int i = 0;
1647                                         for (TagLib::List<TagLib::FLAC::Picture*>::ConstIterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i) {
1648                                                 if (i != index) continue;
1649                                                 // picture can be received as ByteVector (picIt->data()).
1650                                                 // ByteVector has data() - picture itself and size() - the size of picture in data() method
1651                                                 int pictureSize = (*picIt)->data().size();
1652                                                 metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
1653                                                 META_MALLOC(*picture, pictureSize);
1654                                                 metadata_editor_retvm_if(*picture == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
1655
1656                                                 memcpy(*picture, (*picIt)->data().data(), pictureSize);
1657                                                 *size = pictureSize;
1658                                                 TagLib::String mime = (*picIt)->mimeType();
1659                                                 if (!strcmp(mime.toCString(), "image/jpeg"))
1660                                                         *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
1661                                                 else if (!strcmp(mime.toCString(), "image/png"))
1662                                                         *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
1663                                                 else
1664                                                         *mime_type = NULL;
1665                                                 break;
1666                                         }
1667                                         return METADATA_EDITOR_ERROR_NONE;
1668                                 }
1669                         }
1670                 }
1671                 case METADATA_EDITOR_FORMAT_WAV: {
1672                         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;             // Bring the pointer to actual file type
1673                         TagLib::ID3v2::Tag* tag2 = _file->tag();
1674                         if (!tag2) {
1675                                 metadata_editor_error("No ID3v2 tag in file");
1676                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1677                         }
1678                         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
1679                         // Check if there are pictures in the tag
1680                         if (lst.isEmpty()) {
1681                                 metadata_editor_error("No pictures in file");
1682                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1683                         } else {                                                // pictures exist in file
1684                                 // Check if index is correct or not
1685                                 if ((index < 0) || (lst.size() <= (uint)index)) {
1686                                         metadata_editor_error("Index of picture is out of range");
1687                                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1688                                 } else {                                        // everything is correct - begin extraction
1689                                         metadata_editor_info("There are %u pictures in file. Start of picture number %d extraction", lst.size(), index);
1690                                         int i = 0;
1691                                         // Among all frames we must choose that one with specified index. "i" will be counter
1692                                         for (TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i) {
1693                                                 if (i != index) continue;
1694                                                 TagLib::ID3v2::AttachedPictureFrame* pictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
1695                                                 uint pictureSize = pictureFrame->picture().size();
1696                                                 metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
1697
1698                                                 META_MALLOC(*picture, pictureSize);
1699                                                 metadata_editor_retvm_if(*picture == NULL, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
1700
1701                                                 memcpy(*picture, pictureFrame->picture().data(), pictureSize);
1702                                                 *size = pictureSize;
1703                                                 TagLib::String mime = pictureFrame->mimeType();
1704                                                 if (!strcmp(mime.toCString(), "image/jpeg"))
1705                                                         *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
1706                                                 else if (!strcmp(mime.toCString(), "image/png"))
1707                                                         *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
1708                                                 else
1709                                                         *mime_type = NULL;
1710                                                 break;
1711                                         }
1712                                         return METADATA_EDITOR_ERROR_NONE;
1713                                 }
1714                         }
1715                 }
1716 #endif
1717                 default:
1718                         metadata_editor_error("Wrong file type");
1719                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1720         }
1721 }
1722
1723 // *** This function appends a cover art picture to the file *** //
1724 extern "C" int metadata_editor_append_picture(metadata_editor_h metadata, const char *path) {
1725         int ret = METADATA_EDITOR_ERROR_NONE;
1726         void *picture = NULL;
1727         int size = 0;
1728         char *type = NULL;
1729
1730         metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
1731
1732         ret = __check_metadata_set_parameter(_metadata);
1733         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1734         metadata_editor_retvm_if(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
1735
1736         ret = __metadata_editor_get_picture_info(path, &picture, &size, &type);
1737         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File does not exist or you have no rights to open it");
1738
1739         switch (_metadata->filetype) {                                  // Process the file according to the specified file type
1740                 case METADATA_EDITOR_FORMAT_MP3: {
1741                         // Bring the pointer to actual file type and make tags pointers
1742                         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
1743                         TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag(true);
1744                         // Check if the valid tag pointer exists
1745                         if (tag2 == NULL) {
1746                                 metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating");
1747                                 ret = METADATA_EDITOR_ERROR_OPERATION_FAILED;
1748                                 break;
1749                         }
1750                         TagLib::ID3v2::AttachedPictureFrame* pictureFrame = new TagLib::ID3v2::AttachedPictureFrame();
1751                         if (pictureFrame == NULL) {
1752                                 metadata_editor_error("OUT_OF_MEMORY");
1753                                 ret = METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
1754                                 break;
1755                         }
1756                         metadata_editor_info("New APIC frame will be added to the ID3v2 tag");
1757                         pictureFrame->setPicture(TagLib::ByteVector((char*)picture, size));
1758                         pictureFrame->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
1759                         pictureFrame->setMimeType(type);
1760
1761                         tag2->addFrame(pictureFrame);
1762
1763                         ret = METADATA_EDITOR_ERROR_NONE;
1764                         break;
1765                 }
1766                 case METADATA_EDITOR_FORMAT_MP4: {
1767                         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
1768                         TagLib::MP4::Tag* tag = _file->tag();
1769                         if (!tag) {
1770                                 metadata_editor_error("Tag was not created");
1771                                 ret = METADATA_EDITOR_ERROR_OPERATION_FAILED;
1772                                 break;
1773                         }
1774
1775                         // Get map of items directly from tag and launch a search of specific item
1776                         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
1777                         TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
1778                         if (it != itemMap.end()) {                                                                      // Item was found
1779                                 metadata_editor_info("The item <covr> exists. Adding picture");
1780                                 TagLib::MP4::CoverArtList lst = it->second.toCoverArtList();
1781                                 TagLib::MP4::CoverArt::Format format;
1782                                 if (strncmp(type, "image/jpeg", strlen("image/jpeg")) == 0)
1783                                         format = TagLib::MP4::CoverArt::JPEG;
1784                                 else if (strncmp(type, "image/png", strlen("image/jpeg")) == 0)
1785                                         format = TagLib::MP4::CoverArt::PNG;
1786                                 else
1787                                         format = (TagLib::MP4::CoverArt::Format)0xFFFF;
1788                                 TagLib::MP4::CoverArt cover(format, TagLib::ByteVector((char*)picture, size));
1789                                 lst.append(cover);
1790                                 itemMap.insert("covr", TagLib::MP4::Item(lst));
1791
1792                                 ret = METADATA_EDITOR_ERROR_NONE;
1793                                 break;
1794                         } else {                                                                                        // Item was not found
1795                                 metadata_editor_info("The item <covr> does not exist. Adding picture");
1796                                 TagLib::MP4::CoverArt::Format format;
1797                                 if (strncmp(type, "image/jpeg", strlen("image/jpeg")) == 0)
1798                                         format = TagLib::MP4::CoverArt::JPEG;
1799                                 else if (strncmp(type, "image/png", strlen("image/jpeg")) == 0)
1800                                         format = TagLib::MP4::CoverArt::PNG;
1801                                 else
1802                                         format = (TagLib::MP4::CoverArt::Format)0xFFFF;
1803                                 TagLib::MP4::CoverArt cover(format, TagLib::ByteVector((char*)picture, size));
1804                                 TagLib::MP4::CoverArtList lst;
1805                                 lst.append(cover);
1806                                 itemMap.insert("covr", TagLib::MP4::Item(lst));
1807
1808                                 ret = METADATA_EDITOR_ERROR_NONE;
1809                                 break;
1810                         }
1811                 }
1812 #if 0
1813                 case METADATA_EDITOR_FORMAT_FLAC: {
1814                         TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
1815                         TagLib::FLAC::Picture* frontCover = new TagLib::FLAC::Picture;
1816                         if (frontCover == NULL) {
1817                                 metadata_editor_error("OUT_OF_MEMORY");
1818                                 ret = METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
1819                                 break;
1820                         }
1821                         frontCover->setData(TagLib::ByteVector((char*)picture, size));
1822                         frontCover->setType(TagLib::FLAC::Picture::FrontCover);
1823                         frontCover->setMimeType(type);
1824
1825                         metadata_editor_info("Picture will be added to FLAC file");
1826                         _file->addPicture(frontCover);
1827                         ret = METADATA_EDITOR_ERROR_NONE;
1828                         break;
1829                 }
1830                 case METADATA_EDITOR_FORMAT_WAV: {
1831                         // Bring the pointer to actual file type and make tags pointers
1832                         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
1833                         TagLib::ID3v2::Tag* tag2 = _file->tag();
1834                         // Check if the valid tag pointer exists
1835                         if (tag2 == NULL) {
1836                                 metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating");
1837                                 ret = METADATA_EDITOR_ERROR_OPERATION_FAILED;
1838                                 break;
1839                         }
1840                         TagLib::ID3v2::AttachedPictureFrame* pictureFrame = new TagLib::ID3v2::AttachedPictureFrame();
1841                         if (pictureFrame == NULL) {
1842                                 metadata_editor_error("OUT_OF_MEMORY");
1843                                 ret = METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
1844                                 break;
1845                         }
1846                         metadata_editor_info("New APIC frame will be added to the ID3v2 tag");
1847                         pictureFrame->setPicture(TagLib::ByteVector((char*)picture, size));
1848                         pictureFrame->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
1849                         pictureFrame->setMimeType(type);
1850                         tag2->addFrame(pictureFrame);
1851                         ret = METADATA_EDITOR_ERROR_NONE;
1852                         break;
1853                 }
1854 #endif
1855                 default: {
1856                         metadata_editor_error("Wrong file type");
1857                         ret = METADATA_EDITOR_ERROR_NOT_SUPPORTED;
1858                         break;
1859                 }
1860         }
1861
1862         META_SAFE_FREE(picture);
1863         META_SAFE_FREE(type);
1864
1865         return ret;
1866 }
1867
1868 // *** This function is used to delete picture with specified index *** //
1869 extern "C" int metadata_editor_remove_picture(metadata_editor_h metadata, int index) {
1870         int ret = METADATA_EDITOR_ERROR_NONE;
1871         metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
1872
1873         ret = __check_metadata_set_parameter(_metadata);
1874         metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
1875
1876         switch (_metadata->filetype) {                                  // Process the file according to the specified file type
1877                 case METADATA_EDITOR_FORMAT_MP3: {
1878                         // Bring the pointer to actual file type and make tags pointers
1879                         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
1880                         TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag(true);
1881                         // Check if the valid tag pointer exists
1882                         metadata_editor_retvm_if(tag2 == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
1883                         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
1884                         // Check if there are pictures in the tag
1885                         metadata_editor_retvm_if(lst.isEmpty(), METADATA_EDITOR_ERROR_OPERATION_FAILED, "No pictures in file");
1886
1887                         // Check if index is correct or not
1888                         metadata_editor_retvm_if((index < 0) || (lst.size() <= (uint)index), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Index of picture is out of range");
1889                         metadata_editor_info("Removing of picture number %d", index);
1890                         int i = 0;
1891                         // Among all frames we must choose that one with specified index. "i" will be counter
1892                         for (TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i) {
1893                                 if (i != index) continue;
1894                                 tag2->removeFrame(*it);
1895                                 break;
1896                         }
1897                         return METADATA_EDITOR_ERROR_NONE;
1898                 }
1899                 case METADATA_EDITOR_FORMAT_MP4: {
1900                         TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
1901                         TagLib::MP4::Tag* tag = _file->tag();
1902                         metadata_editor_retvm_if(tag == NULL, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. tag not exist.");
1903
1904                         // Get map of items directly from tag and launch a search of specific item
1905                         TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
1906                         TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
1907                         if (it != itemMap.end()) {                                                                      // Item was found
1908                                 TagLib::MP4::CoverArtList lst = it->second.toCoverArtList();
1909                                 // Check if the index is in range of CoverArtList Item
1910                                 if ((index < 0) || ((uint)index >= lst.size())) {                                       // it is not
1911                                         metadata_editor_error("Index of picture is out of range");
1912                                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1913                                 } else {                                                                                // index is in range
1914                                         metadata_editor_info("The picture number %d will be deleted", index);
1915                                         int i = 0;
1916                                         for (TagLib::MP4::CoverArtList::Iterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i) {
1917                                                 if (i != index) continue;
1918                                                 lst.erase(picIt);
1919                                                 break;
1920                                         }
1921                                         itemMap.insert("covr", TagLib::MP4::Item(lst));
1922                                         return METADATA_EDITOR_ERROR_NONE;
1923                                 }
1924                         } else {                                // Item was not found
1925                                 metadata_editor_error("The item <covr> does not exist. Nothing to delete");
1926                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1927                         }
1928                 }
1929 #if 0
1930                 case METADATA_EDITOR_FORMAT_FLAC: {
1931                         TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
1932                         TagLib::List<TagLib::FLAC::Picture*> lst = _file->pictureList();
1933                         if (lst.isEmpty()) {
1934                                 metadata_editor_error("No pictures in file. Nothing to delete");
1935                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1936                         }
1937                         // Check if the index is in range of CoverArtList Item
1938                         if ((index < 0) || ((uint)index >= lst.size())) {                                               // it is not
1939                                 metadata_editor_error("Index of picture is out of range");
1940                                 return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1941                         } else {                                                                                        // index is in range
1942                                 metadata_editor_info("The picture number %d will be deleted", index);
1943                                 int i = 0;
1944                                 for (TagLib::List<TagLib::FLAC::Picture*>::Iterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i) {
1945                                         if (i != index) continue;
1946                                         _file->removePicture(*picIt, true);
1947                                         break;
1948                                 }
1949                                 return METADATA_EDITOR_ERROR_NONE;
1950                         }
1951                 }
1952                 case METADATA_EDITOR_FORMAT_WAV: {
1953                         // Bring the pointer to actual file type and make tags pointers
1954                         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
1955                         TagLib::ID3v2::Tag* tag2 = _file->tag();
1956                         // Check if the valid tag pointer exists
1957                         if (tag2 == NULL) {
1958                                 metadata_editor_error("Error. ID3v2 tag does not exist. Can not remove picture");
1959                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1960                         }
1961                         TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
1962                         // Check if there are pictures in the tag
1963                         if (lst.isEmpty()) {
1964                                 metadata_editor_error("No pictures in file");
1965                                 return METADATA_EDITOR_ERROR_OPERATION_FAILED;
1966                         } else {                // pictures exist in file
1967                                 // Check if index is correct or not
1968                                 if ((index < 0) || (lst.size() <= (uint)index)) {
1969                                         metadata_editor_error("Index of picture is out of range");
1970                                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1971                                 } else {                // everything is correct - begin extraction
1972                                         metadata_editor_info("Removing of picture number %d", index);
1973                                         int i = 0;
1974                                         // Among all frames we must choose that one with specified index. "i" will be counter
1975                                         for (TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i) {
1976                                                 if (i != index) continue;
1977                                                 tag2->removeFrame(*it);
1978                                                 break;
1979                                         }
1980                                         return METADATA_EDITOR_ERROR_NONE;
1981                                 }
1982                         }
1983                 }
1984 #endif
1985                 default:
1986                         metadata_editor_error("Wrong file type");
1987                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
1988         }
1989 }
1990
1991 // *** This function is used to free memory that was allocated with metadata_editor_create(...) and metadata_editor_set_path(...) functions *** //
1992 extern "C" int metadata_editor_destroy(metadata_editor_h metadata) {
1993         metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
1994         metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
1995
1996         switch (_metadata->filetype) {
1997                 case METADATA_EDITOR_FORMAT_MP3: {
1998                         // Bring the pointer to actual file type
1999                         TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
2000                         metadata_editor_info("file free [%p]", _metadata->file);
2001                         delete _file;
2002                         break;
2003                 }
2004                 case METADATA_EDITOR_FORMAT_MP4: {
2005                         TagLib::MP4::File* _file = (TagLib::MP4::File*)_metadata->file;
2006                         metadata_editor_info("file free [%p]", _metadata->file);
2007                         delete _file;
2008                         break;
2009                 }
2010 #if 0
2011                 case METADATA_EDITOR_FORMAT_FLAC: {
2012                         TagLib::FLAC::File* _file = (TagLib::FLAC::File*)_metadata->file;
2013                         metadata_editor_info("file free [%p]", _metadata->file);
2014                         delete _file;
2015                         break;
2016                 }
2017                 case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
2018                         TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)_metadata->file;
2019                         metadata_editor_info("file free [%p]", _metadata->file);
2020                         delete _file;
2021                         break;
2022                 }
2023                 case METADATA_EDITOR_FORMAT_OGG_FLAC: {
2024                         TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)_metadata->file;
2025                         metadata_editor_info("file free [%p]", _metadata->file);
2026                         delete _file;
2027                         break;
2028                 }
2029                 case METADATA_EDITOR_FORMAT_WAV: {
2030                         TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
2031                         metadata_editor_info("file free [%p]", _metadata->file);
2032                         delete _file;
2033                         break;
2034                 }
2035 #endif
2036                 default:
2037                         metadata_editor_error("Wrong file type");
2038                         return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
2039         }
2040
2041         metadata_editor_info("<metadata_editor_s> with address %p will be freed", metadata);
2042         delete _metadata;
2043
2044         return METADATA_EDITOR_ERROR_NONE;
2045 }