[MediaController] Add APIs to create playlist (#484)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / MediaController / MediaControlPlaylist.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using NativePlaylist = Interop.MediaControllerPlaylist;
20
21 namespace Tizen.Multimedia.Remoting
22 {
23     /// <summary>
24     /// Represents playlist for media control.
25     /// </summary>
26     /// <since_tizen> 5 </since_tizen>
27     public class MediaControlPlaylist : IDisposable
28     {
29         private IntPtr _handle;
30         private Dictionary<string, MediaControlMetadata> _metadata = new Dictionary<string, MediaControlMetadata>();
31
32         /// <summary>
33         /// Initializes a new instance of the <see cref="MediaControlPlaylist"/> class.
34         /// </summary>
35         /// <param name="name">The name of this playlist.</param>
36         /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
37         /// <since_tizen> 5 </since_tizen>
38         public MediaControlPlaylist(string name)
39         {
40             if (name == null)
41             {
42                 throw new ArgumentNullException(nameof(name));
43             }
44
45             NativePlaylist.CreatePlaylist(name, out IntPtr handle).ThrowIfError("Failed to create playlist");
46
47             Name = name;
48             _handle = handle;
49
50             MediaControlServer.SavePlaylist(handle);
51         }
52
53         /// <summary>
54         /// Initializes a new instance of the <see cref="MediaControlPlaylist"/> class.
55         /// </summary>
56         /// <param name="name">The name of this playlist.</param>
57         /// <param name="metadata">The metadata of this playlist.</param>
58         /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
59         /// <since_tizen> 5 </since_tizen>
60         public MediaControlPlaylist(string name, Dictionary<string, MediaControlMetadata> metadata)
61             : this(name)
62         {
63             AddMetadata(metadata);
64         }
65
66         /// <summary>
67         /// Initializes a new instance of the <see cref="MediaControlPlaylist"/> class with the playlist handle that created already.
68         /// </summary>
69         /// <param name="handle">The handle of playlist.</param>
70         internal MediaControlPlaylist(IntPtr handle)
71         {
72             if (handle == IntPtr.Zero)
73             {
74                 throw new ArgumentNullException(nameof(handle));
75             }
76
77             // handle will be destroyed in Native FW side.
78             Name = NativePlaylist.GetPlaylistName(handle);
79
80             UpdateMetadata(handle);
81         }
82
83         /// <summary>
84         /// Finalizes an instance of the <see cref="MediaControlPlaylist"/> class.
85         /// </summary>
86         /// <since_tizen> 5 </since_tizen>
87         ~MediaControlPlaylist()
88         {
89             Dispose(false);
90         }
91
92         internal IntPtr Handle
93         {
94             get
95             {
96                 if (_handle == IntPtr.Zero)
97                 {
98                     _handle = MediaControlServer.GetPlaylistHandle(Name);
99                 }
100                 return _handle;
101             }
102             set
103             {
104                 _handle = value;
105             }
106         }
107
108         /// <summary>
109         /// Gets or sets the name of playlist.
110         /// </summary>
111         /// <since_tizen> 5 </since_tizen>
112         public string Name { get; private set; }
113
114         /// <summary>
115         /// Gets the total number of media in this playlist.
116         /// </summary>
117         public int TotalCount
118         {
119             get
120             {
121                 return _metadata != null ? _metadata.Count : 0;
122             }
123         }
124
125         private void UpdateMetadata(IntPtr handle)
126         {
127             NativePlaylist.PlaylistItemCallback playlistItemCallback = (index, metadataHandle, _) =>
128             {
129                 _metadata.Add(index, new MediaControlMetadata(metadataHandle));
130                 return true;
131             };
132             NativePlaylist.ForeachPlaylistItem(handle, playlistItemCallback, IntPtr.Zero).
133                 ThrowIfError("Failed to retrieve playlist item.");
134         }
135
136         /// <summary>
137         /// Gets the playlist index and metadata pair.
138         /// </summary>
139         /// <returns>The dictionary set of index and <see cref="MediaControlMetadata"/> pair.</returns>
140         public Dictionary<string, MediaControlMetadata> GetMetadata()
141         {
142             if (_metadata == null)
143             {
144                 UpdateMetadata(Handle);
145             }
146
147             return _metadata;
148         }
149
150         /// <summary>
151         /// Gets the metadata by index.
152         /// </summary>
153         /// <param name="index">The index of media in the playlist.</param>
154         /// <returns>A <see cref="MediaControlMetadata"/> instance.</returns>
155         public MediaControlMetadata GetMetadata(string index)
156         {
157             if (_metadata == null)
158             {
159                 UpdateMetadata(Handle);
160             }
161
162             if (_metadata.TryGetValue(index, out MediaControlMetadata metadata))
163             {
164                 return metadata;
165             }
166
167             return null;
168         }
169
170         /// <summary>
171         /// Sets the metadata to the playlist.
172         /// </summary>
173         /// <param name="metadata">The metadata of media.</param>
174         /// <since_tizen> 5 </since_tizen>
175         public void AddMetadata(Dictionary<string, MediaControlMetadata> metadata)
176         {
177             foreach (var data in metadata)
178             {
179                 AddMetadata(data.Key, data.Value);
180             }
181
182             MediaControlServer.SavePlaylist(Handle);
183         }
184
185         /// <summary>
186         /// Sets the metadata to the playlist.
187         /// </summary>
188         /// <param name="index">The index of media in the playlist.</param>
189         /// <param name="metadata">The metadata of media.</param>
190         /// <since_tizen> 5 </since_tizen>
191         public void AddMetadata(string index, MediaControlMetadata metadata)
192         {
193             AddItemToPlaylist(index, metadata);
194             _metadata.Add(index, metadata);
195
196             MediaControlServer.SavePlaylist(Handle);
197         }
198
199         private void AddItemToPlaylist(string index, MediaControlMetadata metadata)
200         {
201             void AddMetadataToNative(string idx, MediaControllerNativeAttribute attribute, string value)
202             {
203                 // This API doesn't save playlist to the storage. So we need to call MediaControlServer.SavePlaylist()
204                 // after all items are updated.
205                 NativePlaylist.UpdatePlaylist(Handle, idx, attribute, value)
206                     .ThrowIfError("Failed to update playlist");
207             }
208
209             AddMetadataToNative(index, MediaControllerNativeAttribute.Album, metadata.Album);
210             AddMetadataToNative(index, MediaControllerNativeAttribute.Artist, metadata.Artist);
211             AddMetadataToNative(index, MediaControllerNativeAttribute.Author, metadata.Author);
212             AddMetadataToNative(index, MediaControllerNativeAttribute.Copyright, metadata.Copyright);
213             AddMetadataToNative(index, MediaControllerNativeAttribute.Date, metadata.Date);
214             AddMetadataToNative(index, MediaControllerNativeAttribute.Description, metadata.Description);
215             AddMetadataToNative(index, MediaControllerNativeAttribute.Duration, metadata.Duration);
216             AddMetadataToNative(index, MediaControllerNativeAttribute.Genre, metadata.Genre);
217             AddMetadataToNative(index, MediaControllerNativeAttribute.Picture, metadata.AlbumArtPath);
218             AddMetadataToNative(index, MediaControllerNativeAttribute.Title, metadata.Title);
219             AddMetadataToNative(index, MediaControllerNativeAttribute.TrackNumber, metadata.TrackNumber);
220         }
221
222         /// <summary>
223         /// Update the playlist by lastest info.
224         /// </summary>
225         /// <since_tizen> 5 </since_tizen>
226         public void Update()
227         {
228             // Update the name of playlist.
229             Name = NativePlaylist.GetPlaylistName(Handle);
230
231             // Update metadata.
232             UpdateMetadata(Handle);
233         }
234
235         internal void Destroy()
236         {
237             NativePlaylist.DestroyPlaylist(Handle).ThrowIfError("Failed to delete playlist");
238         }
239
240         #region Dispose support
241         private bool _disposed;
242
243         /// <summary>
244         /// Releases the unmanaged resources used by the MediaControlPlaylist.
245         /// </summary>
246         /// <since_tizen> 5 </since_tizen>
247         public void Dispose()
248         {
249             Dispose(true);
250             GC.SuppressFinalize(this);
251         }
252
253         /// <summary>
254         /// Releases the resources used by the Recorder.
255         /// </summary>
256         /// <param name="disposing">
257         /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
258         /// </param>
259         /// <since_tizen> 3 </since_tizen>
260         protected virtual void Dispose(bool disposing)
261         {
262             if (!_disposed)
263             {
264                 if (_handle != IntPtr.Zero)
265                 {
266                     Destroy();
267                     _handle = IntPtr.Zero;
268                 }
269
270                 _disposed = true;
271             }
272         }
273         #endregion Dispose support
274     }
275 }