using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
+using Tizen.System;
namespace Tizen.Content.MediaContent
{
/// <summary>
/// Provides commands to manage the media information and query related items in the database.
/// </summary>
+ /// <since_tizen> 4 </since_tizen>
public class MediaInfoCommand : MediaCommand
{
/// <summary>
/// </summary>
/// <param name="database">The <see cref="MediaDatabase"/> that the commands run on.</param>
/// <exception cref="ArgumentNullException"><paramref name="database"/> is null.</exception>
- /// <exception cref="ObjectDisposedException"><paramref name="database"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException"><paramref name="database"/> has already been disposed.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaInfoCommand(MediaDatabase database) : base(database)
{
}
/// <param name="mediaId">The media ID to count the bookmarks added to the media.</param>
/// <returns>The number of the bookmarks.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountBookmark(string mediaId)
{
return CountBookmark(mediaId, null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The number of the bookmarks.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountBookmark(string mediaId, CountArguments arguments)
{
ValidateDatabase();
/// <param name="mediaId">The media ID to select the bookmarks added to the media.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<Bookmark> SelectBookmark(string mediaId)
{
return SelectBookmark(mediaId, null);
/// <param name="filter">The criteria to use to filter. This value can be null.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<Bookmark> SelectBookmark(string mediaId, SelectArguments filter)
{
ValidateDatabase();
/// <param name="mediaId">The media ID to count face information added to the media.</param>
/// <returns>The number of the face information.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountFaceInfo(string mediaId)
{
return CountFaceInfo(mediaId, null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The number of the face information.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API11; Will be removed in API13.")]
public int CountFaceInfo(string mediaId, CountArguments arguments)
{
ValidateDatabase();
/// <param name="mediaId">The media ID to select face information added to the media.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API11; Will be removed in API13.")]
public MediaDataReader<FaceInfo> SelectFaceInfo(string mediaId)
{
return SelectFaceInfo(mediaId, null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API11; Will be removed in API13.")]
public MediaDataReader<FaceInfo> SelectFaceInfo(string mediaId, SelectArguments arguments)
{
ValidateDatabase();
/// <returns>The number of tags.</returns>
/// <param name="mediaId">The media ID to count tags added to the media.</param>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountTag(string mediaId)
{
return CountTag(mediaId, null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The number of tags.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountTag(string mediaId, CountArguments arguments)
{
ValidateDatabase();
/// <param name="mediaId">The media ID to select tags added to the media.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<Tag> SelectTag(string mediaId)
{
return SelectTag(mediaId, null);
/// <param name="filter">The criteria to use to filter. This value can be null.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<Tag> SelectTag(string mediaId, SelectArguments filter)
{
ValidateDatabase();
/// </summary>
/// <returns>The number of the media information.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountMedia()
{
return CountMedia(null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The number of media information.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountMedia(CountArguments arguments)
{
ValidateDatabase();
/// <param name="mediaId">The media ID to retrieve.</param>
/// <returns>The <see cref="MediaInfo"/> instance if the matched record was found in the database, otherwise null.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaInfo SelectMedia(string mediaId)
{
ValidateDatabase();
/// <param name="columnKey">The column key.</param>
/// <returns>The number of groups.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentException"><paramref name="columnKey"/> is invalid.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountGroupBy(MediaInfoColumnKey columnKey)
{
return CountGroupBy(columnKey, null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The number of groups.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentException"><paramref name="columnKey"/> is invalid.</exception>
+ /// <since_tizen> 4 </since_tizen>
public int CountGroupBy(MediaInfoColumnKey columnKey, CountArguments arguments)
{
ValidateDatabase();
/// <param name="columnKey">The column key.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentException"><paramref name="columnKey"/> is invalid.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<string> SelectGroupBy(MediaInfoColumnKey columnKey)
{
return SelectGroupBy(columnKey, null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentException"><paramref name="columnKey"/> is invalid.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<string> SelectGroupBy(MediaInfoColumnKey columnKey, SelectArguments arguments)
{
ValidateDatabase();
/// </summary>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<MediaInfo> SelectMedia()
{
return SelectMedia(arguments: null);
/// <param name="arguments">The criteria to use to filter. This value can be null.</param>
/// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaDataReader<MediaInfo> SelectMedia(SelectArguments arguments)
{
ValidateDatabase();
}
/// <summary>
+ /// Retrieves all matched ebook paths with given <paramref name="keyword"/>.
+ /// </summary>
+ /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
+ /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
+ /// <param name="keyword">The keyword to search.</param>
+ /// <returns>A list of ebook paths which contain <paramref name="keyword"/>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="keyword"/> is null.</exception>
+ /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
+ /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
+ /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <since_tizen> 9 </since_tizen>
+ public MediaDataReader<string> SelectEbookPath(string keyword)
+ {
+ ValidateDatabase();
+
+ IntPtr path = IntPtr.Zero;
+ uint length = 0;
+
+ ValidationUtil.ValidateNotNullOrEmpty(keyword, nameof(keyword));
+
+ try
+ {
+ Interop.BookInfo.GetPathByKeyword(keyword, out path, out length).
+ ThrowIfError("Failed to get path by keyword");
+
+ var list = new List<string>();
+ var current = path;
+ for (int i = 0; i < length; i++)
+ {
+ list.Add(Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(current)));
+ current = (IntPtr)((long)current + Marshal.SizeOf(typeof(IntPtr)));
+ }
+
+ return new MediaDataReader<string>(list);
+ }
+ finally
+ {
+ var current = path;
+ for (int i = 0; i < length; i++)
+ {
+ Interop.Libc.Free(Marshal.ReadIntPtr(current));
+ current = (IntPtr)((long)current + Marshal.SizeOf(typeof(IntPtr)));
+ }
+ }
+ }
+
+ /// <summary>
/// Deletes the media from the database.
/// </summary>
/// <privilege>http://tizen.org/privilege/content.write</privilege>
/// <param name="mediaId">The media ID to delete.</param>
/// <returns>true if the matched record was found and deleted, otherwise false.</returns>
- /// <remarks>The <see cref="MediaDatabase.ScanFile(string)"/> or the <see cref="MediaDatabase.ScanFolderAsync(string)"/> can be used instead.</remarks>
- /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <remarks>
+ /// The <see cref="MediaDatabase.ScanFile(string)"/> or the <see cref="MediaDatabase.ScanFolderAsync(string)"/> can be used instead.<br/>
+ /// Since API level 6, if the file related with the <paramref name="mediaId"/> in DB still exists in file system before calling this method,
+ /// <see cref="InvalidOperationException"/> will be thrown to keep consistency in DB.
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">
+ /// The <see cref="MediaDatabase"/> is disconnected.<br/>
+ /// -or-<br/>
+ /// The file related with the <paramref name="mediaId"/> in DB still exists in file system. (Since API level 6)
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
/// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <since_tizen> 4 </since_tizen>
public bool Delete(string mediaId)
{
ValidateDatabase();
return false;
}
- CommandHelper.Delete(Interop.MediaInfo.Delete, mediaId);
+ Interop.MediaInfo.GetMediaFromDB(mediaId, out var handle).
+ ThrowIfError("Failed to delete MediaInfo.");
+
+ var path = InteropHelper.GetString(handle, Interop.MediaInfo.GetFilePath);
+
+ // If we don't check file existence before calling `ScanFile` method,
+ // The inconsistency between DB and file system could be occurred.
+ if (File.Exists(path))
+ {
+ throw new InvalidOperationException("File still exists in file system. Remove it first.");
+ }
+
+ // Native 'delete' function was deprecated, so we need to use 'scan file' function instead of it.
+ Database.ScanFile(path);
+
return true;
}
/// <param name="path">The file path to add.</param>
/// <returns>The <see cref="MediaInfo"/> instance that contains the record information in the database.</returns>
/// <remarks>
- /// If the media already exists in the database, it returns the existing information.\n
- /// \n
- /// The <see cref="MediaDatabase.ScanFile(string)"/> or the <see cref="MediaDatabase.ScanFolderAsync(string)"/> can be used instead.\n
- /// \n
- /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.\n
- /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
+ /// If the media already exists in the database, it returns the existing information.<br/>
+ /// <br/>
+ /// The <see cref="MediaDatabase.ScanFile(string)"/> or the <see cref="MediaDatabase.ScanFolderAsync(string)"/> can be used instead.<br/>
+ /// <br/>
+ /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.<br/>
+ /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.<br/>
+ /// <br/>
+ /// If http://tizen.org/feature/content.scanning.others feature is not supported and the specified file is other-type,
+ /// <see cref="NotSupportedException"/> will be thrown.
/// </remarks>
/// <privilege>http://tizen.org/privilege/content.write</privilege>
/// <privilege>http://tizen.org/privilege/mediastorage</privilege>
/// <privilege>http://tizen.org/privilege/externalstorage</privilege>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
/// <exception cref="ArgumentException">
- /// <paramref name="path"/> is a zero-length string, contains only white space.\n
- /// -or-\n
- /// <paramref name="path"/> contains a hidden path that starts with '.'.\n
- /// -or-\n
+ /// <paramref name="path"/> is a zero-length string, contains only white space.<br/>
+ /// -or-<br/>
+ /// <paramref name="path"/> contains a hidden path that starts with '.'.<br/>
+ /// -or-<br/>
/// <paramref name="path"/> contains a directory containing the ".scan_ignore" file.
/// </exception>
/// <exception cref="FileNotFoundException"><paramref name="path"/> does not exists.</exception>
/// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
+ /// <since_tizen> 4 </since_tizen>
public MediaInfo Add(string path)
{
ValidateDatabase();
/// Adds media files into the media database.
/// </summary>
/// <remarks>
- /// The paths that already exist in the database will be ignored.\n
- /// At most 300 items can be added at once.\n
- /// \n
- /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.\n
- /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
+ /// The paths that already exist in the database will be ignored.<br/>
+ /// At most 300 items can be added at once.<br/>
+ /// <br/>
+ /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.<br/>
+ /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.<br/>
+ /// <br/>
+ /// If http://tizen.org/feature/content.scanning.others feature is not supported and the specified file is other-type,
+ /// <see cref="NotSupportedException"/> will be thrown.
/// </remarks>
/// <privilege>http://tizen.org/privilege/content.write</privilege>
/// <privilege>http://tizen.org/privilege/mediastorage</privilege>
/// <param name="paths">The paths of the media files to add.</param>
/// <returns>A task that represents the asynchronous add operation.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="paths"/> is null.</exception>
/// <exception cref="ArgumentException">
- /// <paramref name="paths"/> contains null.\n
- /// -or-\n
- /// <paramref name="paths"/> contains the invalid path.\n
- /// -or-\n
+ /// <paramref name="paths"/> contains null.<br/>
+ /// -or-<br/>
+ /// <paramref name="paths"/> contains the invalid path.<br/>
+ /// -or-<br/>
/// The number of <paramref name="paths"/> is 300 or more items.
/// </exception>
/// <exception cref="FileNotFoundException"><paramref name="paths"/> contains a path that does not exist.</exception>
/// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
+ /// <since_tizen> 4 </since_tizen>
public async Task AddAsync(IEnumerable<string> paths)
{
ValidateDatabase();
/// <param name="value">The value indicating whether the media is favorite.</param>
/// <returns>true if the matched record was found and updated, otherwise false.</returns>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
/// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <since_tizen> 4 </since_tizen>
public bool UpdateFavorite(string mediaId, bool value)
{
ValidateDatabase();
/// <param name="newPath">The path that the media has been moved to.</param>
/// <returns>true if the matched record was found and updated, otherwise false.</returns>
/// <remarks>
- /// Usually, it is used after the media file is moved to the another path.\n
- /// \n
- /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.\n
+ /// Usually, it is used after the media file is moved to the another path.<br/>
+ /// <br/>
+ /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.<br/>
/// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
/// </remarks>
/// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException">
- /// <paramref name="mediaId"/> is null.\n
- /// -or-\n
+ /// <paramref name="mediaId"/> is null.<br/>
+ /// -or-<br/>
/// <paramref name="newPath"/> is null.
/// </exception>
/// <exception cref="ArgumentException">
- /// <paramref name="mediaId"/> is a zero-length string, contains only white space.\n
- /// -or-\n
- /// <paramref name="newPath"/> is a zero-length string, contains only white space.\n
- /// -or-\n
- /// <paramref name="newPath"/> contains a hidden directory that starts with '.'.\n
- /// -or-\n
+ /// <paramref name="mediaId"/> is a zero-length string, contains only white space.<br/>
+ /// -or-<br/>
+ /// <paramref name="newPath"/> is a zero-length string, contains only white space.<br/>
+ /// -or-<br/>
+ /// <paramref name="newPath"/> contains a hidden directory that starts with '.'.<br/>
+ /// -or-<br/>
/// <paramref name="newPath"/> contains a directory containing the ".scan_ignore" file.
/// </exception>
/// <exception cref="FileNotFoundException"><paramref name="newPath"/> does not exists.</exception>
/// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <since_tizen> 4 </since_tizen>
public bool Move(string mediaId, string newPath)
{
ValidateDatabase();
/// <param name="mediaId">The media ID to create the thumbnail.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the thumbnail path.</returns>
/// <exception cref="InvalidOperationException">
- /// The <see cref="MediaDatabase"/> is disconnected.\n
- /// -or-\n
+ /// The <see cref="MediaDatabase"/> is disconnected.<br/>
+ /// -or-<br/>
/// An internal error occurred while executing.
/// </exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="RecordNotFoundException"><paramref name="mediaId"/> does not exist in the database.</exception>
/// </exception>
/// <exception cref="FileNotFoundException">The file of the media does not exists; moved or deleted.</exception>
/// <exception cref="UnsupportedContentException">
- /// The thumbnail is not available for the given media.\n
- /// -or-\n
- /// The media is in the external USB storage (<see cref="MediaInfo.StorageType"/> is <see cref="StorageType.ExternalUsb"/>).
+ /// The thumbnail is not available for the given media.<br/>
+ /// -or-<br/>
+ /// The media is in the external USB storage.
/// </exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API10; Will be removed in API12. Please use CreateThumbnail instead.")]
public Task<string> CreateThumbnailAsync(string mediaId)
{
return CreateThumbnailAsync(mediaId, CancellationToken.None);
/// <param name="cancellationToken">The token to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the thumbnail path.</returns>
/// <exception cref="InvalidOperationException">
- /// The <see cref="MediaDatabase"/> is disconnected.\n
- /// -or-\n
+ /// The <see cref="MediaDatabase"/> is disconnected.<br/>
+ /// -or-<br/>
/// An internal error occurred while executing.
/// </exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="RecordNotFoundException"><paramref name="mediaId"/> does not exist in the database.</exception>
/// </exception>
/// <exception cref="FileNotFoundException">The file of the media does not exists; moved or deleted.</exception>
/// <exception cref="UnsupportedContentException">
- /// The thumbnail is not available for the given media.\n
- /// -or-\n
- /// The media is in the external USB storage (<see cref="MediaInfo.StorageType"/> is <see cref="StorageType.ExternalUsb"/>).
+ /// The thumbnail is not available for the given media.<br/>
+ /// -or-<br/>
+ /// The media is in the external USB storage.
/// </exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API10; Will be removed in API12. Please use CreateThumbnail instead.")]
public Task<string> CreateThumbnailAsync(string mediaId, CancellationToken cancellationToken)
{
ValidateDatabase();
var tcs = new TaskCompletionSource<string>();
- Interop.MediaInfo.GetMediaFromDB(mediaId, out var handle).ThrowIfError("Failed to create thumbnail");
-
- if (handle.IsInvalid)
+ using (var handle = ValidateFile(mediaId))
{
- throw new RecordNotFoundException("Media does not exist.");
- }
+ string thumbnailPath = null;
+ MediaContentError ret = MediaContentError.None;
+ Task thumbTask = null;
- using (handle)
- {
- if (InteropHelper.GetValue<StorageType>(handle, Interop.MediaInfo.GetStorageType) == StorageType.ExternalUsb)
+ if (cancellationToken.CanBeCanceled)
{
- throw new UnsupportedContentException("The media is in external usb storage.");
- }
-
- var path = InteropHelper.GetString(handle, Interop.MediaInfo.GetFilePath);
+ cancellationToken.Register(() =>
+ {
+ if (tcs.Task.IsCompleted)
+ {
+ return;
+ }
- if (File.Exists(path) == false)
- {
- throw new FileNotFoundException($"The media file does not exist. Path={path}.", path);
+ tcs.TrySetCanceled();
+ });
}
- using (RegisterCancelThumbnail(cancellationToken, tcs, handle))
- using (var cbKeeper = ObjectKeeper.Get(GetCreateThumbnailCallback(tcs)))
+ thumbTask = Task.Factory.StartNew( () =>
{
- Interop.MediaInfo.CreateThumbnail(handle, cbKeeper.Target).ThrowIfError("Failed to create thumbnail");
+ ret = Interop.MediaInfo.GenerateThumbnail(handle);
- return await tcs.Task;
- }
+ if (ret != MediaContentError.None)
+ {
+ tcs.TrySetException(ret.AsException("Failed to create thumbnail"));
+ }
+ else
+ {
+ thumbnailPath = InteropHelper.GetString(handle, Interop.MediaInfo.GetThumbnailPath, true);
+ tcs.TrySetResult(thumbnailPath);
+ }
+ }, cancellationToken,
+ TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning,
+ TaskScheduler.Default);
+
+ return await tcs.Task;
}
}
+ #endregion
- private static Interop.MediaInfo.ThumbnailCompletedCallback GetCreateThumbnailCallback(
- TaskCompletionSource<string> tcs)
+ /// <summary>
+ /// Creates the thumbnail image for the given media.
+ /// If the thumbnail already exists for the given media, the existing path will be returned.
+ /// </summary>
+ /// <privilege>http://tizen.org/privilege/content.write</privilege>
+ /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
+ /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
+ /// <param name="mediaId">The ID of the media for which the thumbnail will be created.</param>
+ /// <returns>A created thumbnail path.</returns>
+ /// <exception cref="InvalidOperationException">
+ /// The <see cref="MediaDatabase"/> is disconnected.<br/>
+ /// -or-<br/>
+ /// An internal error occurred while executing.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
+ /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
+ /// <exception cref="RecordNotFoundException"><paramref name="mediaId"/> does not exist in the database.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="mediaId"/> is a zero-length string, contains only white space.
+ /// </exception>
+ /// <exception cref="FileNotFoundException">The file of the media does not exists; moved or deleted.</exception>
+ /// <exception cref="UnsupportedContentException">
+ /// The thumbnail is not available for the given media.<br/>
+ /// -or-<br/>
+ /// The media is in the external USB storage.
+ /// </exception>
+ /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <since_tizen> 10 </since_tizen>
+ public string CreateThumbnail(string mediaId)
{
- return (error, path, _) =>
+ ValidateDatabase();
+
+ ValidationUtil.ValidateNotNullOrEmpty(mediaId, nameof(mediaId));
+
+ using (var handle = ValidateFile(mediaId))
{
- if (error != MediaContentError.None)
- {
- tcs.TrySetException(error.AsException("Failed to create thumbnail"));
- }
- else
- {
- tcs.TrySetResult(path);
- }
- };
+ Interop.MediaInfo.GenerateThumbnail(handle).ThrowIfError("Failed to create thumbnail");
+
+ return InteropHelper.GetString(handle, Interop.MediaInfo.GetThumbnailPath, true);
+ }
}
- private static IDisposable RegisterCancelThumbnail(CancellationToken cancellationToken,
- TaskCompletionSource<string> tcs, Interop.MediaInfoHandle handle)
+ private Interop.MediaInfoHandle ValidateFile(string mediaId)
{
- if (cancellationToken.CanBeCanceled == false)
+ Interop.MediaInfo.GetMediaFromDB(mediaId, out var handle).ThrowIfError("Failed to create thumbnail");
+
+ if (handle.IsInvalid)
{
- return null;
+ throw new RecordNotFoundException("Media does not exist.");
}
- return cancellationToken.Register(() =>
+ try
{
- if (tcs.Task.IsCompleted)
+ var path = InteropHelper.GetString(handle, Interop.MediaInfo.GetFilePath);
+
+ if (String.IsNullOrEmpty(path) || File.Exists(path) == false)
{
- return;
+ throw new FileNotFoundException($"The media file does not exist. Path={path}.", path);
}
- Interop.MediaInfo.CancelThumbnail(handle).ThrowIfError("Failed to cancel");
- tcs.TrySetCanceled();
- });
+ foreach (var extendedInternal in StorageManager.Storages.Where(s => s.StorageType == StorageArea.ExtendedInternal))
+ {
+ if (path.Contains(extendedInternal.RootDirectory))
+ {
+ throw new UnsupportedContentException("The media is in external usb storage.");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ handle.Dispose();
+ throw ex;
+ }
+
+ return handle;
}
- #endregion
#region DetectFaceAsync
/// <summary>
/// <param name="mediaId">The media ID to create the thumbnail.</param>
/// <returns>A task that represents the asynchronous add operation. The task result contains the number of faces detected.</returns>
/// <exception cref="InvalidOperationException">
- /// The <see cref="MediaDatabase"/> is disconnected.\n
- /// -or-\n
+ /// The <see cref="MediaDatabase"/> is disconnected.<br/>
+ /// -or-<br/>
/// An internal error occurred while executing.
/// </exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="RecordNotFoundException"><paramref name="mediaId"/> does not exist in the database.</exception>
/// <exception cref="UnsupportedContentException">Face detection is not available for the given media.</exception>
/// <exception cref="NotSupportedException">The required feature is not supported.</exception>
/// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API11; Will be removed in API13.")]
public Task<int> DetectFaceAsync(string mediaId)
{
return DetectFaceAsync(mediaId, CancellationToken.None);
/// </summary>
/// <remarks>
/// Media in the external storage is not supported, with the exception of MMC.
+ /// Only JPEG, PNG, BMP images are supported.
/// </remarks>
/// <privilege>http://tizen.org/privilege/content.write</privilege>
/// <feature>http://tizen.org/feature/vision.face_recognition</feature>
/// <param name="cancellationToken">The token to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the number of faces detected.</returns>
/// <exception cref="InvalidOperationException">
- /// The <see cref="MediaDatabase"/> is disconnected.\n
- /// -or-\n
+ /// The <see cref="MediaDatabase"/> is disconnected.<br/>
+ /// -or-<br/>
/// An internal error occurred while executing.
/// </exception>
- /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed.</exception>
/// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
/// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
/// <exception cref="RecordNotFoundException"><paramref name="mediaId"/> does not exist in the database.</exception>
/// </exception>
/// <exception cref="FileNotFoundException">The file of the media does not exists; moved or deleted.</exception>
/// <exception cref="UnsupportedContentException">
- /// Face detection is not available for the given media.\n
- /// -or-\n
- /// The media is in the external USB storage (<see cref="MediaInfo.StorageType"/> is <see cref="StorageType.ExternalUsb"/>).
+ /// Face detection is not available for the given media.<br/>
+ /// -or-<br/>
+ /// The media is in the external USB storage.
/// </exception>
/// <exception cref="NotSupportedException">The required feature is not supported.</exception>
+ /// <since_tizen> 4 </since_tizen>
+ [Obsolete("Deprecated since API11; Will be removed in API13.")]
public Task<int> DetectFaceAsync(string mediaId, CancellationToken cancellationToken)
{
if (Features.IsSupported(Features.FaceRecognition) == false)
using (handle)
{
- if (InteropHelper.GetValue<StorageType>(handle, Interop.MediaInfo.GetStorageType) == StorageType.ExternalUsb)
+ if (InteropHelper.GetValue<MediaType>(handle, Interop.MediaInfo.GetMediaType) != MediaType.Image)
{
- throw new UnsupportedContentException("The media is in external usb storage.");
+ throw new UnsupportedContentException("Only image is supported.");
}
- if (InteropHelper.GetValue<MediaType>(handle, Interop.MediaInfo.GetMediaType) != MediaType.Image)
+ // Native P/Invoke function also check below case, but it returns invalid operation error.
+ // So we check it here to throw more proper exception.
+ string mimeType = InteropHelper.GetString(handle, Interop.MediaInfo.GetMimeType);
+ if (!mimeType.Equals("image/jpeg") && !mimeType.Equals("image/png") && !mimeType.Equals("image/bmp"))
{
- throw new UnsupportedContentException("Only image is supported.");
+ throw new UnsupportedContentException($"{mimeType} is not supported. Only JPEG, PNG, BMP is supported.");
}
var path = InteropHelper.GetString(handle, Interop.MediaInfo.GetFilePath);
using (RegisterCancelFaceDetection(cancellationToken, tcs, handle))
using (var cbKeeper = ObjectKeeper.Get(GetFaceDetectionCallback(tcs)))
{
- Interop.MediaInfo.StartFaceDetection(handle, cbKeeper.Target).ThrowIfError("Failed to detect faces");
+ var ret = Interop.MediaInfo.StartFaceDetection(handle, cbKeeper.Target);
+ if (ret == MediaContentError.InvalidParameter)
+ {
+ throw new UnsupportedContentException("The media is in external usb storage.");
+ }
+
+ ret.ThrowIfError("Failed to detect faces");
return await tcs.Task;
}