[MetadataEditor] Add MetadataEditor API
authorMinje Ahn <minje.ahn@samsung.com>
Tue, 14 Feb 2017 03:39:44 +0000 (12:39 +0900)
committerMinje Ahn <minje.ahn@samsung.com>
Thu, 2 Mar 2017 08:00:41 +0000 (17:00 +0900)
Change-Id: I3841231c25a92e216ff9c1ac251e374b993b3f72
Signed-off-by: Minje Ahn <minje.ahn@samsung.com>
packaging/csapi-multimedia.spec
src/Tizen.Multimedia/Interop/Interop.Libraries.cs
src/Tizen.Multimedia/Interop/Interop.MetadataEditor.cs [new file with mode: 0755]
src/Tizen.Multimedia/MetadataEditor/MetadataEditor.cs [new file with mode: 0755]
src/Tizen.Multimedia/MetadataEditor/MetadataEditorAttr.cs [new file with mode: 0755]
src/Tizen.Multimedia/MetadataEditor/MetadataEditorErrorFactory.cs [new file with mode: 0755]

index c594bcc..dce4004 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       csapi-multimedia
 Summary:    Tizen Multimedia API for C#
-Version:    1.0.33
+Version:    1.0.34
 Release:    0
 Group:      Development/Libraries
 License:    Apache-2.0
index f876246..7556538 100755 (executable)
@@ -23,6 +23,7 @@ internal static partial class Interop
         public const string SoundManager = "libcapi-media-sound-manager.so.0";
         public const string AudioIO = "libcapi-media-audio-io.so.0";
         public const string ScreenMirroring = "libcapi-media-screen-mirroring.so.0";
+        public const string MetadataEditor = "libcapi-media-metadata-editor.so";
         public const string MetadataExtractor = "libcapi-media-metadata-extractor.so";
         public const string MediaController = "libcapi-media-controller.so.0";
         public const string MediaTool = "libcapi-media-tool.so.0";
