/*
* 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.Collections.Generic;
using System.Threading.Tasks;
///
/// The Media Content API provides functions, enumerations used in the entire Content Service.
///
///
/// The Media Content API provides functions and enumerations used in the entire Content Service.
/// The information about media items i.e.image, audio and video, are managed in the content database
/// and operations that involve database requires an active connection with the media content service.
/// During media scanning, Media Service extract media information automatically. media information
/// include basic file info like path, size, modified time etc and some metadata like ID3tag, EXIF,
/// thumbnail, etc. (thumbnail extracted only in Internal and SD card storage.
/// Media content services do not manage hidden files.
/// The API provides functions for connecting (media_content_connect()) and disconnecting(media_content_disconnect())
/// from the media content service.
///
namespace Tizen.Content.MediaContent
{
///
/// ContentDatabase class is the interface class for managing the ContentCollection and MediaInformation from/to the database.
/// This class allows usre to access/create/update db operations for media content.
///
public class ContentDatabase
{
private static IntPtr _updateHandle = IntPtr.Zero;
///
/// Connect to the media database to search, insert, remove or modify media information.
///
/// 4
///
/// For information security, disconnect() after use media database.
///
public static void Connect()
{
MediaContentValidator.ThrowIfError(Interop.Content.Connect(), "Connect failed");
}
///
/// Disconnect from the media database.
///
/// 4
public static void Disconnect()
{
MediaContentValidator.ThrowIfError(Interop.Content.Disconnect(), "Disconnect failed");
}
private static readonly Interop.Content.MediaContentDBUpdatedCallback s_contentUpdatedCallback = (
MediaContentError error,
int pid,
MediaContentUpdateItemType updateItem,
MediaContentDBUpdateType updateType,
MediaContentType mediaType,
string uuid,
string filePath,
string mimeType,
IntPtr userData) =>
{
_contentUpdated?.Invoke(
null, new ContentUpdatedEventArgs(error, pid, updateItem, updateType, mediaType, uuid, filePath, mimeType));
};
private static event EventHandler _contentUpdated;
///
/// ContentUpdated event is triggered when the media DB changes.
///
/// 3
///
/// A ContentUpdatedEventArgs object that contains information about the update operation.
public static event EventHandler ContentUpdated
{
add
{
if (_contentUpdated == null)
{
MediaContentValidator.ThrowIfError(
Interop.Content.AddDbUpdatedCb(s_contentUpdatedCallback, IntPtr.Zero, out _updateHandle), "Failed to set callback");
}
_contentUpdated += value;
}
remove
{
_contentUpdated -= value;
if (_contentUpdated == null)
{
MediaContentValidator.ThrowIfError(
Interop.Content.RemoveDbUpdatedCb(_updateHandle), "Failed to unset callback");
}
}
}
///
/// Gets the count of ContentCollections for the ContentCollectionType and passed filter from the media database.
///
/// 3
/// The media filter
/// The count of contents present in the media database for a ContentSourceType
public int GetCount(ContentFilter filter) where T : class
{
int count = 0;
IntPtr handle = (filter != null) ? filter.Handle : IntPtr.Zero;
MediaGroupType groupType = MediaGroupType.DisplayName;
if (handle != IntPtr.Zero)
{
groupType = filter.GroupType;
}
if (typeof(T) == typeof(MediaInformation))
{
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetMediaCount(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(MediaBookmark))
{
MediaContentValidator.ThrowIfError(
Interop.MediaBookmark.GetBookmarkCountFromDb(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(Album))
{
MediaContentValidator.ThrowIfError(
Interop.Group.MediaAlbumGetAlbumCountFromDb(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(MediaFolder))
{
MediaContentValidator.ThrowIfError(
Interop.Folder.GetFolderCountFromDb(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(Storage))
{
MediaContentValidator.ThrowIfError(
Interop.Storage.GetStorageCountFromDb(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(Tag))
{
MediaContentValidator.ThrowIfError(
Interop.Tag.GetTagCountFromDb(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(PlayList))
{
MediaContentValidator.ThrowIfError(
Interop.Playlist.GetPlaylistCountFromDb(handle, out count), "Failed to get count");
}
else if (typeof(T) == typeof(Group))
{
MediaContentValidator.ThrowIfError(
Interop.Group.GetGroupCountFromDb(handle, groupType, out count), "Failed to get count");
}
else
{
throw new ArgumentException("Wrong type");
}
return count;
}
///
/// Gets the MediaInformation object for the passed media Id.
///
/// 3
/// The media id to fetch the respective MediaInformation instance
/// MediaInformation instance for the associated id.It throws Exception for invalid Id.
public MediaInformation Select(string id)
{
Interop.MediaInformation.SafeMediaInformationHandle mediaHandle;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetMediaFromDB(id, out mediaHandle), "Failed to get information");
MediaContentType type;
MediaInformation res;
Interop.MediaInformation.GetMediaType(mediaHandle, out type);
if (type == MediaContentType.Image)
{
Interop.ImageInformation.SafeImageInformationHandle imageInfo;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetImage(mediaHandle.DangerousGetHandle(), out imageInfo), "Failed to get image information");
res = new ImageInformation(imageInfo, mediaHandle);
}
else if ((type == MediaContentType.Music) || (type == MediaContentType.Sound))
{
Interop.AudioInformation.SafeAudioInformationHandle audioInfo;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetAudio(mediaHandle.DangerousGetHandle(), out audioInfo), "Failed to get audio information");
res = new AudioInformation(audioInfo, mediaHandle);
}
else if (type == MediaContentType.Video)
{
Interop.VideoInformation.SafeVideoInformationHandle videoInfo;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetVideo(mediaHandle.DangerousGetHandle(), out videoInfo), "Failed to get video information");
res = new VideoInformation(videoInfo, mediaHandle);
}
else
{
res = new MediaInformation(mediaHandle);
}
return res;
}
///
/// Gets the ContentCollection object for the passed media Id.
/// Applicable for MediaFolder and Storage types.
///
/// 3
/// The ContentCollection id to fetch the respective MediaInformation instance
/// ContentCollection instance for the associated id.It throws Exception for invalid Id.
public T Select(string id) where T : ContentCollection
{
ContentCollection result = null;
IntPtr handle = IntPtr.Zero;
if (typeof(T) == typeof(MediaFolder))
{
MediaContentValidator.ThrowIfError(
Interop.Folder.GetFolderFromDb(id, out handle), "Failed to get information");
if (handle != IntPtr.Zero)
{
result = new MediaFolder(handle);
return (T)result;
}
}
else if (typeof(T) == typeof(Storage))
{
MediaContentValidator.ThrowIfError(
Interop.Storage.GetStorageInfoFromDb(id, out handle), "Failed to get information");
if (handle != IntPtr.Zero)
{
result = new Storage(handle);
return (T)result;
}
}
return null;
}
///
/// Gets the ContentCollection object for the passed media Id.
/// Applicable for PlayList, Album and Tag types.
///
/// 3
/// The ContentCollection id to fetch the respective MediaInformation instance
/// ContentCollection instance for the associated id.It throws Exception for invalid Id.
public T Select(int id) where T : ContentCollection
{
ContentCollection result = null;
IntPtr handle = IntPtr.Zero;
if (typeof(T) == typeof(PlayList))
{
MediaContentValidator.ThrowIfError(
Interop.Playlist.GetPlaylistFromDb(id, out handle), "Failed to get information");
if (handle != IntPtr.Zero)
{
result = new PlayList(handle);
return (T)result;
}
}
else if (typeof(T) == typeof(Album))
{
MediaContentValidator.ThrowIfError(
Interop.Group.MediaAlbumGetAlbumFromDb(id, out handle), "Failed to get information");
if (handle != IntPtr.Zero)
{
result = new Album(handle);
return (T)result;
}
}
else if (typeof(T) == typeof(Tag))
{
MediaContentValidator.ThrowIfError(
Interop.Tag.GetTagFromDb(id, out handle), "Failed to get information");
if (handle != IntPtr.Zero)
{
result = new Tag(handle);
return (T)result;
}
}
return null;
}
private static IEnumerable ForEachFolder(ContentFilter filter)
{
List result = new List();
Interop.Folder.MediaFolderCallback callback = (IntPtr handle, IntPtr data) =>
{
IntPtr newHandle = IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Folder.Clone(out newHandle, handle), "Failed to clone");
result.Add(new MediaFolder(newHandle));
return true;
};
IntPtr filterHandle = filter != null ? filter.Handle : IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Folder.ForeachFolderFromDb(filterHandle, callback, IntPtr.Zero), "Failed to get information");
return result;
}
private static IEnumerable ForEachAlbum(ContentFilter filter)
{
List result = new List();
Interop.Group.MediaAlbumCallback callback = (IntPtr handle, IntPtr data) =>
{
IntPtr newHandle = IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Group.MediaAlbumClone(out newHandle, handle), "Failed to clone");
result.Add(new Album(newHandle));
return true;
};
IntPtr filterHandle = (filter != null) ? filter.Handle : IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Group.MediaAlbumForeachAlbumFromDb(filterHandle, callback, IntPtr.Zero), "Failed to get information");
return result;
}
private static IEnumerable ForEachGroup(ContentFilter filter)
{
IntPtr handle = (filter != null) ? filter.Handle : IntPtr.Zero;
MediaGroupType groupType;
if (filter == null)
{
groupType = MediaGroupType.DisplayName;
}
else
{
groupType = filter.GroupType;
}
List result = new List();
Interop.Group.MediaGroupCallback callback = (string groupName, IntPtr data) =>
{
result.Add(new Group(groupName, groupType));
return true;
};
MediaContentValidator.ThrowIfError(
Interop.Group.ForeachGroupFromDb(handle, groupType, callback, IntPtr.Zero), "Failed to get information");
return result;
}
private static IEnumerable ForEachStorage(ContentFilter filter)
{
IntPtr handle = (filter != null) ? filter.Handle : IntPtr.Zero;
List result = new List();
Interop.Storage.MediaStorageCallback callback = (IntPtr storageHandle, IntPtr data) =>
{
IntPtr newHandle = IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Storage.Clone(out newHandle, storageHandle), "Failed to clone");
result.Add(new Storage(newHandle));
return true;
};
MediaContentValidator.ThrowIfError(
Interop.Storage.ForeachStorageFromDb(handle, callback, IntPtr.Zero), "Failed to get information");
return result;
}
private static IEnumerable ForEachTag(ContentFilter filter)
{
IntPtr handle = (filter != null) ? filter.Handle : IntPtr.Zero;
List result = new List();
Interop.Tag.MediaTagCallback callback = (IntPtr tagHandle, IntPtr data) =>
{
IntPtr newHandle = IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Tag.Clone(out newHandle, tagHandle), "Failed to clone");
result.Add(new Tag(newHandle));
return true;
};
MediaContentValidator.ThrowIfError(
Interop.Tag.ForeachTagFromDb(handle, callback, IntPtr.Zero), "Failed to get information");
return result;
}
private static IEnumerable ForEachPlayList(ContentFilter filter)
{
IntPtr handle = (filter != null) ? filter.Handle : IntPtr.Zero;
List result = new List();
Interop.Playlist.MediaPlaylistCallback callback = (IntPtr playListHandle, IntPtr data) =>
{
IntPtr newHandle = IntPtr.Zero;
MediaContentValidator.ThrowIfError(
Interop.Playlist.Clone(out newHandle, playListHandle), "Failed to clone");
result.Add(new PlayList(newHandle));
return true;
};
MediaContentValidator.ThrowIfError(
Interop.Playlist.ForeachPlaylistFromDb(handle, callback, IntPtr.Zero), "Failed to get information");
return result;
}
///
/// Returns the ContentCollections with optional filter from the media database.
///
/// 3
///
/// This function gets all ContentCollections matching the given filter. If NULL is passed to the filter, no filtering is applied.
///
/// Filter for content items
///
/// Task with the list of the ContentCollection
///
public IEnumerable SelectAll(ContentFilter filter)
{
if (typeof(T) == typeof(MediaInformation))
{
IEnumerable mediaList = GetMediaInformations(filter);
return (IEnumerable)mediaList;
}
else if (typeof(T) == typeof(Album))
{
IEnumerable collectionList = ForEachAlbum(filter);
return (IEnumerable)collectionList;
}
else if (typeof(T) == typeof(MediaFolder))
{
IEnumerable collectionList = ForEachFolder(filter);
return (IEnumerable)collectionList;
}
else if (typeof(T) == typeof(Group))
{
IEnumerable collectionList = ForEachGroup(filter);
return (IEnumerable)collectionList;
}
else if (typeof(T) == typeof(Storage))
{
IEnumerable collectionList = ForEachStorage(filter);
return (IEnumerable)collectionList;
}
else if (typeof(T) == typeof(Tag))
{
IEnumerable collectionList = ForEachTag(filter);
return (IEnumerable)collectionList;
}
else if (typeof(T) == typeof(PlayList))
{
IEnumerable collectionList = ForEachPlayList(filter);
return (IEnumerable)collectionList;
}
return null;
}
///
/// Returns media from the media database.
/// This function gets all media meeting the given filter
///
/// 3
/// The media filter
/// List of media
private IEnumerable GetMediaInformations(ContentFilter filter)
{
IntPtr handle = (filter != null) ? filter.Handle : IntPtr.Zero;
List mediaInformationList = new List();
Interop.MediaInformation.MediaInformationCallback callback = (IntPtr mediaHandle, IntPtr userData) =>
{
Interop.MediaInformation.SafeMediaInformationHandle newHandle;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.Clone(out newHandle, mediaHandle), "Failed to clone");
MediaContentType type;
Interop.MediaInformation.GetMediaType(newHandle, out type);
if (type == MediaContentType.Image)
{
Interop.ImageInformation.SafeImageInformationHandle imageInfo;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetImage(mediaHandle, out imageInfo), "Failed to get image information");
mediaInformationList.Add(new ImageInformation(imageInfo, newHandle));
}
else if ((type == MediaContentType.Music) || (type == MediaContentType.Sound))
{
Interop.AudioInformation.SafeAudioInformationHandle audioInfo;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetAudio(mediaHandle, out audioInfo), "Failed to get audio information");
mediaInformationList.Add(new AudioInformation(audioInfo, newHandle));
}
else if (type == MediaContentType.Video)
{
Interop.VideoInformation.SafeVideoInformationHandle videoInfo;
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetVideo(mediaHandle, out videoInfo), "Failed to get video information");
mediaInformationList.Add(new VideoInformation(videoInfo, newHandle));
}
else if (type == MediaContentType.Others)
{
mediaInformationList.Add(new MediaInformation(newHandle));
}
return true;
};
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.GetAllMedia(handle, callback, IntPtr.Zero), "Failed to get media information");
return mediaInformationList;
}
///
/// Deletes a MediaInformation from the media database.
///
/// 3
/// The MediaInformation to be deleted
public void Delete(MediaInformation mediaInfo)
{
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.Delete(mediaInfo.MediaId), "Failed to remove information");
}
///
/// Deletes a content collection from the media database.
/// Applicable for Tag and PlayList only.
/// For other types ArgumentException is thrown.
///
/// 3
/// The ContentCollection instance to be deleted
public void Delete(ContentCollection contentcollection)
{
Type type = contentcollection.GetType();
if (type == typeof(Tag))
{
MediaContentValidator.ThrowIfError(
Interop.Tag.DeleteFromDb(((Tag)contentcollection).Id), "Failed to remove information");
}
else if (type == typeof(PlayList))
{
MediaContentValidator.ThrowIfError(
Interop.Playlist.DeleteFromDb(((PlayList)contentcollection).Id), "Failed to remove information");
}
else
{
throw new ArgumentException("The type of content collection is wrong");
}
}
internal void Delete(MediaBookmark bookmark)
{
MediaContentValidator.ThrowIfError(
Interop.MediaBookmark.DeleteFromDb(bookmark.Id), "Failed to remove information");
}
internal void Delete(MediaFace face)
{
MediaContentValidator.ThrowIfError(
Interop.Face.DeleteFromDb(face.Id), "Failed to remove face information");
}
///
/// Updates a content collection in the media database
/// Applicable for Tag, PlayList and MediagFolder types only.
///
/// 3
/// The content collection to be updated
public void Update(ContentCollection contentCollection)
{
Type type = contentCollection.GetType();
if (type == typeof(Tag))
{
MediaContentValidator.ThrowIfError(
Interop.Tag.UpdateToDb(((Tag)contentCollection).Handle), "Failed to update DB");
}
else if (type == typeof(PlayList))
{
MediaContentValidator.ThrowIfError(
Interop.Playlist.UpdateToDb(((PlayList)contentCollection).Handle), "Failed to update DB");
}
else if (type == typeof(MediaFolder))
{
MediaContentValidator.ThrowIfError(
Interop.Folder.UpdateToDb(((MediaFolder)contentCollection).Handle), "Failed to update DB");
}
else
{
throw new ArgumentException("The type of content collection is wrong");
}
}
///
/// Updates a media information instance in the media database
///
/// 3
/// The MediaInformation object to be updated
public void Update(MediaInformation mediaInfo)
{
Type type = mediaInfo.GetType();
if (type == typeof(ImageInformation))
{
MediaContentValidator.ThrowIfError(
Interop.ImageInformation.UpdateToDB(((ImageInformation)mediaInfo).ImageHandle), "Failed to update DB");
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.UpdateToDB(mediaInfo.MediaHandle), "Failed to update DB");
}
else if (type == typeof(AudioInformation))
{
MediaContentValidator.ThrowIfError(
Interop.AudioInformation.UpdateToDB(((AudioInformation)mediaInfo).AudioHandle), "Failed to update DB");
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.UpdateToDB(mediaInfo.MediaHandle), "Failed to update DB");
}
else if (type == typeof(VideoInformation))
{
MediaContentValidator.ThrowIfError(
Interop.VideoInformation.UpdateToDB(((VideoInformation)mediaInfo).VideoHandle), "Failed to update DB");
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.UpdateToDB(mediaInfo.MediaHandle), "Failed to update DB");
}
else if (type == typeof(MediaInformation))
{
MediaContentValidator.ThrowIfError(
Interop.MediaInformation.UpdateToDB(mediaInfo.MediaHandle), "Failed to update DB");
}
else
{
throw new ArgumentException("Invalid information type");
}
}
internal void Update(MediaFace face)
{
MediaContentValidator.ThrowIfError(Interop.Face.UpdateToDb(face.Handle), "Failed to update DB");
}
///
/// Inserts a content collection to the media database.
/// Applicable for Tag and PlayList types only.
///
/// 3
/// The content collection to be inserted
public void Insert(ContentCollection contentCollection)
{
Type type = contentCollection.GetType();
IntPtr handle = IntPtr.Zero;
if (type == typeof(Tag))
{
MediaContentValidator.ThrowIfError(
Interop.Tag.InsertToDb(((Tag)contentCollection).Name, out handle), "Failed to insert collection");
((Tag)contentCollection).Handle = handle;
}
else if (type == typeof(PlayList))
{
MediaContentValidator.ThrowIfError(
Interop.Playlist.InsertToDb(((PlayList)contentCollection).Name, out handle), "Failed to insert collection");
((PlayList)contentCollection).Handle = handle;
}
else
{
throw new ArgumentException("collection type is wrong");
}
}
internal void Insert(string mediaId, uint offset, string thumbnailPath)
{
MediaContentValidator.ThrowIfError(
Interop.MediaBookmark.InsertToDb(mediaId, offset, thumbnailPath), "Failed to insert information");
}
internal void Insert(MediaFace face)
{
MediaContentValidator.ThrowIfError(
Interop.Face.InsertToDb(((MediaFace)face).Handle), "Failed to insert information");
}
}
}