Initialize package. 73/40473/1
authorMinje Ahn <minje.ahn@samsung.com>
Thu, 4 Jun 2015 06:35:34 +0000 (15:35 +0900)
committerMinje Ahn <minje.ahn@samsung.com>
Thu, 4 Jun 2015 06:35:34 +0000 (15:35 +0900)
Change-Id: I43c4bd62fcdb33616e4ccd2b7c04fc8ee81af992
Signed-off-by: Minje Ahn <minje.ahn@samsung.com>
14 files changed:
AUTHORS [new file with mode: 0755]
CMakeLists.txt [new file with mode: 0755]
LICENSE.APLv2.0 [new file with mode: 0755]
NOTICE [new file with mode: 0755]
capi-media-metadata-editor.manifest [new file with mode: 0755]
capi-media-metadata-editor.pc.in [new file with mode: 0755]
doc/metadata_editor_doc.h [new file with mode: 0755]
include/metadata_editor.h [new file with mode: 0755]
include/metadata_editor_private.h [new file with mode: 0755]
include/metadata_editor_type.h [new file with mode: 0755]
packaging/capi-media-metadata-editor.spec [new file with mode: 0755]
src/metadata_editor.cpp [new file with mode: 0755]
test/CMakeLists.txt [new file with mode: 0755]
test/metadata_editor_test.c [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
new file mode 100755 (executable)
index 0000000..4fe6589
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Haejeong Kim <backto.kim at samsung dot com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..89c2122
--- /dev/null
@@ -0,0 +1,97 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_name "capi-media-metadata-editor")
+
+# project
+SET(prefix "/usr")
+SET(version "0.0.1")
+SET(maintainer "Haejeong Kim <backto.kim@samsung.com>")
+SET(description "A Metadata Editor library in Tizen Native API")
+SET(service "metadata-editor")
+
+# for package file
+SET(dependents "dlog capi-base-common taglib aul")
+
+PROJECT(${fw_name} C CXX)
+
+SET(CMAKE_INSTALL_PREFIX ${prefix})
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(VERSION ${version})
+
+SET(INC_DIR include)
+INCLUDE_DIRECTORIES(${INC_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_name} REQUIRED ${dependents})
+FOREACH(flag ${${fw_name}_CFLAGS})
+    SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -fPIC -Wall")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+
+IF("${ARCH}" MATCHES "^arm.*")
+    ADD_DEFINITIONS("-DTARGET")
+ENDIF("${ARCH}" MATCHES "^arm.*")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DTIZEN_DEBUG")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib")
+
+aux_source_directory(src SOURCES)
+ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+
+TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS})
+
+INSTALL(TARGETS ${fw_name} DESTINATION lib)
+INSTALL(
+        DIRECTORY ${INC_DIR}/ DESTINATION include/${service}
+        FILES_MATCHING
+        PATTERN "*_private.h" EXCLUDE
+        PATTERN "${INC_DIR}/*.h"
+        )
+
+SET(PC_NAME ${fw_name})
+SET(PC_REQUIRED ${dependents})
+SET(PC_LDFLAGS -l${fw_name})
+
+CONFIGURE_FILE(
+    ${fw_name}.pc.in
+    ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc
+    @ONLY
+)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION lib/pkgconfig)
+
+ADD_SUBDIRECTORY(test)
+
+IF(UNIX)
+
+ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
+ADD_CUSTOM_COMMAND(
+        DEPENDS clean
+        COMMENT "distribution clean"
+        COMMAND find
+        ARGS    .
+        -not -name config.cmake -and \(
+        -name tester.c -or
+        -name Testing -or
+        -name CMakeFiles -or
+        -name cmake.depends -or
+        -name cmake.check_depends -or
+        -name CMakeCache.txt -or
+        -name cmake.check_cache -or
+        -name *.cmake -or
+        -name Makefile -or
+        -name core -or
+        -name core.* -or
+        -name gmon.out -or
+        -name install_manifest.txt -or
+        -name *.pc -or
+        -name *~ \)
+        | grep -v TC | xargs rm -rf
+        TARGET  distclean
+        VERBATIM
+)
+
+ENDIF(UNIX)
diff --git a/LICENSE.APLv2.0 b/LICENSE.APLv2.0
new file mode 100755 (executable)
index 0000000..261eeb9
--- /dev/null
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/NOTICE b/NOTICE
new file mode 100755 (executable)
index 0000000..ccdad52
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
diff --git a/capi-media-metadata-editor.manifest b/capi-media-metadata-editor.manifest
new file mode 100755 (executable)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/capi-media-metadata-editor.pc.in b/capi-media-metadata-editor.pc.in
new file mode 100755 (executable)
index 0000000..b8a69f8
--- /dev/null
@@ -0,0 +1,13 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=/usr/lib
+includedir=/usr/include/metadata-editor
+
+Name: @PC_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @VERSION@
+Requires: @PC_REQUIRED@
+Libs: -L${libdir} @PC_LDFLAGS@
+Cflags: -I${includedir} @PC_CFLAGS@
diff --git a/doc/metadata_editor_doc.h b/doc/metadata_editor_doc.h
new file mode 100755 (executable)
index 0000000..30b2c93
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __TIZEN_METADATA_EDITOR_DOC_H__
+#define __TIZEN_METADATA_EDITOR_DOC_H__
+
+/**
+ * @file metadata_editor_doc.h
+ * @brief File contains the high level documentation for the Metadata Editor API.
+ *
+ */
+
+/**
+ * @defgroup CAPI_MEDIA_METADATA_EDITOR_MODULE Metadata Editor
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_METADATA_EDITOR_MODULE
+ * @brief The @ref CAPI_MEDIA_METADATA_EDITOR_MODULE API provides functions for editing the metadata of several popular audio format.
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+  * @section CAPI_MEDIA_METADATA_EDITOR_MODULE_HEADER Required Header
+ *    \#include <metadata_editor.h>
+ *
+ * @section CAPI_MEDIA_METADATA_EDITOR_OVERVIEW Overview
+ * The @ref CAPI_MEDIA_METADATA_EDITOR_MODULE API allows you to read the metadata from a media file(#metadata_editor_get_metadata()). To edit a metadata(#metadata_editor_set_metadata()), create/destory the handle(#metadata_editor_create()/#metadata_editor_destroy), and append/ remove a picture in the metadata(#metadata_editor_append_picture()/ #metadata_editor_remove_picture()).
+ */
+
+#endif /* __TIZEN_METADATA_EDITOR_DOC_H__ */
+
+
diff --git a/include/metadata_editor.h b/include/metadata_editor.h
new file mode 100755 (executable)
index 0000000..1a038f6
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+* Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __TIZEN_METADATA_EDITOR_H__
+#define __TIZEN_METADATA_EDITOR_H__
+
+
+#include <metadata_editor_type.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @addtogroup CAPI_MEDIA_METADATA_EDITOR_MODULE
+ * @{
+ *
+ * @file metadata_editor.h
+ * @brief This file contains the API for metadata of several popular audio formats and related structure and enumeration. \n
+ *        Description of metadata: title, album, artist, author, genre and description etc. \n
+ */
+
+
+/**
+ * @brief Create metadata
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a metadata using metadata_editor_destroy().
+ *
+ * @param [in] metadata The handle to metadata
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @see metadata_editor_destroy()
+ */
+int metadata_editor_create(metadata_editor_h *metadata);
+
+
+/**
+ * @brief Set file path to read or write metadata
+ * @since_tizen 2.4
+ *
+ * @remarks In case of accessing specific path in internal storage or external storage, you may add the privilege for accessing the path. \n
+ *                   For example, if you get the specific path by using storage_get_directory(). you should add previlege http://tizen.org/privilege/mediastorage or http://tizen.org/privilege/externalstorage.
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] path path to read or write metadata
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_FILE_EXISTS File not exist
+ * @retval #METADATA_EDITOR_ERROR_NOT_SUPPORTED unsupported file type
+ * @retval #METADATA_EDITOR_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @pre Create metadata handle by calling metadata_editor_create()
+ * @see metadata_editor_create(), metadata_editor_destroy()
+ */
+int metadata_editor_set_path(metadata_editor_h metadata, const char *path);
+
+
+/**
+ * @brief Get the metadata corresponding to the attribute.
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a value using @c free(). \n
+ *                   If the attribute value of the metadata is empty, return value is NULL. \n
+ *                   In case of accessing specific path in internal storage or external storage, you may add the privilege for accessing the path. \n
+ *                   For example, if you get the specific path by using storage_get_directory(). you should add previlege http://tizen.org/privilege/mediastorage or http://tizen.org/privilege/externalstorage.
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] attribute key attribute name to get
+ * @param [out] value The value of the attribute
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #METADATA_EDITOR_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @pre Set path to read or write metadata by calling metadata_editor_set_path()
+ * @see metadata_editor_create(), metadata_editor_destroy()
+ */
+int metadata_editor_get_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, char **value);
+
+
+/**
+ * @brief Set the attribute of the metadata.
+ * @since_tizen 2.4
+ * @details This function set the attribute of the metadata for updating the metadata. \n
+ *
+ * @remarks You must release @a value using @c free(). \n
+ *                  You must call metadata_editor_update_metadata() for applying to the metadata of the media file. if not, you will see the existing metadata when you call metadata_editor_get_metadata().
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] attribute key attribute name to get
+ * @param [int] value The value of the attribute
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @pre Set path to read or write metadata by calling metadata_editor_set_path()
+ * @see metadata_editor_create(), metadata_editor_update_metadata(), metadata_editor_destroy()
+ */
+int metadata_editor_set_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, const char *value);
+
+
+/**
+ * @brief Update the modified metadata
+ * @since_tizen 2.4
+ * @details This function update the metadata in the media file that is modified by metadata_editor_set_metadata().
+ *
+ * @remarks In case of accessing specific path in internal storage or external storage, you may add the privilege for accessing the path. \n
+ *                   For example, if you get the specific path by using storage_get_directory(). you should add previlege http://tizen.org/privilege/mediastorage or http://tizen.org/privilege/externalstorage.
+ *
+ * @param [in] metadata The handle to metadata
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #METADATA_EDITOR_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @pre Set path to read or write metadata by calling metadata_editor_set_path()
+ * @see metadata_editor_create(), metadata_editor_destroy()
+ */
+int metadata_editor_update_metadata(metadata_editor_h metadata);
+
+/**
+ * @brief Get the picture in the media file
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a picture using @c free(). \n
+ *                   In case of accessing specific path in internal storage or external storage, you may add the privilege for accessing the path. \n
+ *                   For example, if you get the specific path by using storage_get_directory(). you should add previlege http://tizen.org/privilege/mediastorage or http://tizen.org/privilege/externalstorage.
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] index picture order
+ * @param [out] picture encoded picture
+ * @param [out] size encoded picture size
+ * @param [out] mime_type the mime type of picture
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @retval #METADATA_EDITOR_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Set path to read or write metadata by calling metadata_editor_set_path()
+ * @see metadata_editor_create(), metadata_editor_destroy()
+ */
+int metadata_editor_get_picture(metadata_editor_h metadata, int index, void **picture, int *size, char **mime_type);
+
+/**
+ * @brief Append the picture to the media file
+ * @since_tizen 2.4
+ *
+ * @remarks You must call metadata_editor_update_metadata() for applying to the metadata of the media file. if not, you will see the existing metadata when you call metadata_editor_get_metadata(). \n
+ *                   Image type of the metadata supports jpeg and png. \n
+ *                   In case of accessing specific path in internal storage or external storage, you may add the privilege for accessing the path. \n
+ *                   For example, if you get the specific path by using storage_get_directory(). you should add previlege http://tizen.org/privilege/mediastorage or http://tizen.org/privilege/externalstorage.
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] picture_path The path of picture for adding to the metadata
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #METADATA_EDITOR_ERROR_NOT_SUPPORTED unsupported file type
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @retval #METADATA_EDITOR_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Set path to read or write metadata by calling metadata_editor_set_path()
+ * @see metadata_editor_create(), metadata_editor_destroy()
+ */
+int metadata_editor_append_picture(metadata_editor_h metadata, const char *picture_path);
+
+/**
+ * @brief Remove artwork image from media file
+ * @since_tizen 2.4
+ *
+ * @remarks You must call metadata_editor_update_metadata() for applying to the metadata of the media file. if not, you will see the existing metadata when you call metadata_editor_get_metadata(). \n
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] index artwork image order
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @retval #METADATA_EDITOR_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Set path to read or write metadata by calling metadata_editor_set_path()
+ * @see metadata_editor_create(), metadata_editor_destroy()
+ */
+int metadata_editor_remove_picture(metadata_editor_h metadata, int index);
+
+/**
+ * @brief Destroy metadata
+ * @since_tizen 2.4
+ *
+ * @param [in] metadata The handle to metadata
+ * @return 0 on success, otherwise a negative error value
+ * @retval #METADATA_EDITOR_ERROR_NONE Successful
+ * @retval #METADATA_EDITOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #METADATA_EDITOR_ERROR_OPERATION_FAILED Internal Operation Fail
+ * @pre Create metadata handle by calling metadata_editor_create()
+ * @see metadata_editor_create()
+ */
+int metadata_editor_destroy(metadata_editor_h metadata);
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_METADATA_EDITOR_H__ */
diff --git a/include/metadata_editor_private.h b/include/metadata_editor_private.h
new file mode 100755 (executable)
index 0000000..2471416
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+#ifndef __TIZEN_METADATA_EDITOR_PRIVATE_H__
+#define __TIZEN_METADATA_EDITOR_PRIVATE_H__
+
+#include <iostream>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <dlog.h>
+#include <taglib/tag.h>
+#include <taglib/mpegfile.h>
+#include <taglib/mp4file.h>
+#include <taglib/flacfile.h>
+#include <taglib/oggflacfile.h>
+#include <taglib/vorbisfile.h>
+#include <taglib/wavfile.h>
+#include <taglib/id3v1tag.h>
+#include <taglib/id3v2tag.h>
+#include <taglib/mp4tag.h>
+#include <taglib/xiphcomment.h>
+#include <taglib/commentsframe.h>
+#include <taglib/textidentificationframe.h>
+#include <taglib/attachedpictureframe.h>
+#include <taglib/unsynchronizedlyricsframe.h>
+#include <taglib/mp4item.h>
+#include <taglib/mp4coverart.h>
+
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "CAPI_MEDIA_METADATA_EDITOR"
+
+#define metadata_editor_debug(fmt, arg...) do { \
+                       LOGD(""fmt"", ##arg);     \
+               } while (0)
+
+#define metadata_editor_info(fmt, arg...) do { \
+                       LOGI(""fmt"", ##arg);     \
+               } while (0)
+
+#define metadata_editor_error(fmt, arg...) do { \
+                       LOGE(""fmt"", ##arg);     \
+               } while (0)
+
+#define metadata_editor_debug_fenter() do { \
+                       LOGD("<Enter>");     \
+               } while (0)
+
+#define metadata_editor_debug_fleave() do { \
+                       LOGD("<Leave>");     \
+               } while (0)
+
+typedef struct
+{
+       void*   file;
+       int     filetype;
+       bool    isOpen;
+       bool    isReadOnly;
+} metadata_editor_s;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /*__TIZEN_METADATA_EDITOR_PRIVATE_H__*/
diff --git a/include/metadata_editor_type.h b/include/metadata_editor_type.h
new file mode 100755 (executable)
index 0000000..7755ce9
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+
+#ifndef __TIZEN_METADATA_EDITOR_TYPE_H__
+#define __TIZEN_METADATA_EDITOR_TYPE_H__
+
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/**
+* @addtogroup CAPI_MEDIA_METADATA_EDITOR_MODULE
+* @{
+*/
+
+/**
+ * @ingroup CAPI_MEDIA_METADATA_EDITOR_MODULE
+ * @brief The enumerations of media metadata error
+ * @since_tizen 2.4
+ */
+typedef enum
+{
+       METADATA_EDITOR_ERROR_NONE                              = TIZEN_ERROR_METADATA_EDITOR,                          /**< Successful */
+       METADATA_EDITOR_ERROR_INVALID_PARAMETER                 = TIZEN_ERROR_INVALID_PARAMETER,                /**< Invalid parameter */
+       METADATA_EDITOR_ERROR_OUT_OF_MEMORY                     = TIZEN_ERROR_OUT_OF_MEMORY,                    /**< Out of memory */
+       METADATA_EDITOR_ERROR_FILE_EXISTS                       = TIZEN_ERROR_FILE_EXISTS,                      /**< File not exist */
+       METADATA_EDITOR_ERROR_PERMISSION_DENIED         = TIZEN_ERROR_PERMISSION_DENIED,        /**< Permission denied */
+       METADATA_EDITOR_ERROR_NOT_SUPPORTED                             = TIZEN_ERROR_NOT_SUPPORTED,            /* Unsupported type */
+       METADATA_EDITOR_ERROR_OPERATION_FAILED                  = TIZEN_ERROR_METADATA_EDITOR |0x01,            /**< Invalid internal operation */
+} metadata_editor_error_e;
+
+
+/**
+ * @ingroup CAPI_MEDIA_METADATA_EDITOR_MODULE
+ * @brief The enumerations of attribute
+ * @since_tizen 2.4
+ */
+typedef enum
+{
+       METADATA_EDITOR_ATTR_ARTIST,                                    /**< Artist*/
+       METADATA_EDITOR_ATTR_TITLE,                                     /**< Title*/
+       METADATA_EDITOR_ATTR_ALBUM,                                     /**< Album*/
+       METADATA_EDITOR_ATTR_GENRE,                                     /**< Genre*/
+       METADATA_EDITOR_ATTR_AUTHOR,                                /**< Author*/
+       METADATA_EDITOR_ATTR_COPYRIGHT,                         /**< Copyright*/
+       METADATA_EDITOR_ATTR_DATE,                                      /**< Date*/
+       METADATA_EDITOR_ATTR_DESCRIPTION,                               /**< Description*/
+       METADATA_EDITOR_ATTR_COMMENT,                                   /**< Comment*/
+       METADATA_EDITOR_ATTR_TRACK_NUM,                         /**< Track number info*/
+       METADATA_EDITOR_ATTR_PICTURE_NUM,                       /**< Picture number*/
+       METADATA_EDITOR_ATTR_CONDUCTOR,                         /**< Conductor*/
+       METADATA_EDITOR_ATTR_UNSYNCLYRICS,                      /**< Unsynchronized lyric*/
+} metadata_editor_attr_e;
+
+/**
+ * @ingroup CAPI_MEDIA_METADATA_EDITOR_MODULE
+ * @brief The handle of media metadata
+ * @since_tizen 2.4
+ */
+typedef void * metadata_editor_h;
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /*__TIZEN_METADATA_EDITOR_TYPE_H__*/
diff --git a/packaging/capi-media-metadata-editor.spec b/packaging/capi-media-metadata-editor.spec
new file mode 100755 (executable)
index 0000000..919b74e
--- /dev/null
@@ -0,0 +1,52 @@
+Name:       capi-media-metadata-editor
+Summary:    A metadata editor library in SLP C API
+Version: 0.1.0
+Release:    0
+Group:      System/Libraries
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(capi-base-common)
+BuildRequires:  pkgconfig(taglib)
+BuildRequires:  pkgconfig(aul)
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description
+A metadata editor library in SLP C API
+
+%package devel
+Summary:  A metadata editor library in SLP C API (Development)
+Group:    TO_BE/FILLED_IN
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+A metadata editor library in SLP C API
+
+%prep
+%setup -q
+
+%build
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/%{_datadir}/license
+cp -rf %{_builddir}/%{name}-%{version}/LICENSE.APLv2.0 %{buildroot}/%{_datadir}/license/%{name}
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%manifest capi-media-metadata-editor.manifest
+%{_libdir}/libcapi-media-metadata-editor.so
+%{_datadir}/license/%{name}
+
+%files devel
+%{_includedir}/metadata-editor/*.h
+%{_libdir}/pkgconfig/capi-media-metadata-editor.pc
diff --git a/src/metadata_editor.cpp b/src/metadata_editor.cpp
new file mode 100755 (executable)
index 0000000..132aeb0
--- /dev/null
@@ -0,0 +1,2772 @@
+/*
+* Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <metadata_editor.h>
+#include <metadata_editor_private.h>
+#include <aul.h>
+
+static int __ID3_getTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value);
+static int __ID3_setTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value);
+static int __ID3_getFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value);
+static int __ID3_setFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value);
+static int __ID3_getNumberOfPictures(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value);
+static int __ID3_getLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value);
+static int __ID3_setTwixCommentFrame(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* value);
+static int __ID3_setLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* value);
+static int __MP4_getStringItem(metadata_editor_s* _metadata, const char* itemname, char** value);
+static int __MP4_getIntegerItem(metadata_editor_s* _metadata, const char* itemname, char** value);
+static int __MP4_updateStringItem(metadata_editor_s* _metadata, const char* itemname, const char* value);
+static int __MP4_updateIntegerItem(metadata_editor_s* _metadata, const char* itemname, const char* value);
+static int __MP4_getNumberOfPictures(metadata_editor_s* _metadata, char** value);
+static int __xiph_getFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, char** value);
+static int __xiph_updateFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, const char* value);
+static int __FLAC_getNumberOfPictures(metadata_editor_s* _metadata, char** value);
+
+typedef enum
+{
+       METADATA_EDITOR_FORMAT_MP3      = 0,                            /**< MP3 File */
+       METADATA_EDITOR_FORMAT_MP4 = 1,                         /**< MP4 File */
+       METADATA_EDITOR_FORMAT_FLAC,                               /**< FLAC File */
+       METADATA_EDITOR_FORMAT_OGG_VORBIS,                         /**< Vorbis Audio in Ogg container */
+       METADATA_EDITOR_FORMAT_OGG_FLAC,                           /**< FLAC Audio in Ogg container */
+       METADATA_EDITOR_FORMAT_WAV,                                /**< WAV file */
+       METADATA_EDITOR_FORMAT_NOTYPE = 0xFF                    /**< Error type. File type is not correct or not specified */
+} metadata_editor_format_e;
+
+
+// *** This is an auxiliary function that is used to get the frame value *** //
+// *** It operates with frames that exists both in ID3v1 and ID3v2 tags  *** //
+static int __ID3_getTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value)
+{
+       // Check if we have valid arguments to work with
+       if((_metadata == NULL) || (frameID == NULL))
+       {
+               metadata_editor_error("INVALID PARAMETER\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       // Check if the frame is empty (nothing to read) or ID3v2 tag does not exist
+       if(!tag2 || tag2->frameListMap()[frameID].isEmpty())
+       {
+               metadata_editor_info("The frame %s in ID3v2 tag is empty\n", frameID);
+               // Check if the tag ID3v1 is also empty or does not exist
+               if(!tag1 || tag1->isEmpty())
+               {
+                       *value = NULL;
+                       metadata_editor_info("The frame %s in ID3v1 tag is empty as well\n", frameID);
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               else // if not - read the frame you need there
+               {
+                       metadata_editor_info("Reading data from ID3v1 tag\n");
+
+                       TagLib::String str;
+                       uint length;
+                       bool found = false;
+
+                       if(!strcmp(frameID, "TPE1"))                    // artist
+                       {
+                               str = tag1->artist(); found = true;
+                       }
+                       else if(!strcmp(frameID, "TALB"))               // album
+                       {
+                               str = tag1->album(); found = true;
+                       }
+                       else if(!strcmp(frameID, "COMM"))               // comment
+                       {
+                               str = tag1->comment(); found = true;
+                       }
+                       else if(!strcmp(frameID, "TCON"))               // genre
+                       {
+                               str = tag1->genre(); found = true;
+                       }
+                       else if(!strcmp(frameID, "TIT2"))               // title
+                       {
+                               str = tag1->title(); found = true;
+                       }
+                       // Check if we have already found the frame
+                       if(found)
+                       {
+                               bool isUTF = false;
+                               if(!str.isLatin1()) isUTF = true;
+                               metadata_editor_info("String is %sUTF\n", (isUTF ? "" : "not "));
+                               length = strlen(str.toCString(isUTF));
+                               if(length == 0)
+                               {
+                                       *value = NULL;
+                                       metadata_editor_info("Empty string...\n");
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                               *value = new char[length + 1];
+                               if(*value == NULL)
+                               {
+                                       metadata_editor_error("OUT_OF_MEMORY\n");
+                                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                               }
+                               strcpy(*value, str.toCString(isUTF));
+                               return METADATA_EDITOR_ERROR_NONE;
+                       }
+
+                       uint size = 20;
+                       char buf[size];
+
+                       if(!strcmp(frameID, "TRCK"))                    // track
+                       {
+                               // Convert int into char[]
+                               snprintf(buf, size, "%u", tag1->track()); found = true;
+                       }
+                       else if(!strcmp(frameID, "TDRC"))               // data (year)
+                       {
+                               // Convert int into char[]
+                               snprintf(buf, size, "%u", tag1->year()); found = true;
+                       }
+                       if(found)
+                       {
+                               length = strlen(buf);
+                               if(length == 0)
+                               {
+                                       *value = NULL;
+                                       metadata_editor_info("Empty string...\n");
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                               *value = new char[length + 1];
+                               if(*value == NULL)
+                               {
+                                       metadata_editor_error("OUT_OF_MEMORY\n");
+                                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                               }
+                               strcpy(*value, buf);
+                               return METADATA_EDITOR_ERROR_NONE;
+                       }
+                       // The desired frame was not found
+                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+       }
+       else                                // or frame has data to read
+       {
+               metadata_editor_info("The frame %s exists in ID3v2 tag\n", frameID);
+               // This string is used to copy the value in the frame
+               TagLib::String str = tag2->frameListMap()[frameID][0]->toString();
+               bool isUTF = false;
+               if(!str.isLatin1()) isUTF = true;
+               metadata_editor_info("String is %sUTF\n", (isUTF ? "" : "not "));
+               uint length = strlen(str.toCString(isUTF));
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               // Allocate the memory and copy the value to this memory
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, str.toCString(isUTF));
+
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This is an auxiliary function that is used to write the new value to the frame *** //
+// *** It operates with frames that exists both in ID3v1 and ID3v2 tags               *** //
+static int __ID3_setTwixFrameByName(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value)
+{
+       // Check if we have valid arguments to work with
+       if((_metadata == NULL) || (frameID == NULL))
+       {
+               metadata_editor_error("INVALID PARAMETER\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Check if the valid tag pointer exists
+       if(tag2 == NULL)
+       {
+               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+       // If the pointer is NULL or c-string is empty - handle as request for deletion
+       if(!value || (*value == '\0'))
+       {
+               metadata_editor_info("Request for frame %s deletion\n", frameID);
+               tag2->removeFrames(frameID);
+               if(tag1 && !tag1->isEmpty())
+               {
+                       if(!strcmp(frameID, "TPE1"))            { tag1->setArtist("");  }
+                       else if(!strcmp(frameID, "TALB"))       { tag1->setAlbum("");   }
+                       else if(!strcmp(frameID, "TCON"))       { tag1->setGenre("");   }
+                       else if(!strcmp(frameID, "TIT2"))       { tag1->setTitle("");   }
+                       else if(!strcmp(frameID, "TRCK"))       { tag1->setTrack(0);    }
+                       else if(!strcmp(frameID, "TDRC"))       { tag1->setYear(0);             }
+               }
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       // Check if the frame is empty (must create the frame before writing the data)
+       if(tag2->frameListMap()[frameID].isEmpty())
+       {
+               metadata_editor_info("The frame %s does not exist. Creating.\n", frameID);
+               // This is a common frame type for textural frames except comment frame
+               TagLib::ID3v2::TextIdentificationFrame* fr = new TagLib::ID3v2::TextIdentificationFrame(frameID);
+               if(fr == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               fr->setTextEncoding(TagLib::String::UTF8);
+               fr->setText(TagLib::String(value,TagLib::String::UTF8));
+               tag2->addFrame(fr);
+       }
+       else                // if not - just modify the data in the existing frame
+       {
+               metadata_editor_info("The frame %s exists. Changing.\n", frameID);
+               tag2->frameListMap()[frameID][0]->setText(TagLib::String(value,TagLib::String::UTF8));
+       }
+       if(tag1 && !tag1->isEmpty())                            // Check if ID3v1 tag exists. Must copy data if yes.
+       {
+               metadata_editor_info("ID3v1 tag also exists. Copying frame\n");
+               if(!strcmp(frameID, "TPE1"))
+                               tag1->setArtist(value);
+               else if(!strcmp(frameID, "TALB"))
+                               tag1->setAlbum(value);
+               else if(!strcmp(frameID, "TCON"))               // Genre in ID3v1 is enumeration, so can not write it with "value"
+                               tag1->setGenre("");
+               else if(!strcmp(frameID, "TIT2"))
+                               tag1->setTitle(value);
+               else if(!strcmp(frameID, "TRCK"))
+                               tag1->setTrack(atoi(value));
+               else if(!strcmp(frameID, "TDRC"))
+                               tag1->setYear(atoi(value));
+       }
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function reads frames that exist only in ID3v2 tag *** //
+static int __ID3_getFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, char** value)
+{
+       // Check if we have valid arguments to work with
+       if((_metadata == NULL) || (frameID == NULL))
+       {
+               metadata_editor_error("INVALID PARAMETER\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       // Check if the frame is empty (nothing to read) or ID3v2 tag does not exist
+       if (!tag2 || tag2->frameListMap()[frameID].isEmpty())
+       {
+               metadata_editor_info("The frame %s does not exist\n", frameID);
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                // frame exists - read it
+       {
+               metadata_editor_info("The frame %s exists\n", frameID);
+               // This string is used to copy the value in the frame
+               TagLib::String str = tag2->frameListMap()[frameID][0]->toString();
+               bool isUTF = false;
+               if(!str.isLatin1()) isUTF = true;
+               metadata_editor_info("String is %sUTF\n", (isUTF ? "" : "not "));
+               uint length = strlen(str.toCString(isUTF));
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               // Allocate the memory and copy the value to this memory
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, str.toCString(isUTF));
+
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function writes frames that exist only in ID3v2 tag *** //
+static int __ID3_setFrameByName(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* frameID, const char* value)
+{
+       // Check if we have valid arguments to work with
+       if((_metadata == NULL) || (frameID == NULL))
+       {
+               metadata_editor_error("INVALID PARAMETER\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Check if the valid tag pointer exist
+       if(tag2 == NULL)
+       {
+               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+       // If the pointer is NULL or c-string is empty - handle as request for deletion
+       if(!value || (*value == '\0'))
+       {
+               metadata_editor_info("Request for frame %s deletion\n", frameID);
+               tag2->removeFrames(frameID);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+
+       // Check if the ID3v2 tag exists
+       if (tag2->frameListMap()[frameID].isEmpty())
+       {
+               metadata_editor_info("The frame %s does not exist. Creating.\n", frameID);
+               // This is a common frame type for textural frames except comment frame
+               TagLib::ID3v2::TextIdentificationFrame* fr = new TagLib::ID3v2::TextIdentificationFrame(frameID);
+               if(fr == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               fr->setTextEncoding(TagLib::String::UTF8);
+               fr->setText(TagLib::String(value,TagLib::String::UTF8));
+               tag2->addFrame(fr);
+       }
+       else                // if not - just modify the data in the existing frame
+       {
+               metadata_editor_info("The frame %s exists. Changing.\n", frameID);
+               tag2->frameListMap()[frameID][0]->setText(TagLib::String(value,TagLib::String::UTF8));
+       }
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function is used to receive the number of pictures stored in ID3v2 tag of file *** //
+static int __ID3_getNumberOfPictures(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value)
+{
+       // Check if parameters are valid
+       if(_metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if((value == NULL))
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       // Check if the valid tag pointer exist
+       if(tag2 == NULL)
+       {
+               metadata_editor_error("Error. ID3v2 tag does not exist. Can not process further\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];        // link to picture frames in tag
+       // Check if the frames exist
+       if(lst.isEmpty())
+       {
+               metadata_editor_info("No pictures in file\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                // picture frames exist
+       {
+               metadata_editor_info("APIC frames exist in file\n");
+               int size = 20;
+               char buf[size];
+               // Convert the number of frames (lst.size()) to c-string
+               snprintf(buf, size, "%u", lst.size());
+               uint length = strlen(buf);
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               // Copy c-string to value for returning
+               strcpy(*value, buf);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function is used to receive unsynchronized lyrics from ID3v2 tag in file *** //
+// *** This frame differs from other string-type frames and uses UnsynchronizedLyricsFrame instead of TextIdentificationFrame *** //
+static int __ID3_getLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, char** value)
+{
+       // Check if parameters are valid
+       if(_metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if((value == NULL))
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       // Check if the valid tag pointer exist
+       if(tag2 == NULL)
+       {
+               metadata_editor_error("Error. ID3v2 tag does not exist. Can not process further\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["USLT"];        // link to unsynchronized lyric frames in tag
+       // Check if frames exist in file
+       if(lst.isEmpty())
+       {
+               metadata_editor_info("The frame USLT does not exist\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else
+       {
+               metadata_editor_info("The frame USLT exists\n");
+               TagLib::ID3v2::FrameList::Iterator it = lst.begin();
+               TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = static_cast<TagLib::ID3v2::UnsynchronizedLyricsFrame*>(*it);
+               TagLib::String str = frame->text();
+               bool isUTF = false;
+               if(!str.isLatin1()) isUTF = true;
+               metadata_editor_info("String is %sUTF\n", (isUTF ? "" : "not "));
+               uint length = strlen(str.toCString(isUTF));
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, str.toCString(isUTF));
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function is used to set text in comment frame. It processes both ID3v1 and ID3v2 tags *** //
+// *** Comment frame is different from other string-type frames. It uses CommentsFrame instead of TextIdentificationFrame *** //
+static int __ID3_setTwixCommentFrame(metadata_editor_s* _metadata, TagLib::ID3v1::Tag* tag1, TagLib::ID3v2::Tag* tag2, const char* value)
+{
+       // Check if we have a valid argument to work with
+       if(_metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Check if the valid tag pointer exist
+       if(tag2 == NULL)
+       {
+               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // If the pointer is NULL or c-string is empty - handle as request for deletion
+       if(!value || (*value == '\0'))
+       {
+               metadata_editor_info("Request for frame COMM deletion\n");
+               tag2->removeFrames("COMM");
+               if(tag1 && !tag1->isEmpty())
+                       tag1->setComment("");
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       // If the comment frame is empty - create the frame and add it to the list
+       if (tag2->frameListMap()["COMM"].isEmpty())
+       {
+               metadata_editor_info("The frame COMM does not exist. Creating.\n");
+               TagLib::ID3v2::CommentsFrame* fr = new TagLib::ID3v2::CommentsFrame;
+               if(fr == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               fr->setText(TagLib::String(value, TagLib::String::UTF8));
+               fr->setTextEncoding(TagLib::String::UTF8);
+               tag2->addFrame(fr);
+       }
+       else                                            // If the frame already exists - just modify its value
+       {
+               metadata_editor_info("The frame COMM exists. Changing.\n");
+               tag2->frameListMap()["COMM"][0]->setText(TagLib::String(value,TagLib::String::UTF8));
+       }
+       if(tag1 && !tag1->isEmpty())                    // Copy the value to ID3v1 tag comment
+       {
+               metadata_editor_info("ID3v1 tag also exists. Copying frame\n");
+               tag1->setComment(value);
+       }
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function is used to set text in Lyrics frame *** //
+// *** Lyrics frame is different from other string-type frames and uses UnsynchronizedLyricsFrame instead of TextIdentificationFrame *** //
+static int __ID3_setLyricsFrame(metadata_editor_s* _metadata, TagLib::ID3v2::Tag* tag2, const char* value)
+{
+       // Check if we have a valid argument to work with
+       if(_metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                               // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Check if the valid tag pointer exist
+       if(tag2 == NULL)
+       {
+               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["USLT"];    // link to unsynchronized lyric frames in tag
+       // If the pointer is NULL or c-string is empty - handle as request for deletion
+       if(!value || (*value == '\0'))
+       {
+               metadata_editor_info("Request for frame USLT deletion\n");
+               tag2->removeFrames("USLT");
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       // Check if lyrics frames exist
+       if(lst.isEmpty())
+       {
+               // No lyrics - create the frame and add it to the ID3v2 tag
+               metadata_editor_info("The frame USLT does not exist. Creating.\n");
+               TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame;
+               if(frame == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               frame->setTextEncoding(TagLib::String::UTF8);
+               frame->setText(TagLib::String(value,TagLib::String::UTF8));
+               tag2->addFrame(frame);
+       }
+       else                                                                    // the lyrics frames exist - change the existing one
+       {
+               metadata_editor_info("USLT frames exist in file. Changing.\n");
+               TagLib::ID3v2::FrameList::Iterator it = lst.begin();
+               TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = static_cast<TagLib::ID3v2::UnsynchronizedLyricsFrame*>(*it);
+               frame->setTextEncoding(TagLib::String::UTF8);
+               frame->setText(TagLib::String(value,TagLib::String::UTF8));
+       }
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function extracts string values from tag in MP4 file *** //
+static int __MP4_getStringItem(metadata_editor_s* _metadata, const char* itemname, char** value)
+{
+       // Check if parameters are valid
+       if((_metadata == NULL)|| (itemname == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+       TagLib::MP4::Tag* tag = _file->tag();
+       if(!tag)                                                                        // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag does not exist\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Get map of items directly from tag and launch a search of specific item
+       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+       TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find(itemname);
+       if(it != itemMap.end())                                                         // Item was found
+       {
+               TagLib::String str = it->second.toStringList()[0];                      // Get the first string in item
+               // Check the encoding of the string (1252 or not)
+               bool isUTF = false;
+               if(!str.isLatin1()) isUTF = true;
+               metadata_editor_info("String is %sUTF\n", (isUTF ? "" : "not "));
+               // Get the length of the string and check if it is empty or not
+               uint length = strlen(str.toCString(isUTF));
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               // Allocate the memory and copy string to output variable
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, str.toCString(isUTF));
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                                                                            // Item was not found
+       {
+               metadata_editor_info("No item <%s> in file\n", itemname);
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function extracts integer value from item in MP4 tag *** //
+static int __MP4_getIntegerItem(metadata_editor_s* _metadata, const char* itemname, char** value)
+{
+       // Check if parameters are valid
+       if((_metadata == NULL)|| (itemname == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+       TagLib::MP4::Tag* tag = _file->tag();
+       if(!tag)                                                                        // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag does not exist.\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Get map of items directly from tag and launch a search of specific item
+       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+       TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find(itemname);
+       if(it != itemMap.end())                                                         // Item was found
+       {
+               uint size = 20;
+               char buf[size];
+               int num = it->second.toInt();                                           // Get integer value in item
+               snprintf(buf, size, "%u", num);                                         // Convert int into char[]
+               // Determine the length of created c-string and copy it into the output variable
+               int length = strlen(buf);
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, buf);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                                                                            // Item was not found
+       {
+               metadata_editor_info("No item <%s> in file\n", itemname);
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function adds (or changes) string item of itemname type *** //
+static int __MP4_updateStringItem(metadata_editor_s* _metadata, const char* itemname, const char* value)
+{
+       // Check if parameters are valid
+       if((_metadata == NULL)|| (itemname == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+       TagLib::MP4::Tag* tag = _file->tag();
+       if(!tag)                                                                        // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag was not created.\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Get map of items directly from tag and launch a search of specific item
+       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+       // Check if it is a request for deletion
+       if((value == NULL) || value[0] == '\0')
+       {
+               metadata_editor_info("Request for deleting of item <%s>\n", itemname);
+               TagLib::MP4::ItemListMap::Iterator it = itemMap.find(itemname);
+               if(it != itemMap.end())
+                       itemMap.erase(it);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       metadata_editor_info("The item <%s> will be added\n", itemname);
+       itemMap[itemname] = TagLib::MP4::Item(TagLib::String(value, TagLib::String::UTF8));
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function adds (or changes) integer item of itemname type *** //
+static int __MP4_updateIntegerItem(metadata_editor_s* _metadata, const char* itemname, const char* value)
+{
+       // Check if parameters are valid
+       if((_metadata == NULL) || (itemname == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+       TagLib::MP4::Tag* tag = _file->tag();
+       if(!tag)                                                                        // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag was not created.\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Get map of items directly from tag and launch a search of specific item
+       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+       // Check if it is a request for deletion
+       if((value == NULL) || value[0] == '\0')
+       {
+               metadata_editor_info("Request for deleting of item <%s>\n", itemname);
+               TagLib::MP4::ItemListMap::Iterator it = itemMap.find(itemname);
+               if(it != itemMap.end())
+                       itemMap.erase(it);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       // Check if the value is integer string then it can be successfully converted into integer
+       if(isdigit(value[0]))
+       {
+               metadata_editor_info("The item <%s> will be added\n", itemname);
+               int number = atoi(value);
+               itemMap[itemname] = TagLib::MP4::Item(number);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                                                                            // Notify that string is not a number to process
+       {
+               metadata_editor_error("Error. String does not contain a number\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+}
+
+// *** This function is used to find the number of pictures stored in MP4 file *** //
+static int __MP4_getNumberOfPictures(metadata_editor_s* _metadata, char** value)
+{
+       // Check if parameters are valid
+       if(_metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if((value == NULL))
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+       TagLib::MP4::Tag* tag = _file->tag();
+       if(!tag)                                                                        // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag does not exist\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       // Get map of items directly from tag and launch a search of specific item
+       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+       TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
+       if(it != itemMap.end())                                                         // Item was found
+       {
+               uint number = it->second.toCoverArtList().size();                       // Get the size of CoverList (i.e. number of pictures in file)
+               metadata_editor_info("There are %u picture(s) in file\n", number);
+               int size = 20;
+               char buf[size];
+               snprintf(buf,size, "%u", number);                                       // Convert integer value of size to its c-string representation
+               int length = strlen(buf);
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, buf);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                                                                            // Item was not found
+       {
+               metadata_editor_info("No item <covr> in file\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function is used to extract string from Xiph Comment field *** //
+static int __xiph_getFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, char** value)
+{
+       // Check if we have a valid argument to work with
+       if((_metadata == NULL) || (fieldname == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(!xtag)                                                                       // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag does not exist\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+       const TagLib::Ogg::FieldListMap& fieldMap = xtag->fieldListMap();
+       TagLib::Ogg::FieldListMap::ConstIterator it = fieldMap.find(fieldname);
+
+       if((xtag->contains(fieldname)) && (it != fieldMap.end()))                       // Field was found
+       {
+               metadata_editor_info("Field %s was found. Extracting\n", fieldname);
+               TagLib::String str = it->second[0];                                     // Get the first string in xiph field
+               // Check the encoding of the string (1252 or not)
+               bool isUTF = false;
+               if(!str.isLatin1()) isUTF = true;
+               metadata_editor_info("String is %sUTF\n", (isUTF ? "" : "not "));
+               // Get the length of the string and check if it is empty or not
+               uint length = strlen(str.toCString(isUTF));
+               if(length == 0)
+               {
+                       *value = NULL;
+                       metadata_editor_info("Empty string...\n");
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               // Allocate the memory and copy string to output variable
+               *value = new char[length + 1];
+               if(*value == NULL)
+               {
+                       metadata_editor_error("OUT_OF_MEMORY\n");
+                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+               }
+               strcpy(*value, str.toCString(isUTF));
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else                                                                            // Field was not found
+       {
+               metadata_editor_info("No field %s in Xiph Comment\n", fieldname);
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+}
+
+// *** This function is used to write string into Xiph Comment fields *** //
+static int __xiph_updateFieldValue(metadata_editor_s* _metadata, TagLib::Ogg::XiphComment* xtag, const char* fieldname, const char* value)
+{
+       // Check if we have a valid argument to work with
+       if((_metadata == NULL) || (fieldname == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       if(!xtag)                                                                       // Check if we have a valid tag for processing
+       {
+               metadata_editor_error("Tag does not exist\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+       // Check if it is a request for deletion
+       if((value == NULL) || value[0] == '\0')
+       {
+               metadata_editor_info("Request for deleting of field %s\n", fieldname);
+               xtag->removeField(fieldname);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       metadata_editor_info("The field %s will be added\n", fieldname);
+       // "true" is used to remove other strings of the same "fieldname" first
+       xtag->addField(fieldname, TagLib::String(value,TagLib::String::UTF8), true);
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function is used to receive the number of pictures in FLAC file *** //
+static int __FLAC_getNumberOfPictures(metadata_editor_s* _metadata, char** value)
+{
+       // Check if parameters are valid
+       if(_metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
+       if(_file->pictureList().isEmpty())
+       {
+               metadata_editor_info("No pictures in FLAC file\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       uint number = _file->pictureList().size();
+       metadata_editor_info("There are %u picture(s) in file\n", number);
+       int size = 20;
+       char buf[size];
+       snprintf(buf,size, "%u", number);                                               // Convert integer value of size to its c-string representation
+       int length = strlen(buf);
+       if(length == 0)
+       {
+               *value = NULL;
+               metadata_editor_info("Empty string...\n");
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       *value = new char[length + 1];
+       if(*value == NULL)
+       {
+               metadata_editor_error("OUT_OF_MEMORY\n");
+               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+       }
+       strcpy(*value, buf);
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+int __metadata_editor_get_file_ext(const char *file_path, char *file_ext, int max_len)
+{
+       int i = 0;
+
+       for (i = strlen(file_path); i >= 0; i--)
+       {
+               if ((file_path[i] == '.') && (i < strlen(file_path)))
+               {
+                       strncpy(file_ext, &file_path[i + 1], max_len);
+                       return 0;
+               }
+
+               /* meet the dir. no ext */
+               if (file_path[i] == '/')
+               {
+                       return -1;
+               }
+       }
+
+       return -1;
+}
+
+int __metadata_editor_get_file_type(const char *path)
+{
+       int ret = 0;
+       char mimetype[255] = {0,};
+
+       /* get content type and mime type from file. */
+       ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype));
+       if (ret < 0)
+       {
+               metadata_editor_debug("aul_get_mime_from_file fail.. Now trying to get type by extension");
+
+               char ext[255] = { 0 };
+               int ret = __metadata_editor_get_file_ext(path, ext, sizeof(ext));
+               if (ret < 0)
+               {
+                       metadata_editor_error("__metadata_editor_get_file_type failed");
+                       return METADATA_EDITOR_FORMAT_NOTYPE;
+               }
+
+               if (strcasecmp(ext, "MP3") == 0)
+               {
+                       return METADATA_EDITOR_FORMAT_MP3;
+               }
+               else if (strcasecmp(ext, "MP4") == 0)
+               {
+                       return METADATA_EDITOR_FORMAT_MP4;
+               }
+               else
+               {
+                       return METADATA_EDITOR_FORMAT_NOTYPE;
+               }
+       }
+
+       metadata_editor_debug("mime type : %s", mimetype);
+
+       /* categorize from mimetype */
+       if (strstr(mimetype, "mpeg") != NULL)
+       {
+               return METADATA_EDITOR_FORMAT_MP3;
+       }
+       else if (strstr(mimetype, "mp4") != NULL)
+       {
+               return METADATA_EDITOR_FORMAT_MP4;
+       }
+
+       return METADATA_EDITOR_FORMAT_NOTYPE;
+}
+
+int __metadata_editor_get_picture_type(const char *path, char **type)
+{
+       int ret = 0;
+       char mimetype[255] = {0,};
+       const char *type_jpeg = "image/jpeg";
+       const char *type_png = "image/png";
+
+       /* get content type and mime type from file. */
+       ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype));
+       if (ret < 0)
+       {
+               metadata_editor_debug("aul_get_mime_from_file fail.. Now trying to get type by extension");
+
+               char ext[255] = { 0 };
+               int ret = __metadata_editor_get_file_ext(path, ext, sizeof(ext));
+               if (ret < 0)
+               {
+                       metadata_editor_error("__metadata_editor_get_file_type failed");
+                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+
+               if (strcasecmp(ext, "JPG") == 0 || strcasecmp(ext, "JPEG") == 0)
+               {
+                       *type = strndup(type_jpeg, strlen(type_jpeg));
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               else if (strcasecmp(ext, "PNG") == 0)
+               {
+                       *type = strndup(type_png, strlen(type_png));
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               else
+               {
+                       return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
+               }
+       }
+
+       metadata_editor_debug("mime type : %s", mimetype);
+
+       /* categorize from mimetype */
+       if (strstr(mimetype, "jpeg") != NULL)
+       {
+               *type = strndup(mimetype, strlen(mimetype));
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       else if (strstr(mimetype, "png") != NULL)
+       {
+               *type = strndup(mimetype, strlen(mimetype));
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+
+       return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
+}
+
+int __metadata_editor_get_picture_info(const char *path, void **picture, int *size, char **type)
+{
+       int ret;
+
+       ret = __metadata_editor_get_picture_type(path, type);
+       if(ret != METADATA_EDITOR_ERROR_NONE)
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+
+       //IF ok.. read file
+       FILE* fin = fopen(path, "rb");
+       int file_size = 0;
+
+       if(fin)
+       {
+               while(fgetc(fin) != EOF)
+               {
+                       file_size++;
+               }
+               fclose(fin);
+               char picture_buffer[file_size];
+               fin = fopen(path, "rb");
+               ret = fread(picture_buffer, file_size, 1, fin);
+               fclose(fin);
+
+               *picture = malloc(file_size * sizeof(char));
+               memset(*picture, 0, file_size * sizeof(char));
+               memcpy(*picture, picture_buffer, file_size);
+               *size = file_size;
+       }
+
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+bool __metadata_editor_file_exist(const std::string& name) {
+       struct stat buffer;
+       return (stat (name.c_str(), &buffer) == 0);
+}
+
+
+// *** This function is used to allocate the metadata_editor_s in memory               *** //
+// *** The structure metadata_editor_s contains all information about the file *** //
+extern "C" int metadata_editor_create(metadata_editor_h *metadata)
+{
+       // Check if we have a valid argument to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID PARAMETER\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s *_metadata = new metadata_editor_s;           // Allocate a structure for handler
+       if(_metadata == NULL)                                           // Check if the structure was allocated successfully
+       {
+               metadata_editor_error("OUT_OF_MEMORY\n");
+               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+       }
+
+       _metadata->file = NULL;
+       _metadata->filetype = METADATA_EDITOR_FORMAT_NOTYPE;                    // Specify file type out of range
+       _metadata->isOpen = false;                                              // File is not opened yet
+       _metadata->isReadOnly = true;                                           // Handle unexisting file as readonly
+
+       // Save the structure in the metadata
+       *metadata = (metadata_editor_h)_metadata;
+
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
+// *** This function is used to open the file. It creates the instance that is responsible for connection with file *** //
+extern "C" int metadata_editor_set_path(metadata_editor_h metadata, const char *path)
+{
+       // Check if we have valid arguments to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(path == NULL)
+       {
+               metadata_editor_error("INVALID Path\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       if(!__metadata_editor_file_exist(path))
+       {
+               metadata_editor_error("Not exist file\n");
+               return METADATA_EDITOR_ERROR_FILE_EXISTS;
+       }
+
+       metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
+       int media_type;
+
+       media_type = __metadata_editor_get_file_type(path);
+
+
+
+       switch(media_type)                                                      // Parse file according the specified type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Allocate the file object in memory to work with it later on
+                       TagLib::MPEG::File* _file = new TagLib::MPEG::File(path);
+
+                       if(_file == NULL)                                       // Check if the file was allocated successfully
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       _metadata->file = _file;                                // Copy file pointer to the structure
+
+                       _metadata->filetype = METADATA_EDITOR_FORMAT_MP3;
+
+                       if (_file->isOpen())                                    // Check if the file was opened successfully
+                       {
+                               metadata_editor_info("The file is successfully opened. Address is %lX\n", _metadata->file);
+                               _metadata->isOpen = true;
+                       }
+                       else                                                    // The file does not exist or you have no permission to process it
+                       {
+                               metadata_editor_error("The file was not found. Pointer address is %lX\n", _metadata->file);
+                               _metadata->isOpen = false;
+                               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+                       }
+                       if(_file->readOnly())                                   // Check if the file is readonly
+                       {
+                               metadata_editor_info("File is readonly\n");
+                               _metadata->isReadOnly = true;
+                       }
+                       else                                                    // or not
+                       {
+                               metadata_editor_info("The file is writable\n");
+                               _metadata->isReadOnly = false;
+                       }
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       // Allocate the file object in memory to work with it later on
+                       TagLib::MP4::File* _file = new TagLib::MP4::File(path);
+
+                       if(_file == NULL)                                       // Check if the file was allocated successfully
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       _metadata->file = _file;                                // Copy file pointer to the structure
+
+                       _metadata->filetype = METADATA_EDITOR_FORMAT_MP4;
+
+                       if (_file->isOpen())                                    // Check if the file was opened successfully
+                       {
+                               metadata_editor_info("The file is successfully opened. Address is %lX\n", _metadata->file);
+                               _metadata->isOpen = true;
+                       }
+                       else                                                    // The file does not exist or you have no permission to process it
+                       {
+                               metadata_editor_error("The file was not found. Pointer address is %lX\n", _metadata->file);
+                               _metadata->isOpen = false;
+                               return METADATA_EDITOR_ERROR_FILE_EXISTS;
+                       }
+                       if(_file->readOnly())                                   // Check if the file is readonly
+                       {
+                               metadata_editor_info("File is readonly\n");
+                               _metadata->isReadOnly = true;
+                       }
+                       else                                                    // or not
+                       {
+                               metadata_editor_info("The file is writable\n");
+                               _metadata->isReadOnly = false;
+                       }
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       // Allocate the file object in memory to work with it later on
+                       TagLib::FLAC::File* _file = new TagLib::FLAC::File(path);
+
+                       if(_file == NULL)                                       // Check if the file was allocated successfully
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       _metadata->file = _file;                                // Copy file pointer to the structure
+
+                       _metadata->filetype = METADATA_EDITOR_FORMAT_FLAC;
+
+                       if (_file->isOpen())                                    // Check if the file was opened successfully
+                       {
+                               metadata_editor_info("The file is successfully opened. Address is %lX\n", _metadata->file);
+                               _metadata->isOpen = true;
+                       }
+                       else                                                    // The file does not exist or you have no permission to process it
+                       {
+                               metadata_editor_error("The file was not found. Pointer address is %lX\n", _metadata->file);
+                               _metadata->isOpen = false;
+                               return METADATA_EDITOR_ERROR_FILE_EXISTS;
+                       }
+                       if(_file->readOnly())                                   // Check if the file is readonly
+                       {
+                               metadata_editor_info("File is readonly\n");
+                               _metadata->isReadOnly = true;
+                       }
+                       else                                                    // or not
+                       {
+                               metadata_editor_info("The file is writable\n");
+                               _metadata->isReadOnly = false;
+                       }
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
+               {
+                       // Allocate the file object in memory to work with it later on
+                       TagLib::Ogg::Vorbis::File* _file = new TagLib::Ogg::Vorbis::File(path);
+
+                       if(_file == NULL)                                       // Check if the file was allocated successfully
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       _metadata->file = _file;                                // Copy file pointer to the structure
+
+                       _metadata->filetype = METADATA_EDITOR_FORMAT_OGG_VORBIS;
+
+                       if (_file->isOpen())                                    // Check if the file was opened successfully
+                       {
+                               metadata_editor_info("The file is successfully opened. Address is %lX\n", _metadata->file);
+                               _metadata->isOpen = true;
+                       }
+                       else                                                    // The file does not exist or you have no permission to process it
+                       {
+                               metadata_editor_error("The file was not found. Pointer address is %lX\n", _metadata->file);
+                               _metadata->isOpen = false;
+                               return METADATA_EDITOR_ERROR_FILE_EXISTS;
+                       }
+                       if(_file->readOnly())                                   // Check if the file is readonly
+                       {
+                               metadata_editor_info("File is readonly\n");
+                               _metadata->isReadOnly = true;
+                       }
+                       else                                                    // or not
+                       {
+                               metadata_editor_info("The file is writable\n");
+                               _metadata->isReadOnly = false;
+                       }
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               case METADATA_EDITOR_FORMAT_OGG_FLAC:
+               {
+                       // Allocate the file object in memory to work with it later on
+                       TagLib::Ogg::FLAC::File* _file = new TagLib::Ogg::FLAC::File(path);
+
+                       if(_file == NULL)                                       // Check if the file was allocated successfully
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       _metadata->file = _file;                                // Copy file pointer to the structure
+
+                       _metadata->filetype = METADATA_EDITOR_FORMAT_OGG_FLAC;
+
+                       if (_file->isOpen())                                    // Check if the file was opened successfully
+                       {
+                               metadata_editor_info("The file is successfully opened. Address is %lX\n", _metadata->file);
+                               _metadata->isOpen = true;
+                       }
+                       else                                                    // The file does not exist or you have no permission to process it
+                       {
+                               metadata_editor_error("The file was not found. Pointer address is %lX\n", _metadata->file);
+                               _metadata->isOpen = false;
+                               return METADATA_EDITOR_ERROR_FILE_EXISTS;
+                       }
+                       if(_file->readOnly())                                   // Check if the file is readonly
+                       {
+                               metadata_editor_info("File is readonly\n");
+                               _metadata->isReadOnly = true;
+                       }
+                       else                                                    // or not
+                       {
+                               metadata_editor_info("The file is writable\n");
+                               _metadata->isReadOnly = false;
+                       }
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       // Allocate the file object in memory to work with it later on
+                       TagLib::RIFF::WAV::File* _file = new TagLib::RIFF::WAV::File(path);
+
+                       if(_file == NULL)                                       // Check if the file was allocated successfully
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       _metadata->file = _file;                                // Copy file pointer to the structure
+
+                       _metadata->filetype = METADATA_EDITOR_FORMAT_WAV;
+
+                       if (_file->isOpen())                                    // Check if the file was opened successfully
+                       {
+                               metadata_editor_info("The file is successfully opened. Address is %lX\n", _metadata->file);
+                               _metadata->isOpen = true;
+                       }
+                       else                                                    // The file does not exist or you have no permission to process it
+                       {
+                               metadata_editor_error("The file was not found. Pointer address is %lX\n", _metadata->file);
+                               _metadata->isOpen = false;
+                               return METADATA_EDITOR_ERROR_FILE_EXISTS;
+                       }
+                       if(_file->readOnly())                                   // Check if the file is readonly
+                       {
+                               metadata_editor_info("File is readonly\n");
+                               _metadata->isReadOnly = true;
+                       }
+                       else                                                    // or not
+                       {
+                               metadata_editor_info("The file is writable\n");
+                               _metadata->isReadOnly = false;
+                       }
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
+       }
+}
+
+// *** This function is used to get the tag frame (field, item - each tag has its own name for data unit) from file *** //
+extern "C" int metadata_editor_get_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, char **value)
+{
+       // Check if we have valid arguments to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if(value == NULL)
+       {
+               metadata_editor_error("INVALID Value Pointer\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *value = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       switch(_metadata->filetype)                             // Process the file according to the specified file type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Bring the pointer to actual file type and make tag pointers
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
+                       TagLib::ID3v1::Tag* tag1 = _file->ID3v1Tag();
+                       TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag();
+
+                       switch (attribute)                                      // Check which one of frame types was given to the function for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "TPE1", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "TIT2", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "TALB", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "TCON", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_getFrameByName(_metadata, tag2, "TCOM", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __ID3_getFrameByName(_metadata, tag2, "TCOP", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "TDRC", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_getFrameByName(_metadata, tag2, "TIT3", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "COMM", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __ID3_getTwixFrameByName(_metadata, tag1, tag2, "TRCK", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __ID3_getFrameByName(_metadata, tag2, "TPE3", value);
+                               case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __ID3_getNumberOfPictures(_metadata, tag2, value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_getLyricsFrame(_metadata, tag2, value);
+                               default:
+                                       *value = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       switch(attribute)                                       // Check which one of frame types was given to the function for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_getStringItem(_metadata, "\xA9""ART", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_getStringItem(_metadata, "\xA9""nam", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_getStringItem(_metadata, "\xA9""alb", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_getStringItem(_metadata, "\xA9""gen", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_getStringItem(_metadata, "\xA9""wrt", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __MP4_getStringItem(_metadata, "cprt", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __MP4_getStringItem(_metadata, "\xA9""day", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_getStringItem(_metadata, "desc", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __MP4_getStringItem(_metadata, "\xA9""cmt", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __MP4_getIntegerItem(_metadata, "trkn", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __MP4_getStringItem(_metadata, "cond", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __MP4_getStringItem(_metadata, "\xA9""lyr", value);
+                               case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __MP4_getNumberOfPictures(_metadata, value);
+                               default:
+                                       *value = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*)_metadata->file;
+                       TagLib::Ogg::XiphComment* xtag = _file->xiphComment(false);
+                       if(!xtag)                                                                       // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Tag does not exist\n");
+                               *value = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       switch(attribute)                                       // Check which one of frame types was given to the function for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(_metadata, xtag, "ARTIST", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(_metadata, xtag, "TITLE", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(_metadata, xtag, "ALBUM", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(_metadata, xtag, "GENRE", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(_metadata, xtag, "COMPOSER", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(_metadata, xtag, "COPYRIGHT", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(_metadata, xtag, "DATE", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(_metadata, xtag, "DESCRIPTION", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(_metadata, xtag, "COMMENT", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(_metadata, xtag, "TRACKNUMBER", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(_metadata, xtag, "CONDUCTOR", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(_metadata, xtag, "LYRICS", value);
+                               case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __FLAC_getNumberOfPictures(_metadata, value);
+                               default:
+                                       *value = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)_metadata->file;
+                       TagLib::Ogg::XiphComment* xtag = _file->tag();
+                       if(!xtag)                                                                       // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Tag does not exist\n");
+                               *value = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       switch(attribute)                                       // Check which one of frame types was given to the function for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(_metadata, xtag, "ARTIST", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(_metadata, xtag, "TITLE", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(_metadata, xtag, "ALBUM", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(_metadata, xtag, "GENRE", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(_metadata, xtag, "COMPOSER", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(_metadata, xtag, "COPYRIGHT", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(_metadata, xtag, "DATE", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(_metadata, xtag, "DESCRIPTION", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(_metadata, xtag, "COMMENT", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(_metadata, xtag, "TRACKNUMBER", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(_metadata, xtag, "CONDUCTOR", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(_metadata, xtag, "LYRICS", value);
+                               default:
+                                       *value = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_OGG_FLAC:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)_metadata->file;
+                       TagLib::Ogg::XiphComment* xtag = _file->tag();
+                       if(!xtag)                                                                       // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Tag does not exist\n");
+                               *value = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       switch(attribute)                                       // Check which one of frame types was given to the function for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(_metadata, xtag, "ARTIST", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(_metadata, xtag, "TITLE", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(_metadata, xtag, "ALBUM", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(_metadata, xtag, "GENRE", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(_metadata, xtag, "COMPOSER", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(_metadata, xtag, "COPYRIGHT", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(_metadata, xtag, "DATE", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(_metadata, xtag, "DESCRIPTION", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(_metadata, xtag, "COMMENT", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(_metadata, xtag, "TRACKNUMBER", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(_metadata, xtag, "CONDUCTOR", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(_metadata, xtag, "LYRICS", value);
+                               default:
+                                       *value = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       // Bring the pointer to actual file type and make tag pointers
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
+                       TagLib::ID3v2::Tag* tag2 = _file->tag();
+
+                       if(tag2 == NULL)                                                                // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Error. ID3v2 tag does not exist. Can not proceed metadata extraction\n");
+                               *value = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+
+                       switch (attribute)                                      // Check which one of frame types was given to the function for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_getFrameByName(_metadata, tag2, "TPE1", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_getFrameByName(_metadata, tag2, "TIT2", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_getFrameByName(_metadata, tag2, "TALB", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_getFrameByName(_metadata, tag2, "TCON", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_getFrameByName(_metadata, tag2, "TCOM", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __ID3_getFrameByName(_metadata, tag2, "TCOP", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __ID3_getFrameByName(_metadata, tag2, "TDRC", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_getFrameByName(_metadata, tag2, "TIT3", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __ID3_getFrameByName(_metadata, tag2, "COMM", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __ID3_getFrameByName(_metadata, tag2, "TRCK", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __ID3_getFrameByName(_metadata, tag2, "TPE3", value);
+                               case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __ID3_getNumberOfPictures(_metadata, tag2, value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_getLyricsFrame(_metadata, tag2, value);
+                               default:
+                                       *value = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       *value = NULL;
+                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+}
+
+// *** This function is used to modify the metadata (frame in tag). But it does not apply changes to file *** //
+extern "C" int metadata_editor_set_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, const char* value)
+{
+       // Check if we have valid arguments to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                               // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       switch(_metadata->filetype)                                             // Process the file according to the specified file type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
+                       TagLib::ID3v1::Tag* tag1 = _file->ID3v1Tag();
+                       TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag(true);
+
+                       if(tag2 == NULL)                                        // Check if the valid tag pointer exist
+                       {
+                               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+
+                       switch (attribute)                                      // Check which one of frame type was given for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:               return __ID3_setTwixFrameByName(_metadata, tag1, tag2, "TPE1", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                return __ID3_setTwixFrameByName(_metadata, tag1, tag2, "TIT2", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                return __ID3_setTwixFrameByName(_metadata, tag1, tag2, "TALB", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                return __ID3_setTwixFrameByName(_metadata, tag1, tag2, "TCON", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:               return __ID3_setFrameByName(_metadata, tag2, "TCOM", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:            return __ID3_setFrameByName(_metadata, tag2, "TCOP", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __ID3_setTwixFrameByName(_metadata, tag1, tag2, "TDRC", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_setFrameByName(_metadata, tag2, "TIT3", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:            return __ID3_setTwixFrameByName(_metadata, tag1, tag2, "TRCK", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:            return __ID3_setFrameByName(_metadata, tag2, "TPE3", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                              return __ID3_setTwixCommentFrame(_metadata, tag1, tag2, value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_setLyricsFrame(_metadata, tag2, value);
+                               default:
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       switch(attribute)                                       // Check which one of frame type was given for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_updateStringItem(_metadata, "\xA9""ART", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_updateStringItem(_metadata, "\xA9""nam", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_updateStringItem(_metadata, "\xA9""alb", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_updateStringItem(_metadata, "\xA9""gen", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_updateStringItem(_metadata, "\xA9""wrt", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:            return __MP4_updateStringItem(_metadata, "cprt", value);
+                               case METADATA_EDITOR_ATTR_DATE:                         return __MP4_updateStringItem(_metadata, "\xA9""day", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_updateStringItem(_metadata, "desc", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __MP4_updateStringItem(_metadata, "\xA9""cmt", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:            return __MP4_updateIntegerItem(_metadata, "trkn", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:            return __MP4_updateStringItem(_metadata, "cond", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:         return __MP4_updateStringItem(_metadata, "\xA9""lyr", value);
+                               default:
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*)_metadata->file;
+                       TagLib::Ogg::XiphComment* xtag = _file->xiphComment(true);
+                       if(!xtag)                                                               // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Error. Xiph Comment was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       switch(attribute)                                       // Check which one of frame type was given for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(_metadata, xtag, "ARTIST", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(_metadata, xtag, "TITLE", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(_metadata, xtag, "ALBUM", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(_metadata, xtag, "GENRE", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(_metadata, xtag, "COMPOSER", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(_metadata, xtag, "COPYRIGHT", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(_metadata, xtag, "DATE", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(_metadata, xtag, "DESCRIPTION", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(_metadata, xtag, "COMMENT", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(_metadata, xtag, "TRACKNUMBER", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(_metadata, xtag, "CONDUCTOR", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(_metadata, xtag, "LYRICS", value);
+                               default:
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)_metadata->file;
+                       TagLib::Ogg::XiphComment* xtag = _file->tag();
+                       if(!xtag)                                                               // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Error. Xiph Comment was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       switch(attribute)                                       // Check which one of frame type was given for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(_metadata, xtag, "ARTIST", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(_metadata, xtag, "TITLE", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(_metadata, xtag, "ALBUM", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(_metadata, xtag, "GENRE", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(_metadata, xtag, "COMPOSER", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(_metadata, xtag, "COPYRIGHT", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(_metadata, xtag, "DATE", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(_metadata, xtag, "DESCRIPTION", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(_metadata, xtag, "COMMENT", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(_metadata, xtag, "TRACKNUMBER", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(_metadata, xtag, "CONDUCTOR", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(_metadata, xtag, "LYRICS", value);
+                               default:
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_OGG_FLAC:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)_metadata->file;
+                       TagLib::Ogg::XiphComment* xtag = _file->tag();
+                       if(!xtag)                                                               // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Error. Xiph Comment was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       switch(attribute)                                       // Check which one of frame type was given for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(_metadata, xtag, "ARTIST", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(_metadata, xtag, "TITLE", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(_metadata, xtag, "ALBUM", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(_metadata, xtag, "GENRE", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(_metadata, xtag, "COMPOSER", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(_metadata, xtag, "COPYRIGHT", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(_metadata, xtag, "DATE", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(_metadata, xtag, "DESCRIPTION", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(_metadata, xtag, "COMMENT", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(_metadata, xtag, "TRACKNUMBER", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(_metadata, xtag, "CONDUCTOR", value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(_metadata, xtag, "LYRICS", value);
+                               default:
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
+                       TagLib::ID3v2::Tag* tag2 = _file->tag();
+                       // Check if the valid tag pointer exist
+                       if(tag2 == NULL)
+                       {
+                               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+
+                       switch (attribute)                                      // Check which one of frame type was given for processing
+                       {
+                               case METADATA_EDITOR_ATTR_ARTIST:               return __ID3_setFrameByName(_metadata, tag2, "TPE1", value);
+                               case METADATA_EDITOR_ATTR_TITLE:                return __ID3_setFrameByName(_metadata, tag2, "TIT2", value);
+                               case METADATA_EDITOR_ATTR_ALBUM:                return __ID3_setFrameByName(_metadata, tag2, "TALB", value);
+                               case METADATA_EDITOR_ATTR_GENRE:                return __ID3_setFrameByName(_metadata, tag2, "TCON", value);
+                               case METADATA_EDITOR_ATTR_AUTHOR:               return __ID3_setFrameByName(_metadata, tag2, "TCOM", value);
+                               case METADATA_EDITOR_ATTR_COPYRIGHT:            return __ID3_setFrameByName(_metadata, tag2, "TCOP", value);
+                               case METADATA_EDITOR_ATTR_DATE:                 return __ID3_setFrameByName(_metadata, tag2, "TDRC", value);
+                               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_setFrameByName(_metadata, tag2, "TIT3", value);
+                               case METADATA_EDITOR_ATTR_TRACK_NUM:            return __ID3_setFrameByName(_metadata, tag2, "TRCK", value);
+                               case METADATA_EDITOR_ATTR_CONDUCTOR:            return __ID3_setFrameByName(_metadata, tag2, "TPE3", value);
+                               case METADATA_EDITOR_ATTR_COMMENT:                      return __ID3_setTwixCommentFrame(_metadata, NULL, tag2, value);
+                               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_setLyricsFrame(_metadata, tag2, value);
+                               default:
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+}
+
+// *** This function apply all changes done in the tag(s) and update them to file *** //
+extern "C" int metadata_editor_update_metadata(metadata_editor_h metadata)
+{
+       // Check if we have a valid argument to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                               // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       switch(_metadata->filetype)                                             // Process the file according to the specified file type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Bring the pointer to actual file type
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
+
+                       TagLib::ID3v1::Tag* tag1 = _file->ID3v1Tag();
+
+                       if(!tag1 || tag1->isEmpty())                                                    // If no ID3v1 tag - prevent its creation
+                       {
+                               if(_file->save(TagLib::MPEG::File::ID3v2 | TagLib::MPEG::File::APE))
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               else
+                                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       else                                                                            // otherwise - save all tags in file
+                       {
+                               if(_file->save(TagLib::MPEG::File::AllTags))
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               else
+                                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       TagLib::MP4::File* _file = (TagLib::MP4::File*)_metadata->file;
+                       if(_file->save())
+                               return METADATA_EDITOR_ERROR_NONE;
+                       else
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*)_metadata->file;
+                       if(_file->save())
+                               return METADATA_EDITOR_ERROR_NONE;
+                       else
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
+               {
+                       TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)_metadata->file;
+                       if(_file->save())
+                               return METADATA_EDITOR_ERROR_NONE;
+                       else
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+               case METADATA_EDITOR_FORMAT_OGG_FLAC:
+               {
+                       TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)_metadata->file;
+                       if(_file->save())
+                               return METADATA_EDITOR_ERROR_NONE;
+                       else
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
+                       if(_file->save())
+                               return METADATA_EDITOR_ERROR_NONE;
+                       else
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+}
+
+// *** This function returns buffer with picture under the specified index and buffer's (picture's) size *** //
+extern "C" int metadata_editor_get_picture(metadata_editor_h metadata, int index, void **picture, int *size, char **mime_type)
+{
+       const char *TYPE_JPEG = "image/jpeg";
+       const char *TYPE_PNG = "image/png";
+       // Check if we have valid arguments to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               *picture = NULL; *size = 0; *mime_type = NULL;
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+       if((picture == NULL) || (size == NULL))
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+
+       metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               *picture = NULL; *size = 0; *mime_type = NULL;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       switch(_metadata->filetype)                                                                     // Process the file according to the specified file type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;               // Bring the pointer to actual file type
+                       TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag();
+                       if(!tag2)
+                       {
+                               metadata_editor_error("No ID3v2 tag in file\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
+                       // Check if there are pictures in the tag
+                       if(lst.isEmpty())
+                       {
+                               metadata_editor_error("No pictures in file\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       else                // pictures exist in file
+                       {
+                               // Check if index is correct or not
+                               if( (index < 0) || (lst.size() <= (uint)index) )
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else            // everything is correct - begin extraction
+                               {
+                                       metadata_editor_info("There are %u pictures in file. Start of picture number %d extraction", lst.size(), index);
+                                       int i = 0;
+                                       // Among all frames we must choose that one with specified index. "i" will be counter
+                                       for(TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               TagLib::ID3v2::AttachedPictureFrame* pictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
+                                               uint pictureSize = pictureFrame->picture().size();
+                                               if(pictureSize == 0)
+                                               {
+                                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                                       metadata_editor_error("Size of picture is 0\n");
+                                                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                                               }
+                                               *picture = new char[pictureSize];
+                                               if(*picture == NULL)
+                                               {
+                                                       metadata_editor_error("OUT_OF_MEMORY\n");
+                                                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                                               }
+                                               memcpy(*picture, pictureFrame->picture().data(), pictureSize);
+                                               *size = pictureSize;
+                                               TagLib::String mime = pictureFrame->mimeType();
+                                               if(!strcmp(mime.toCString(),"image/jpeg"))
+                                                       *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
+                                               else if(!strcmp(mime.toCString(),"image/png"))
+                                                       *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
+                                               else
+                                                       *mime_type = NULL;
+                                               break;
+                                       }
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+                       TagLib::MP4::Tag* tag = _file->tag();
+                       if(!tag)                                                                        // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Tag does not exist\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+
+                       // Get map of items directly from tag and launch a search of specific item
+                       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+                       TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
+                       if(it != itemMap.end())                                                         // Item was found
+                       {
+                               TagLib::MP4::CoverArtList lst = it->second.toCoverArtList();
+                               // Check if the index is in range of CoverArtList Item
+                               if((index < 0) || ((uint)index >= lst.size()))                          // it is not
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else                                                                    // index is in range
+                               {
+                                       int i = 0;
+                                       for(TagLib::MP4::CoverArtList::ConstIterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               int pictureSize = picIt->data().size();
+                                               if(pictureSize == 0)
+                                               {
+                                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                                       metadata_editor_error("Size of picture is 0\n");
+                                                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                                               }
+                                               *picture = new char[pictureSize];
+                                               if(*picture == NULL)
+                                               {
+                                                       metadata_editor_error("OUT_OF_MEMORY\n");
+                                                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                                               }
+                                               memcpy(*picture, picIt->data().data(), pictureSize);
+                                               *size = pictureSize;
+                                               if(picIt->format() == TagLib::MP4::CoverArt::JPEG)      *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
+                                               else if(picIt->format() == TagLib::MP4::CoverArt::PNG)  *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
+                                               else                                                    *mime_type = NULL;
+                                               break;
+                                       }
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+                       else                                                                            // Item was not found - no pictures in file
+                       {
+                               metadata_editor_error("No item <covr> in file. No pictures in file\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
+                       TagLib::List<TagLib::FLAC::Picture*> lst = _file->pictureList();
+                       if(lst.isEmpty())
+                       {
+                               metadata_editor_error("No pictures in FLAC file\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       else
+                       {
+                               // Check if the index is in range of CoverArtList Item
+                               if((index < 0) || ((uint)index >= lst.size()))                  // it is not
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else                                                                                                    // index is in range
+                               {
+                                       // Consecutive check of all pictures until the desired one is found
+                                       int i = 0;
+                                       for(TagLib::List<TagLib::FLAC::Picture*>::ConstIterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               // picture can be received as ByteVector (picIt->data()).
+                                               // ByteVector has data() - picture itself and size() - the size of picture in data() method
+                                               int pictureSize = (*picIt)->data().size();
+                                               if(pictureSize == 0)
+                                               {
+                                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                                       metadata_editor_error("Size of picture is 0\n");
+                                                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                                               }
+                                               *picture = new char[pictureSize];
+                                               if(*picture == NULL)
+                                               {
+                                                       metadata_editor_error("OUT_OF_MEMORY\n");
+                                                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                                               }
+                                               memcpy(*picture, (*picIt)->data().data(), pictureSize);
+                                               *size = pictureSize;
+                                               TagLib::String mime = (*picIt)->mimeType();
+                                               if(!strcmp(mime.toCString(),"image/jpeg"))
+                                                       *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
+                                               else if(!strcmp(mime.toCString(),"image/png"))
+                                                       *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
+                                               else
+                                                       *mime_type = NULL;
+                                               break;
+                                       }
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;             // Bring the pointer to actual file type
+                       TagLib::ID3v2::Tag* tag2 = _file->tag();
+                       if(!tag2)
+                       {
+                               metadata_editor_error("No ID3v2 tag in file\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
+                       // Check if there are pictures in the tag
+                       if(lst.isEmpty())
+                       {
+                               metadata_editor_error("No pictures in file\n");
+                               *picture = NULL; *size = 0; *mime_type = NULL;
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       else                                            // pictures exist in file
+                       {
+                               // Check if index is correct or not
+                               if( (index < 0) || (lst.size() <= (uint)index) )
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else                                    // everything is correct - begin extraction
+                               {
+                                       metadata_editor_info("There are %u pictures in file. Start of picture number %d extraction", lst.size(), index);
+                                       int i = 0;
+                                       // Among all frames we must choose that one with specified index. "i" will be counter
+                                       for(TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               TagLib::ID3v2::AttachedPictureFrame* pictureFrame = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
+                                               uint pictureSize = pictureFrame->picture().size();
+                                               if(pictureSize == 0)
+                                               {
+                                                       *picture = NULL; *size = 0; *mime_type = NULL;
+                                                       metadata_editor_error("Size of picture is 0\n");
+                                                       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                                               }
+                                               *picture = new char[pictureSize];
+                                               if(*picture == NULL)
+                                               {
+                                                       metadata_editor_error("OUT_OF_MEMORY\n");
+                                                       return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                                               }
+                                               memcpy(*picture, pictureFrame->picture().data(), pictureSize);
+                                               *size = pictureSize;
+                                               TagLib::String mime = pictureFrame->mimeType();
+                                               if(!strcmp(mime.toCString(),"image/jpeg"))
+                                                       *mime_type = strndup(TYPE_JPEG, strlen(TYPE_JPEG));
+                                               else if(!strcmp(mime.toCString(),"image/png"))
+                                                       *mime_type = strndup(TYPE_PNG, strlen(TYPE_PNG));
+                                               else
+                                                       *mime_type = NULL;
+                                               break;
+                                       }
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       *picture = NULL; *size = 0; *mime_type = NULL;
+                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+}
+
+// *** This function appends a cover art picture to the file *** //
+extern "C" int metadata_editor_append_picture(metadata_editor_h metadata, const char *path)
+{
+       // Check if we have valid arguments to work with
+       if((metadata == NULL) || (path == NULL))
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       int ret;
+       void *picture;
+       int size;
+       char *type;
+
+       ret = __metadata_editor_get_picture_info(path, &picture, &size, &type);
+       if(ret != METADATA_EDITOR_ERROR_NONE) {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+
+       switch(_metadata->filetype)                                     // Process the file according to the specified file type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
+                       TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag(true);
+                       // Check if the valid tag pointer exists
+                       if(tag2 == NULL)
+                       {
+                               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       TagLib::ID3v2::AttachedPictureFrame* pictureFrame = new TagLib::ID3v2::AttachedPictureFrame();
+                       if(pictureFrame == NULL)
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       metadata_editor_info("New APIC frame will be added to the ID3v2 tag\n");
+                       pictureFrame->setPicture(TagLib::ByteVector((char*)picture, size));
+                       pictureFrame->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
+                       pictureFrame->setMimeType(type);
+
+                       tag2->addFrame(pictureFrame);
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+                       TagLib::MP4::Tag* tag = _file->tag();
+                       if(!tag)                                                                                // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Tag was not created\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+
+                       // Get map of items directly from tag and launch a search of specific item
+                       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+                       TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
+                       if(it != itemMap.end())                                                                 // Item was found
+                       {
+                               metadata_editor_info("The item <covr> exists. Adding picture\n");
+                               TagLib::MP4::CoverArtList lst = it->second.toCoverArtList();
+                               TagLib::MP4::CoverArt::Format format;
+                               if(strncmp(type, "image/jpeg", strlen("image/jpeg")) == 0)
+                                       format = TagLib::MP4::CoverArt::JPEG;
+                               else if(strncmp(type, "image/png", strlen("image/jpeg")) == 0)
+                                       format = TagLib::MP4::CoverArt::PNG;
+                               else
+                                       format = (TagLib::MP4::CoverArt::Format)0xFFFF;
+                               TagLib::MP4::CoverArt cover(format, TagLib::ByteVector((char*)picture, size));
+                               lst.append(cover);
+                               itemMap.insert("covr", TagLib::MP4::Item(lst));
+                               return METADATA_EDITOR_ERROR_NONE;
+                       }
+                       else                                                                                    // Item was not found
+                       {
+                               metadata_editor_info("The item <covr> does not exist. Adding picture\n");
+                               TagLib::MP4::CoverArt::Format format;
+                               if(strncmp(type, "image/jpeg", strlen("image/jpeg")) == 0)
+                                       format = TagLib::MP4::CoverArt::JPEG;
+                               else if(strncmp(type, "image/png", strlen("image/jpeg")) == 0)
+                                       format = TagLib::MP4::CoverArt::PNG;
+                               else
+                                       format = (TagLib::MP4::CoverArt::Format)0xFFFF;
+                               TagLib::MP4::CoverArt cover(format, TagLib::ByteVector((char*)picture, size));
+                               TagLib::MP4::CoverArtList lst;
+                               lst.append(cover);
+                               itemMap.insert("covr", TagLib::MP4::Item(lst));
+                               return METADATA_EDITOR_ERROR_NONE;
+                       }
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
+                       TagLib::FLAC::Picture* frontCover = new TagLib::FLAC::Picture;
+                       if(frontCover == NULL)
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       frontCover->setData(TagLib::ByteVector((char*)picture, size));
+                       frontCover->setType(TagLib::FLAC::Picture::FrontCover);
+                       frontCover->setMimeType(type);
+
+                       metadata_editor_info("Picture will be added to FLAC file\n");
+                       _file->addPicture(frontCover);
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
+                       TagLib::ID3v2::Tag* tag2 = _file->tag();
+                       // Check if the valid tag pointer exists
+                       if(tag2 == NULL)
+                       {
+                               metadata_editor_error("Error. ID3v2 tag was not created. Can not proceed metadata updating\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       TagLib::ID3v2::AttachedPictureFrame* pictureFrame = new TagLib::ID3v2::AttachedPictureFrame();
+                       if(pictureFrame == NULL)
+                       {
+                               metadata_editor_error("OUT_OF_MEMORY\n");
+                               return METADATA_EDITOR_ERROR_OUT_OF_MEMORY;
+                       }
+                       metadata_editor_info("New APIC frame will be added to the ID3v2 tag\n");
+                       pictureFrame->setPicture(TagLib::ByteVector((char*)picture, size));
+                       pictureFrame->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
+                       pictureFrame->setMimeType(type);
+                       tag2->addFrame(pictureFrame);
+                       return METADATA_EDITOR_ERROR_NONE;
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
+       }
+}
+
+// *** This function is used to delete picture with specified index *** //
+extern "C" int metadata_editor_remove_picture(metadata_editor_h metadata, int index)
+{
+       // Check if we have a valid argument to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Parameter\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s* _metadata = (metadata_editor_s*) metadata;
+
+       // Check if the file, given through metadata, exists and is opened correctly
+       if(_metadata->file && _metadata->isOpen == false)
+       {
+               metadata_editor_error("File does not exist or you have no rights to open it\n");
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
+       if(_metadata->isReadOnly)                                       // Check if the file is writable or it is readonly
+       {
+               metadata_editor_error("File is readonly. Unable to modify\n");
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+       }
+
+       switch(_metadata->filetype)                                     // Process the file according to the specified file type
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
+                       TagLib::ID3v2::Tag* tag2 = _file->ID3v2Tag(true);
+                       // Check if the valid tag pointer exists
+                       if(tag2 == NULL)
+                       {
+                               metadata_editor_error("Error. ID3v2 tag does not exist. Can not remove picture\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
+                       // Check if there are pictures in the tag
+                       if(lst.isEmpty())
+                       {
+                               metadata_editor_error("No pictures in file\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       else                                            // pictures exist in file
+                       {
+                               // Check if index is correct or not
+                               if( (index < 0) || (lst.size() <= (uint)index) )
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else                                    // everything is correct - begin extraction
+                               {
+                                       metadata_editor_info("Removing of picture number %d\n", index);
+                                       int i = 0;
+                                       // Among all frames we must choose that one with specified index. "i" will be counter
+                                       for(TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               tag2->removeFrame(*it);
+                                               break;
+                                       }
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       TagLib::MP4::File* _file = (TagLib::MP4::File*) _metadata->file;
+                       TagLib::MP4::Tag* tag = _file->tag();
+                       if(!tag)                                                                        // Check if we have a valid tag for processing
+                       {
+                               metadata_editor_error("Tag does not exist\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+
+                       // Get map of items directly from tag and launch a search of specific item
+                       TagLib::MP4::ItemListMap& itemMap = tag->itemListMap();
+                       TagLib::MP4::ItemListMap::ConstIterator it = itemMap.find("covr");
+                       if(it != itemMap.end())                                                                 // Item was found
+                       {
+                               TagLib::MP4::CoverArtList lst = it->second.toCoverArtList();
+                               // Check if the index is in range of CoverArtList Item
+                               if((index < 0) || ((uint)index >= lst.size()))                                  // it is not
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else                                                                            // index is in range
+                               {
+                                       metadata_editor_info("The picture number %d will be deleted\n", index);
+                                       int i = 0;
+                                       for(TagLib::MP4::CoverArtList::Iterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               lst.erase(picIt);
+                                               break;
+                                       }
+                                       itemMap.insert("covr", TagLib::MP4::Item(lst));
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+                       else                                                                                    // Item was not found
+                       {
+                               metadata_editor_error("The item <covr> does not exist. Nothing to delete\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*) _metadata->file;
+                       TagLib::List<TagLib::FLAC::Picture*> lst = _file->pictureList();
+                       if(lst.isEmpty())
+                       {
+                               metadata_editor_error("No pictures in file. Nothing to delete\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       // Check if the index is in range of CoverArtList Item
+                       if((index < 0) || ((uint)index >= lst.size()))                                          // it is not
+                       {
+                               metadata_editor_error("Index of picture is out of range\n");
+                               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                       }
+                       else                                                                                    // index is in range
+                       {
+                               metadata_editor_info("The picture number %d will be deleted\n", index);
+                               int i = 0;
+                               for(TagLib::List<TagLib::FLAC::Picture*>::Iterator picIt = lst.begin(); picIt != lst.end(); ++picIt, ++i)
+                               {
+                                       if(i != index) continue;
+                                       _file->removePicture(*picIt,true);
+                                       break;
+                               }
+                               return METADATA_EDITOR_ERROR_NONE;
+                       }
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       // Bring the pointer to actual file type and make tags pointers
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
+                       TagLib::ID3v2::Tag* tag2 = _file->tag();
+                       // Check if the valid tag pointer exists
+                       if(tag2 == NULL)
+                       {
+                               metadata_editor_error("Error. ID3v2 tag does not exist. Can not remove picture\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       TagLib::ID3v2::FrameList lst = tag2->frameListMap()["APIC"];
+                       // Check if there are pictures in the tag
+                       if(lst.isEmpty())
+                       {
+                               metadata_editor_error("No pictures in file\n");
+                               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+                       }
+                       else                // pictures exist in file
+                       {
+                               // Check if index is correct or not
+                               if( (index < 0) || (lst.size() <= (uint)index) )
+                               {
+                                       metadata_editor_error("Index of picture is out of range\n");
+                                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+                               }
+                               else            // everything is correct - begin extraction
+                               {
+                                       metadata_editor_info("Removing of picture number %d\n", index);
+                                       int i = 0;
+                                       // Among all frames we must choose that one with specified index. "i" will be counter
+                                       for(TagLib::ID3v2::FrameList::Iterator it = lst.begin(); it != lst.end(); ++it, ++i)
+                                       {
+                                               if(i != index) continue;
+                                               tag2->removeFrame(*it);
+                                               break;
+                                       }
+                                       return METADATA_EDITOR_ERROR_NONE;
+                               }
+                       }
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+}
+
+// *** This function is used to free memory that was allocated with metadata_editor_create(...) and metadata_editor_set_path(...) functions *** //
+extern "C" int metadata_editor_destroy(metadata_editor_h metadata)
+{
+       // Check if we have a valid argument to work with
+       if(metadata == NULL)
+       {
+               metadata_editor_error("INVALID Handle\n");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
+
+       switch(_metadata->filetype)
+       {
+               case METADATA_EDITOR_FORMAT_MP3:
+               {
+                       // Bring the pointer to actual file type
+                       TagLib::MPEG::File* _file = (TagLib::MPEG::File*)_metadata->file;
+                       metadata_editor_info("The file with address %lX will now be freed\n", _metadata->file);
+                       delete _file;
+                       break;
+               }
+               case METADATA_EDITOR_FORMAT_MP4:
+               {
+                       TagLib::MP4::File* _file = (TagLib::MP4::File*)_metadata->file;
+                       metadata_editor_info("The file with address %lX will now be freed\n", _metadata->file);
+                       delete _file;
+                       break;
+               }
+#if 0
+               case METADATA_EDITOR_FORMAT_FLAC:
+               {
+                       TagLib::FLAC::File* _file = (TagLib::FLAC::File*)_metadata->file;
+                       metadata_editor_info("The file with address %lX will now be freed\n", _metadata->file);
+                       delete _file;
+                       break;
+               }
+               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
+               {
+                       TagLib::Ogg::Vorbis::File* _file = (TagLib::Ogg::Vorbis::File*)_metadata->file;
+                       metadata_editor_info("The file with address %lX will now be freed\n", _metadata->file);
+                       delete _file;
+                       break;
+               }
+               case METADATA_EDITOR_FORMAT_OGG_FLAC:
+               {
+                       TagLib::Ogg::FLAC::File* _file = (TagLib::Ogg::FLAC::File*)_metadata->file;
+                       metadata_editor_info("The file with address %lX will now be freed\n", _metadata->file);
+                       delete _file;
+                       break;
+               }
+               case METADATA_EDITOR_FORMAT_WAV:
+               {
+                       TagLib::RIFF::WAV::File* _file = (TagLib::RIFF::WAV::File*)_metadata->file;
+                       metadata_editor_info("The file with address %lX will now be freed\n", _metadata->file);
+                       delete _file;
+                       break;
+               }
+#endif
+               default:
+                       metadata_editor_error("Wrong file type\n");
+                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
+
+       metadata_editor_info("<metadata_editor_s> with address %lX will be freed\n", metadata);
+       delete _metadata;
+
+       return METADATA_EDITOR_ERROR_NONE;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..a2e3764
--- /dev/null
@@ -0,0 +1,18 @@
+SET(fw_test "${fw_name}-test")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_test} REQUIRED dlog)
+
+FOREACH(flag ${${fw_test}_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -pie")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+    GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+    MESSAGE("${src_name}")
+    ADD_EXECUTABLE(${src_name} ${src})
+    TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS})
+ENDFOREACH()
diff --git a/test/metadata_editor_test.c b/test/metadata_editor_test.c
new file mode 100755 (executable)
index 0000000..0816bcf
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+* Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <metadata_editor.h>
+
+#define SAFE_FREE(src)         { if(src) {free(src); src = NULL;}}
+
+int dummy;
+
+void __flush();
+void __printRetValue(const char* func_name, int result);
+static bool __get_tag_info(metadata_editor_h metadata);
+static bool __write_tag_info(metadata_editor_h metadata);
+static bool __add_picture(metadata_editor_h metadata);
+static bool __delete_pictures(metadata_editor_h metadata);
+
+void __flush()
+{
+       char c;
+       while((c = getc(stdin)) != '\n');
+}
+
+void __printRetValue(const char* func_name, int result)
+{
+       printf("In function %s result is ", func_name);
+       if(result == METADATA_EDITOR_ERROR_NONE)                                printf("METADATA_EDITOR_ERROR_NONE\n");
+       else if(result == METADATA_EDITOR_ERROR_INVALID_PARAMETER)      printf("METADATA_EDITOR_ERROR_INVALID_PARAMETER\n");
+       else if(result == METADATA_EDITOR_ERROR_OUT_OF_MEMORY)          printf("METADATA_EDITOR_ERROR_OUT_OF_MEMORY\n");
+       else if(result == METADATA_EDITOR_ERROR_FILE_EXISTS)            printf("METADATA_EDITOR_ERROR_FILE_EXISTS\n");
+       else if(result == METADATA_EDITOR_ERROR_OPERATION_FAILED)       printf("METADATA_EDITOR_ERROR_OPERATION_FAILED\n");
+       else                                                            printf("Unallowed value. Error!\n");
+}
+
+static bool __get_tag_info(metadata_editor_h metadata)
+{
+       int ret = METADATA_EDITOR_ERROR_NONE;
+
+       char *artist = NULL;
+       char *title = NULL;
+       char *album = NULL;
+       char *genre = NULL;
+       char *composer = NULL;
+       char *copyright = NULL;
+       char *date = NULL;
+       char *description = NULL;
+       char *comment = NULL;
+       char *track_num = NULL;
+       char* picture_index = NULL;
+       int picture_size = 0;
+       char *picture_type = NULL;
+       void *picture = NULL;
+       char *conductor = NULL;
+       char *lyric = NULL;
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_ARTIST, &artist);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("1. - artist = [%s]\n", artist);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_TITLE, &title);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("2. - title = [%s]\n", title);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_ALBUM, &album);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("3. - album = [%s]\n", album);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_GENRE, &genre);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("4. - genre = [%s]\n", genre);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_AUTHOR, &composer);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("5. - composer = [%s]\n", composer);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_COPYRIGHT, &copyright);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("6. - copyright = [%s]\n", copyright);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_DATE, &date);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("7. - date = [%s]\n", date);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_DESCRIPTION, &description);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("8. - description = [%s]\n", description);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_COMMENT, &comment);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("9. - comment = [%s]\n", comment);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_TRACK_NUM, &track_num);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("10. - track_num = [%s]\n", track_num);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_PICTURE_NUM, &picture_index);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       printf("Picture index is [%s]\n", picture_index);
+#if 0
+       if((filetype == METADATA_EDITOR_TYPE_OGG_VORBIS) || (filetype == METADATA_EDITOR_TYPE_OGG_FLAC))
+       {
+               if(ret != METADATA_EDITOR_ERROR_INVALID_PARAMETER)
+               printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       }
+       else
+       {
+#endif
+               if(ret != METADATA_EDITOR_ERROR_NONE)           printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+               else if((ret == METADATA_EDITOR_ERROR_NONE) && picture_index)
+               {
+                       uint num, i;
+                       num = atoi(picture_index);
+                       printf("Number of pictures: %u\n", num);
+                       for(i = 0; i < num; ++i)
+                       {
+                               ret = metadata_editor_get_picture(metadata, i, &picture, &picture_size, &picture_type);
+                               //__printRetValue("metadata_editor_get_picture(...)", ret);
+                               if(ret == METADATA_EDITOR_ERROR_NONE && picture)
+                               {
+                                       printf("Saving picture number %u\n", i);
+                                       int size = 30;
+                                       char picture_file_name[size];
+                                       snprintf(picture_file_name, size, "outputFile_%u" ,i+1);
+                                       if(strncmp(picture_type, "image/jpeg", strlen("image/jpeg")) == 0)              strcat(picture_file_name,".jpg");
+                                       else if(strncmp(picture_type, "image/png", strlen("image/jpeg")) == 0)  strcat(picture_file_name,".png");
+                                       FILE * fout = fopen(picture_file_name, "wb");
+                                       fwrite(picture, picture_size, 1, fout);
+                                       fclose(fout);
+                               }
+                               else
+                                       printf("Error occured while picture extraction\n");
+                       }
+                       free(picture_index);
+               }
+#if 0
+       }
+#endif
+       printf("11. - picture size = [%u]\n", picture_size);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_CONDUCTOR, &conductor);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("12. - conductor = [%s]\n", conductor);
+
+       ret = metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_UNSYNCLYRICS, &lyric);
+       //__printRetValue("metadata_editor_get_metadata(...)",ret);
+       if(ret != METADATA_EDITOR_ERROR_NONE)   printf("Fail metadata_editor_get_metadata() at line [%d]\n", __LINE__);
+       printf("13. - lyric = [%s]\n", lyric);
+
+       SAFE_FREE(artist);
+       SAFE_FREE(title);
+       SAFE_FREE(album);
+       SAFE_FREE(genre);
+       SAFE_FREE(composer);
+       SAFE_FREE(copyright);
+       SAFE_FREE(date);
+       SAFE_FREE(description);
+       SAFE_FREE(comment);
+       SAFE_FREE(track_num);
+       SAFE_FREE(picture);
+       SAFE_FREE(conductor);
+       SAFE_FREE(lyric);
+
+       return true;
+}
+
+static bool __write_tag_info(metadata_editor_h metadata)
+{
+
+       char input_data[400];
+
+       printf("\n===========================================");
+       printf("\nPlease, type in the following tag data: ");
+       printf("\n===========================================\n");
+
+       printf("\n 1. - Writing artist: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_ARTIST, input_data);
+       *input_data = '\0';
+       printf("2. - Writing title: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_TITLE, input_data);
+       *input_data = '\0';
+       printf("3. - Writing album: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_ALBUM, input_data);
+       *input_data = '\0';
+       printf("4. - Writing genre: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_GENRE, input_data);
+       *input_data = '\0';
+       printf("5. - Writing composer: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_AUTHOR, input_data);
+       *input_data = '\0';
+       printf("6. - Writing copyright: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_COPYRIGHT, input_data);
+       *input_data = '\0';
+       printf("7. - Writing year: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_DATE, input_data);
+       *input_data = '\0';
+       printf("8. - Writing description: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_DESCRIPTION, input_data);
+       *input_data = '\0';
+       printf("9. - Writing track: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_TRACK_NUM, input_data);
+       *input_data = '\0';
+       printf("10. - Writing comment: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_COMMENT, input_data);
+       *input_data = '\0';
+       printf("11. - Writing conductor: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_CONDUCTOR, input_data);
+       *input_data = '\0';
+       printf("12. - Writing lyrics: ");
+       dummy = scanf("%[^\n]",input_data);
+       __flush();
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_UNSYNCLYRICS,input_data);
+       *input_data = '\0';
+
+       metadata_editor_update_metadata(metadata);
+
+       return true;
+}
+
+static bool __delete_tag_info(metadata_editor_h metadata)
+{
+       printf("\n 1. - Deleting artist: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_ARTIST, "");
+       printf("\n 2. - Deleting title: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_TITLE, 0);
+       printf("\n 3. - Deleting album: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_ALBUM, "");
+       printf("\n 4. - Deleting genre: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_GENRE, 0);
+       printf("\n 5. - Deleting composer: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_AUTHOR, "");
+       printf("\n 6. - Deleting copyright: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_COPYRIGHT, 0);
+       printf("\n 7. - Deleting year: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_DATE, "");
+       printf("\n 8. - Deleting description: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_DESCRIPTION, 0);
+       printf("\n 9. - Deleting track: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_TRACK_NUM, "");
+       printf("\n 10. - Deleting comment: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_COMMENT, 0);
+       printf("\n 11. - Deleting conductor: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_CONDUCTOR, "");
+       printf("\n 12. - Deleting lyrics: ");
+       metadata_editor_set_metadata(metadata, METADATA_EDITOR_ATTR_UNSYNCLYRICS, 0);
+
+       metadata_editor_update_metadata(metadata);
+       return true;
+}
+
+static bool __add_picture(metadata_editor_h metadata)
+{
+       uint c2 = 0;
+       char *picture_filename = NULL;
+
+       printf("\n=============================");
+       printf("\n Choose picture: PNG or JPG ");
+       printf("\n=============================");
+       printf("\n |  TestImage.png  ->  1    | ");
+       printf("\n |  TestImage.jpg  ->  2    | ");
+       printf("\n Your choice : ");
+
+       dummy = scanf("%u",  &c2);
+       __flush();
+
+       switch (c2)
+       {
+               case 1:
+               printf("\n===========================");
+               printf("\n Your choice is TestImage.png\n");
+               picture_filename = "TestImage.png";
+               break;
+
+               case 2:
+               printf("\n===========================");
+               printf("\n Your choice is TestImage.jpg\n");
+               picture_filename = "TestImage.jpg";
+               break;
+       }
+
+       metadata_editor_append_picture(metadata, picture_filename);
+
+       return true;
+}
+
+static bool __delete_pictures(metadata_editor_h metadata)
+{
+       uint num, i;
+       char *picture_index = NULL;
+
+       metadata_editor_get_metadata(metadata, METADATA_EDITOR_ATTR_PICTURE_NUM, &picture_index);
+       printf("The number of pictures is [%s]\n", picture_index);
+
+       if(picture_index)
+       {
+               num = atoi(picture_index);
+               printf("Number of pictures: %u\n", num);
+
+               for(i = 0; i < num; ++i)
+               {
+                       metadata_editor_remove_picture(metadata, 0);
+                       //__printRetValue("metadata_editor_remove_picture(...)", ret);
+               }
+       }
+       else
+               printf("There are no pictures to delete\n");
+       return true;
+}
+
+static bool __save_tags(metadata_editor_h metadata)
+{
+
+       metadata_editor_update_metadata(metadata);
+
+       return true;
+}
+
+
+int main(int argc, char *argv[])
+{
+       int ret = METADATA_EDITOR_ERROR_NONE;
+       metadata_editor_h metadata = NULL;
+       int cnt = argc -1;
+       uint c2 = 0;
+
+       if(cnt < 1)
+       {
+               printf("\n====================================================================================================");
+               printf("\n Please type file path and media type as media-metadata-test /opt/usr/media/Sounds/<filename.mp3>   ");
+               printf("\n====================================================================================================");
+               return 0;
+       }
+       printf("\n\n --- media metadata test start ---\n\n");
+
+       ret = metadata_editor_create(&metadata);
+       //__printRetValue("metadata_editor_create(...)",ret);
+
+       if(ret != METADATA_EDITOR_ERROR_NONE)
+       {
+               printf("Fail metadata_editor_create()  at line [%d]\n",  __LINE__);
+               return 0;
+       }
+
+       ret = metadata_editor_set_path(metadata, argv[1]);
+       //__printRetValue("metadata_editor_set_path(...)",ret);
+
+       if(ret != METADATA_EDITOR_ERROR_NONE)
+       {
+               printf("Fail metadata_editor_set_path() at line [%d]\n",  __LINE__);
+               goto exception;
+       }
+
+       while (c2 != 9)
+       {
+               c2 = 0;
+               printf("\n========================================================================");
+               printf("\n The file you are working with is %s", argv[1]);
+               printf("\n======================================================================== ");
+               printf("\n Choose desired operation for testing:\n");
+               printf("1 - Read tags.       Press 1 \n");
+               printf("2 - Write tags.      Press 2 \n");
+               printf("3 - Delete tags.     Press 3 \n");
+               printf("4 - Add picture.     Press 4 \n");
+               printf("5 - Delete picture.  Press 5 \n");
+               printf("6 - Save tags.       Press 6 \n");
+               printf("9 - Quit.            Press 9 ");
+               printf("\n=========================\n");
+               printf("\n Your choice : ");
+               dummy = scanf("%u",  &c2);
+               __flush();
+
+               switch (c2)
+               {
+                       case 1:
+                               printf("\n==============");
+                               printf("\n Reading tags \n");
+                               __get_tag_info(metadata);
+                               break;
+                       case 2:
+                               printf("\n==============");
+                               printf("\n Writing tags ");
+                               __write_tag_info(metadata);
+                               break;
+                       case 3:
+                               printf("\n==============");
+                               printf("\n Deleting tags ");
+                               __delete_tag_info(metadata);
+                               break;
+                       case 4:
+                               printf("\n==============");
+                               printf("\n Adding picture ");
+                               __add_picture(metadata);
+                               break;
+                       case 5:
+                               printf("\n==============");
+                               printf("\n Deleting pictures \n");
+                               __delete_pictures(metadata);
+                               break;
+                       case 6:
+                               printf("\n==============");
+                               printf("\n Saving updated tags \n");
+                               __save_tags(metadata);
+                               break;
+               }
+       }
+
+exception:
+       ret = metadata_editor_destroy(metadata);
+       if(ret != METADATA_EDITOR_ERROR_NONE)
+       {
+               printf("Fail metadata_editor_destroy [%d]\n", ret);
+               return 0;
+       }
+
+       printf("\n\n--- metadata writer test end ---\n\n");
+
+       return ret;
+}