diff --git a/src/Tizen.Multimedia/Interop/Interop.MetadataEditor.cs b/src/Tizen.Multimedia/Interop/Interop.MetadataEditor.cs
new file mode 100755 (executable)
index 0000000..c187e7b
--- /dev/null
@@ -0,0 +1,36 @@
+using System;
+using System.Runtime.InteropServices;
+using Tizen.Multimedia;
+
+internal static partial class Interop
+{
+    internal static partial class MetadataEditor
+    {
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_create")]
+        internal static extern MetadataEditorError Create(out IntPtr handle);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_set_path")]
+        internal static extern MetadataEditorError SetPath(IntPtr handle, string path);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_destroy")]
+        internal static extern MetadataEditorError Destroy(IntPtr handle);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_get_metadata")]
+        internal static extern MetadataEditorError GetMetadata(IntPtr handle, MetadataEditorAttr attribute, out IntPtr value);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_set_metadata")]
+        internal static extern MetadataEditorError SetMetadata(IntPtr handle, MetadataEditorAttr attribute, string value);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_update_metadata")]
+        internal static extern MetadataEditorError UpdateMetadata(IntPtr handle);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_get_picture")]
+        internal static extern MetadataEditorError GetPicture(IntPtr handle, int index, out IntPtr picture, out int size, out IntPtr mimeType);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_append_picture")]
+        internal static extern MetadataEditorError AddPicture(IntPtr handle, string path);
+
+        [DllImport(Libraries.MetadataEditor, EntryPoint = "metadata_editor_remove_picture")]
+        internal static extern MetadataEditorError RemovePicture(IntPtr handle, int index);
+    }
+}
diff --git a/src/Tizen.Multimedia/MetadataEditor/MetadataEditor.cs b/src/Tizen.Multimedia/MetadataEditor/MetadataEditor.cs
new file mode 100755 (executable)
index 0000000..83175ee
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+* Copyright (c) 2016 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.
+*/
+
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Tizen.Multimedia
+{
+    static internal class MetadataEditorLog
+    {
+        internal const string LogTag = "Tizen.Multimedia.MetadataEditor";
+    }
+
+    /// <summary>
+    /// The Metadata editor class provides a set of functions to edit the metadata of the media file
+    /// </summary>
+    /// <privilege>
+    /// If you want to access only internal storage,
+    /// you should add privilege http://tizen.org/privilege/mediastorage. \n
+    /// Or if you want to access only external storage,
+    /// you should add privilege http://tizen.org/privilege/externalstorage. \n
+    /// </privilege>
+    public class MetadataEditor : IDisposable
+    {
+        private bool _disposed = false;
+        private IntPtr _handle = IntPtr.Zero;
+
+        private IntPtr MetadataHandle
+        {
+            get
+            {
+                if (_handle == IntPtr.Zero)
+                {
+                    throw new ObjectDisposedException(nameof(MetadataEditor));
+                }
+                return _handle;
+            }
+        }
+
+        /// <summary>
+        /// Metadata extractor constructor
+        /// </summary>
+        /// <param name="path"> The path of the media file to edit metadata </param>
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="OutOfMemoryException">Memory allocation failed.</exception>
+        /// <exception cref="NotSupportedException">Unsupported file type</exception>
+        /// <exception cref="FileNotFoundException">File not exist</exception>
+        public MetadataEditor(string path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+
+            MetadataEditorError ret = Interop.MetadataEditor.Create(out _handle);
+            MetadataEditorErrorFactory.ThrowIfError(ret, "Failed to create metadata");
+
+            try
+            {
+                MetadataEditorErrorFactory.ThrowIfError(
+                    Interop.MetadataEditor.SetPath(MetadataHandle, path), "Failed to set path");
+            }
+            catch (Exception)
+            {
+                Interop.MetadataEditor.Destroy(_handle);
+                _handle = IntPtr.Zero;
+                throw;
+            }
+        }
+
+        private string GetParam(MetadataEditorAttr attr)
+        {
+            IntPtr val = IntPtr.Zero;
+
+            try
+            {
+                MetadataEditorError e = Interop.MetadataEditor.GetMetadata(MetadataHandle, attr, out val);
+                MetadataEditorErrorFactory.ThrowIfError(e, "Failed to get metadata");
+
+                return Marshal.PtrToStringAnsi(val);
+            }
+            finally
+            {
+                Interop.Libc.Free(val);
+            }
+        }
+
+        private void SetParam(MetadataEditorAttr attr, string value)
+        {
+            MetadataEditorErrorFactory.ThrowIfError(
+                    Interop.MetadataEditor.SetMetadata(MetadataHandle, attr, value), "Fail to set value");
+        }
+
+        /// <summary>
+        /// Artist of media
+        /// </summary>
+        public string Artist
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Artist);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Artist, value);
+            }
+        }
+
+        /// <summary>
+        /// Title of media
+        /// </summary>
+        public string Title
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Title);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Title, value);
+            }
+        }
+
+        /// <summary>
+        /// Album name of media
+        /// </summary>
+        public string Album
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Album);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Album, value);
+            }
+        }
+
+        /// <summary>
+        /// Genre of media
+        /// </summary>
+        public string Genre
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Genre);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Genre, value);
+            }
+        }
+
+        /// <summary>
+        /// Author of media
+        /// </summary>
+        public string Author
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Author);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Author, value);
+            }
+        }
+
+        /// <summary>
+        /// Copyright of media
+        /// </summary>
+        public string Copyright
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Copyright);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Copyright, value);
+            }
+        }
+
+        /// <summary>
+        /// Date of media
+        /// </summary>
+        /// <remarks>
+        /// If the added media contains ID3 tag, This parameter refers to the recording time.
+        /// If the added media is a mp4 format, This parameter refers to the year.
+        /// </remarks>
+        public string Date
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Date);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Date, value);
+            }
+        }
+
+        /// <summary>
+        /// Description of media
+        /// </summary>
+        public string Description
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Description);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Description, value);
+            }
+        }
+
+        /// <summary>
+        /// Comment of media
+        /// </summary>
+        public string Comment
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Comment);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Comment, value);
+            }
+        }
+
+        /// <summary>
+        /// Track number of media
+        /// </summary>
+        public string TrackNumber
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.TrackNumber);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.TrackNumber, value);
+            }
+        }
+
+        /// <summary>
+        /// Album art count of media
+        /// </summary>
+        public string PictureCount
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.PictureCount);
+            }
+        }
+
+        /// <summary>
+        /// Conductor of media
+        /// </summary>
+        public string Conductor
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.Conductor);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.Conductor, value);
+            }
+        }
+
+        /// <summary>
+        /// Unsynchronized lyric of media
+        /// </summary>
+        public string UnsyncLyrics
+        {
+            get
+            {
+                return GetParam(MetadataEditorAttr.UnsyncLyrics);
+            }
+            set
+            {
+                SetParam(MetadataEditorAttr.UnsyncLyrics, value);
+            }
+        }
+
+        /// <summary>
+        /// Writes the modified metadata to a media file
+        /// </summary>
+        /// <exception cref="InvalidOperationException"> When internal process error is occured</exception>
+        public void Commit()
+        {
+            MetadataEditorErrorFactory.ThrowIfError(
+                Interop.MetadataEditor.UpdateMetadata(MetadataHandle), "Failed to update file");
+        }
+
+        /// <summary>
+        /// Gets the artwork image in a media file
+        /// </summary>
+        /// <param name="index"> Index of picture to import </param>
+        /// <returns> Artwork included in the media file</returns>
+        /// <exception cref="InvalidOperationException"> When internal process error is occured</exception>
+        /// <exception cref="ArgumentOutOfRangeException"> Wrong index number </exception>
+        public Artwork GetPicture(int index)
+        {
+            if (index < 0)
+            {
+                throw new ArgumentOutOfRangeException("Index should be larger than 0 [" + index + "]");
+            }
+
+            IntPtr data = IntPtr.Zero;
+            int size;
+            IntPtr mimeType = IntPtr.Zero;
+
+            try
+            {
+                MetadataEditorErrorFactory.ThrowIfError(
+                    Interop.MetadataEditor.GetPicture(MetadataHandle, index, out data, out size, out mimeType), "Failed to get the value");
+
+                if (size > 0)
+                {
+                    byte[] tmpBuf = new byte[size];
+                    Marshal.Copy(data, tmpBuf, 0, size);
+
+                    return new Artwork(tmpBuf, Marshal.PtrToStringAnsi(mimeType));
+                }
+
+                return null;
+            }
+            finally
+            {
+                if (data != IntPtr.Zero)
+                {
+                    Interop.Libc.Free(data);
+                }
+
+                if (mimeType != IntPtr.Zero)
+                {
+                    Interop.Libc.Free(mimeType);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Append the picture to the media file
+        /// </summary>
+        /// <param name="path"> The path of picture for adding to the metadata </param>
+        /// <exception cref="InvalidOperationException"> When internal process error is occured</exception>
+        /// <exception cref="ArgumentNullException"> Picture path is null</exception>
+        public void AddPicture(string path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException(nameof(path));
+            }
+
+            MetadataEditorErrorFactory.ThrowIfError(
+                Interop.MetadataEditor.AddPicture(MetadataHandle, path), "Failed to append picture");
+        }
+
+        /// <summary>
+        /// Remove the picture from the media file
+        /// </summary>
+        /// <param name="index"> Index of picture to remove </param>
+        /// <exception cref="InvalidOperationException"> When internal process error is occured</exception>
+        /// <exception cref="ArgumentOutOfRangeException"> Wrong index number </exception>
+        public void RemovePicture(int index)
+        {
+            if (index < 0)
+            {
+                throw new ArgumentOutOfRangeException("Index should be larger than 0 [" + index + "]");
+            }
+
+            MetadataEditorErrorFactory.ThrowIfError(
+                Interop.MetadataEditor.RemovePicture(MetadataHandle, index), "Failed to remove picture");
+        }
+
+        /// <summary>
+        /// Metadata Editor destructor
+        /// </summary>
+        ~MetadataEditor()
+        {
+            Dispose(false);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    // To be used if there are any other disposable objects
+                }
+                if (_handle != IntPtr.Zero)
+                {
+                    Interop.MetadataEditor.Destroy(_handle);
+                    _handle = IntPtr.Zero;
+                }
+                _disposed = true;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia/MetadataEditor/MetadataEditorAttr.cs b/src/Tizen.Multimedia/MetadataEditor/MetadataEditorAttr.cs
new file mode 100755 (executable)
index 0000000..30b972b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2016 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.
+*/
+
+namespace Tizen.Multimedia
+{
+    internal enum MetadataEditorAttr
+    {
+        Artist,
+        Title,
+        Album,
+        Genre,
+        Author,
+        Copyright,
+        Date,
+        Description,
+        Comment,
+        TrackNumber,
+        PictureCount,
+        Conductor,
+        UnsyncLyrics,
+    }
+}
\ No newline at end of file
diff --git a/src/Tizen.Multimedia/MetadataEditor/MetadataEditorErrorFactory.cs b/src/Tizen.Multimedia/MetadataEditor/MetadataEditorErrorFactory.cs
new file mode 100755 (executable)
index 0000000..8875b0f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2016 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.
+*/
+
+
+using System;
+using System.IO;
+using Tizen.Internals.Errors;
+
+namespace Tizen.Multimedia
+{
+    /// <summary>
+    /// Enumeration for metadata extractor's error codes.
+    /// </summary>
+    internal enum MetadataEditorError
+    {
+        None = ErrorCode.None,                          // Success
+        InvalidParameter = ErrorCode.InvalidParameter,  // Invalid parameter
+        OutOfMemory = ErrorCode.OutOfMemory,            // Out of memory
+        FileNotExists = ErrorCode.FileExists,              // File does not exist
+        PermissionDenied = ErrorCode.PermissionDenied,  // Permission deny
+        NotSupported = ErrorCode.NotSupported,          // Unsupported type
+        TizenMetadataEditorError = -0x019C0000,
+        OperationFailed = TizenMetadataEditorError | 0x01  // Invalid operation
+    };
+
+    internal static class MetadataEditorErrorFactory
+    {
+        internal static void ThrowIfError(MetadataEditorError errorCode, string errorMessage)
+        {
+            switch (errorCode)
+            {
+                case MetadataEditorError.InvalidParameter:
+                    throw new ArgumentException(errorMessage);
+
+                case MetadataEditorError.OutOfMemory:
+                    throw new OutOfMemoryException(errorMessage);
+
+                case MetadataEditorError.FileNotExists:
+                    throw new FileNotFoundException(errorMessage);
+
+                case MetadataEditorError.PermissionDenied:
+                    throw new UnauthorizedAccessException(errorMessage);
+
+                case MetadataEditorError.NotSupported:
+                    throw new NotSupportedException(errorMessage);
+
+                case MetadataEditorError.OperationFailed:
+                    throw new InvalidOperationException(errorMessage);
+            }
+        }
+    }
+}
+