Setting since_tizen 3/4 on Tizen.NET API
[platform/core/csapi/tizenfx.git] / src / Tizen.Content.MediaContent / Tizen.Content.MediaContent / PlaylistCommand.cs
1 /*
2  * Copyright (c) 2016 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 System.IO;
20 using System.Linq;
21
22 namespace Tizen.Content.MediaContent
23 {
24     /// <summary>
25     /// Provides the commands to manage playlists in the database.
26     /// </summary>
27     /// <seealso cref="Playlist"/>
28     /// <since_tizen> 4 </since_tizen>
29     public class PlaylistCommand : MediaCommand
30     {
31         /// <summary>
32         /// Initializes a new instance of the <see cref="PlaylistCommand"/> class with the specified <see cref="MediaDatabase"/>.
33         /// </summary>
34         /// <param name="database">A <see cref="MediaDatabase"/> that the commands run on.</param>
35         /// <exception cref="ArgumentNullException"><paramref name="database"/> is null.</exception>
36         /// <exception cref="ObjectDisposedException"><paramref name="database"/> has already been disposed of.</exception>
37         /// <since_tizen> 4 </since_tizen>
38         public PlaylistCommand(MediaDatabase database) : base(database)
39         {
40         }
41
42         /// <summary>
43         /// Retrieves the number of playlists.
44         /// </summary>
45         /// <returns>The number of playlists.</returns>
46         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
47         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
48         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
49         /// <since_tizen> 4 </since_tizen>
50         public int Count()
51         {
52             return Count(null);
53         }
54
55         /// <summary>
56         /// Retrieves the number of playlists with the <see cref="CountArguments"/>.
57         /// </summary>
58         /// <param name="arguments">The criteria to use to filter. This value can be null.</param>
59         /// <returns>The number of playlists.</returns>
60         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
61         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
62         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
63         /// <since_tizen> 4 </since_tizen>
64         public int Count(CountArguments arguments)
65         {
66             ValidateDatabase();
67
68             return CommandHelper.Count(Interop.Playlist.GetPlaylistCount, arguments);
69         }
70
71         /// <summary>
72         /// Retrieves the play order of the member.
73         /// </summary>
74         /// <param name="playlistId">The playlist ID.</param>
75         /// <param name="memberId">The member ID of the playlist.</param>
76         /// <returns>The order of the member in the playlist.</returns>
77         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
78         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
79         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
80         /// <exception cref="ArgumentOutOfRangeException">
81         ///     <paramref name="playlistId"/> is less than or equal to zero.<br/>
82         ///     -or-<br/>
83         ///     <paramref name="memberId"/> is less than or equal to zero.
84         /// </exception>
85         /// <since_tizen> 4 </since_tizen>
86         public int GetPlayOrder(int playlistId, int memberId)
87         {
88             ValidateDatabase();
89
90             if (playlistId <= 0)
91             {
92                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
93                     "Playlist id can't be less than or equal to zero.");
94             }
95
96             if (memberId <= 0)
97             {
98                 throw new ArgumentOutOfRangeException(nameof(memberId), memberId,
99                     "Member id can't be less than or equal to zero.");
100             }
101
102             Interop.Playlist.GetPlayOrder(playlistId, memberId, out var order).ThrowIfError("Failed to query");
103
104             return order;
105         }
106
107         /// <summary>
108         /// Deletes a playlist from the database.
109         /// </summary>
110         /// <privilege>http://tizen.org/privilege/content.write</privilege>
111         /// <param name="playlistId">The playlist ID to delete.</param>
112         /// <returns>true if the matched record was found and deleted, otherwise false.</returns>
113         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
114         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
115         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
116         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
117         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
118         /// <since_tizen> 4 </since_tizen>
119         public bool Delete(int playlistId)
120         {
121             ValidateDatabase();
122
123             if (playlistId <= 0)
124             {
125                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
126                     "Playlist id can't be less than or equal to zero.");
127             }
128
129             if (Select(playlistId) == null)
130             {
131                 return false;
132             }
133
134             CommandHelper.Delete(Interop.Playlist.Delete, playlistId);
135             return true;
136         }
137
138         /// <summary>
139         /// Inserts the playlist into the database from the specified M3U file.
140         /// </summary>
141         /// <remarks>
142         ///     If you want to access an internal storage, you should add privilege http://tizen.org/privilege/mediastorage.<br/>
143         ///     If you want to access an external storage, you should add privilege http://tizen.org/privilege/externalstorage.
144         /// </remarks>
145         /// <privilege>http://tizen.org/privilege/content.write</privilege>
146         /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
147         /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
148         /// <param name="name">The name of the playlist.</param>
149         /// <param name="path">The path to a M3U file to import.</param>
150         /// <returns>The <see cref="Playlist"/> instance that contains the record information inserted.</returns>
151         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
152         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
153         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
154         /// <exception cref="ArgumentNullException">
155         ///     <paramref name="name"/> is null.<br/>
156         ///     -or-<br/>
157         ///     <paramref name="path"/> is null.
158         /// </exception>
159         /// <exception cref="ArgumentException">
160         ///     <paramref name="name"/> is a zero-length string.<br/>
161         ///     -or-<br/>
162         ///     <paramref name="path"/> is a zero-length string, contains only white space.
163         /// </exception>
164         /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exists.</exception>
165         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
166         /// <since_tizen> 4 </since_tizen>
167         public Playlist InsertFromFile(string name, string path)
168         {
169             ValidateDatabase();
170
171             if (name == null)
172             {
173                 throw new ArgumentNullException(nameof(name));
174             }
175
176             if (name.Length == 0)
177             {
178                 throw new ArgumentException("Playlist name can't be an empty string.");
179             }
180
181             ValidationUtil.ValidateNotNullOrEmpty(path, nameof(path));
182
183             if (File.Exists(path) == false)
184             {
185                 throw new FileNotFoundException("The specified path does not exists.", path);
186             }
187
188             IntPtr handle = IntPtr.Zero;
189             Interop.Playlist.ImportFromFile(path, name, out handle).ThrowIfError("Failed to insert");
190
191             try
192             {
193                 return new Playlist(handle);
194             }
195             finally
196             {
197                 if (handle != IntPtr.Zero)
198                 {
199                     Interop.Playlist.Destroy(handle);
200                 }
201             }
202         }
203         /// <summary>
204         /// Exports the playlist to a M3U file.
205         /// </summary>
206         /// <remarks>
207         ///     If the file already exists in the file system, then it will be overwritten.<br/>
208         ///     <br/>
209         ///     If you want to access an internal storage, you should add privilege http://tizen.org/privilege/mediastorage.<br/>
210         ///     If you want to access an external storage, you should add privilege http://tizen.org/privilege/externalstorage.
211         /// </remarks>
212         /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
213         /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
214         /// <param name="playlistId">The playlist ID to export.</param>
215         /// <param name="path">The path to a M3U file.</param>
216         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
217         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
218         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
219         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
220         /// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length string, contains only white space.</exception>
221         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
222         /// <exception cref="RecordNotFoundException">No matching playlist exists.</exception>
223         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
224         /// <since_tizen> 4 </since_tizen>
225         public void ExportToFile(int playlistId, string path)
226         {
227             ValidateDatabase();
228
229             ValidationUtil.ValidateNotNullOrEmpty(path, nameof(path));
230
231             if (playlistId <= 0)
232             {
233                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
234                     "Playlist id can't be less than or equal to zero.");
235             }
236
237             IntPtr handle = IntPtr.Zero;
238             try
239             {
240                 Interop.Playlist.GetPlaylistFromDb(playlistId, out handle).ThrowIfError("Failed to query");
241
242                 if (handle == IntPtr.Zero)
243                 {
244                     throw new RecordNotFoundException("No matching playlist exists.");
245                 }
246
247                 Interop.Playlist.ExportToFile(handle, path).ThrowIfError("Failed to export");
248             }
249             finally
250             {
251                 if (handle != IntPtr.Zero)
252                 {
253                     Interop.Playlist.Destroy(handle);
254                 }
255             }
256         }
257
258         /// <summary>
259         /// Inserts the playlist into the database with the specified name.
260         /// </summary>
261         /// <privilege>http://tizen.org/privilege/content.write</privilege>
262         /// <param name="name">The name of the playlist.</param>
263         /// <returns>The <see cref="Playlist"/> instance that contains the record information inserted.</returns>
264         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
265         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
266         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
267         /// <exception cref="ArgumentNullException"><paramref name="name"/> is null.</exception>
268         /// <exception cref="ArgumentException"><paramref name="name"/> is a zero-length string.</exception>
269         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
270         /// <since_tizen> 4 </since_tizen>
271         public Playlist Insert(string name)
272         {
273             return Insert(name, null);
274         }
275
276         /// <summary>
277         /// Inserts the playlist into the database with the specified name and the thumbnail path.
278         /// </summary>
279         /// <privilege>http://tizen.org/privilege/content.write</privilege>
280         /// <param name="name">The name of the playlist.</param>
281         /// <param name="thumbnailPath">The path of the thumbnail for the playlist. This value can be null.</param>
282         /// <returns>The <see cref="Playlist"/> instance that contains the record information inserted.</returns>
283         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
284         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
285         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
286         /// <exception cref="ArgumentNullException"><paramref name="name"/> is null.</exception>
287         /// <exception cref="ArgumentException"><paramref name="name"/> is a zero-length string.</exception>
288         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
289         /// <since_tizen> 4 </since_tizen>
290         public Playlist Insert(string name, string thumbnailPath)
291         {
292             ValidateDatabase();
293
294             if (name == null)
295             {
296                 throw new ArgumentNullException(nameof(name));
297             }
298
299             if (name.Length == 0)
300             {
301                 throw new ArgumentException("Playlist name can't be an empty string.");
302             }
303
304             IntPtr handle = IntPtr.Zero;
305             Interop.Playlist.Create(out handle).ThrowIfError("Failed to insert");
306
307             try
308             {
309                 Interop.Playlist.SetName(handle, name).ThrowIfError("Failed to insert");
310
311                 if (thumbnailPath != null)
312                 {
313                     Interop.Playlist.SetThumbnailPath(handle, thumbnailPath).ThrowIfError("Failed to insert");
314                 }
315
316                 Interop.Playlist.Insert(handle).ThrowIfError("Failed to insert");
317                 return new Playlist(handle);
318             }
319             finally
320             {
321                 if (handle != IntPtr.Zero)
322                 {
323                     Interop.Playlist.Destroy(handle);
324                 }
325             }
326         }
327
328         /// <summary>
329         /// Retrieves the playlists.
330         /// </summary>
331         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
332         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
333         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
334         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
335         /// <since_tizen> 4 </since_tizen>
336         public MediaDataReader<Playlist> Select()
337         {
338             return Select(null);
339         }
340
341         /// <summary>
342         /// Retrieves the playlists with the <see cref="SelectArguments"/>.
343         /// </summary>
344         /// <param name="filter">The criteria to use to filter. This value can be null.</param>
345         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
346         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
347         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
348         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
349         /// <since_tizen> 4 </since_tizen>
350         public MediaDataReader<Playlist> Select(SelectArguments filter)
351         {
352             ValidateDatabase();
353
354             return CommandHelper.Select(filter, Interop.Playlist.ForeachPlaylistFromDb,
355                 Playlist.FromHandle);
356         }
357
358         /// <summary>
359         /// Retrieves the playlist with the specified playlist ID.
360         /// </summary>
361         /// <param name="playlistId">The playlist ID to select.</param>
362         /// <returns>The <see cref="Playlist"/> instance if the matched record was found in the database, otherwise null.</returns>
363         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
364         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
365         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
366         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
367         /// <since_tizen> 4 </since_tizen>
368         public Playlist Select(int playlistId)
369         {
370             ValidateDatabase();
371
372             if (playlistId <= 0)
373             {
374                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
375                     "Playlist id can't be less than or equal to zero.");
376             }
377
378             IntPtr handle = IntPtr.Zero;
379
380             try
381             {
382                 Interop.Playlist.GetPlaylistFromDb(playlistId, out handle).ThrowIfError("Failed to query");
383
384                 if (handle == IntPtr.Zero)
385                 {
386                     return null;
387                 }
388
389                 return new Playlist(handle);
390             }
391             finally
392             {
393                 if (handle != IntPtr.Zero)
394                 {
395                     Interop.Playlist.Destroy(handle);
396                 }
397             }
398         }
399
400         /// <summary>
401         /// Retrieves the number of media information of the playlist.
402         /// </summary>
403         /// <param name="playlistId">The playlist ID to count media added to the playlist.</param>
404         /// <returns>The number of media information.</returns>
405         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
406         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
407         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
408         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
409         /// <since_tizen> 4 </since_tizen>
410         public int CountMember(int playlistId)
411         {
412             return CountMember(playlistId, null);
413         }
414
415         /// <summary>
416         /// Retrieves the number of media information of the playlist with the <see cref="CountArguments"/>.
417         /// </summary>
418         /// <param name="playlistId">The playlist ID to count the media added to the playlist.</param>
419         /// <param name="arguments">The criteria to use to filter. This value can be null.</param>
420         /// <returns>The number of media information.</returns>
421         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
422         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
423         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
424         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
425         /// <since_tizen> 4 </since_tizen>
426         public int CountMember(int playlistId, CountArguments arguments)
427         {
428             ValidateDatabase();
429
430             if (playlistId <= 0)
431             {
432                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
433                     "Playlist id can't be less than or equal to zero.");
434             }
435
436             return CommandHelper.Count(Interop.Playlist.GetMediaCountFromDb, playlistId, arguments);
437
438         }
439
440         private static List<PlaylistMember> GetMembers(int playlistId, SelectArguments arguments)
441         {
442             using (var filter = QueryArguments.ToNativeHandle(arguments))
443             {
444                 Exception caught = null;
445                 List<PlaylistMember> list = new List<PlaylistMember>();
446
447                 Interop.Playlist.ForeachMediaFromDb(playlistId, filter, (memberId, mediaInfoHandle, _) =>
448                 {
449                     try
450                     {
451                         list.Add(new PlaylistMember(memberId, MediaInfo.FromHandle(mediaInfoHandle)));
452
453                         return true;
454                     }
455                     catch (Exception e)
456                     {
457                         caught = e;
458                         return false;
459                     }
460                 }).ThrowIfError("Failed to query");
461
462                 if (caught != null)
463                 {
464                     throw caught;
465                 }
466
467                 return list;
468             }
469         }
470
471         /// <summary>
472         /// Retrieves the member ID of the media in the playlist.
473         /// </summary>
474         /// <param name="playlistId">The playlist ID.</param>
475         /// <param name="mediaId">The media ID.</param>
476         /// <returns>The member ID if the member was found in the playlist, otherwise -1.</returns>
477         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
478         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
479         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
480         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
481         /// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
482         /// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
483         /// <since_tizen> 4 </since_tizen>
484         public int GetMemberId(int playlistId, string mediaId)
485         {
486             ValidateDatabase();
487
488             ValidationUtil.ValidateNotNullOrEmpty(mediaId, nameof(mediaId));
489
490             if (playlistId <= 0)
491             {
492                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
493                     "Playlist id can't be less than or equal to zero.");
494             }
495
496             var reader = SelectMember(playlistId, new SelectArguments()
497             {
498                 FilterExpression = $"{MediaInfoColumns.Id}='{mediaId}'"
499             });
500             reader.Read();
501
502             return reader.Current?.MemberId ?? -1;
503         }
504
505         /// <summary>
506         /// Retrieves the media information of the playlist.
507         /// </summary>
508         /// <param name="playlistId">The playlist ID to query with.</param>
509         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
510         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
511         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
512         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
513         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
514         /// <since_tizen> 4 </since_tizen>
515         public MediaDataReader<PlaylistMember> SelectMember(int playlistId)
516         {
517             return SelectMember(playlistId, null);
518         }
519
520         /// <summary>
521         /// Retrieves the media information of the playlist with the <see cref="SelectArguments"/>.
522         /// </summary>
523         /// <param name="playlistId">The playlist ID to query with.</param>
524         /// <param name="filter">The criteria to use to filter. This value can be null.</param>
525         /// <returns>The <see cref="MediaDataReader{TRecord}"/> containing the results.</returns>
526         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
527         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
528         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
529         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
530         /// <since_tizen> 4 </since_tizen>
531         public MediaDataReader<PlaylistMember> SelectMember(int playlistId, SelectArguments filter)
532         {
533             ValidateDatabase();
534
535             if (playlistId <= 0)
536             {
537                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
538                     "Playlist id can't be less than or equal to zero.");
539             }
540
541             return new MediaDataReader<PlaylistMember>(GetMembers(playlistId, filter));
542         }
543
544         /// <summary>
545         /// Updates the playlist with the specified values.
546         /// </summary>
547         /// <privilege>http://tizen.org/privilege/content.write</privilege>
548         /// <param name="playlistId">The playlist ID to update.</param>
549         /// <param name="values">The values for the update.</param>
550         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
551         /// <remarks>Only values set in the <see cref="PlaylistUpdateValues"/> are updated.</remarks>
552         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
553         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
554         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
555         /// <exception cref="ArgumentNullException"><paramref name="values"/> is null.</exception>
556         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
557         /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
558         /// <since_tizen> 4 </since_tizen>
559         public bool Update(int playlistId, PlaylistUpdateValues values)
560         {
561             ValidateDatabase();
562
563             if (playlistId <= 0)
564             {
565                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
566                     "Playlist id can't be less than or equal to zero.");
567             }
568
569             if (values == null)
570             {
571                 throw new ArgumentNullException(nameof(values));
572             }
573
574             if (CommandHelper.Count(
575                 Interop.Playlist.GetPlaylistCount, $"{PlaylistColumns.Id}={playlistId}") == 0)
576             {
577                 return false;
578             }
579
580             Interop.Playlist.Create(out var handle).ThrowIfError("Failed to update");
581
582             try
583             {
584                 if (values.Name != null)
585                 {
586                     Interop.Playlist.SetName(handle, values.Name).ThrowIfError("Failed to update");
587                 }
588
589                 if (values.ThumbnailPath != null)
590                 {
591                     Interop.Playlist.SetThumbnailPath(handle, values.ThumbnailPath).ThrowIfError("Failed to update");
592                 }
593
594                 Interop.Playlist.Update(playlistId, handle).ThrowIfError("Failed to update");
595                 return true;
596             }
597             finally
598             {
599                 if (handle != IntPtr.Zero)
600                 {
601                     Interop.Playlist.Destroy(handle);
602                 }
603             }
604         }
605
606         /// <summary>
607         /// Adds the media to the playlist.
608         /// </summary>
609         /// <param name="playlistId">The playlist ID that the media will be added to.</param>
610         /// <param name="mediaId">The media ID to add to the playlist.</param>
611         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
612         /// <remarks>The invalid media ID will be ignored.</remarks>
613         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
614         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
615         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
616         /// <exception cref="ArgumentNullException"><paramref name="mediaId"/> is null.</exception>
617         /// <exception cref="ArgumentException"><paramref name="mediaId"/> is a zero-length string, contains only white space.</exception>
618         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
619         /// <since_tizen> 4 </since_tizen>
620         public bool AddMember(int playlistId, string mediaId)
621         {
622             ValidationUtil.ValidateNotNullOrEmpty(mediaId, nameof(mediaId));
623
624             return AddMembers(playlistId, new string[] { mediaId });
625         }
626
627         /// <summary>
628         /// Adds the media set to the playlist.
629         /// </summary>
630         /// <param name="playlistId">The playlist ID that the media will be added to.</param>
631         /// <param name="mediaIds">The collection of media ID to add to the playlist.</param>
632         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
633         /// <remarks>The invalid media IDs will be ignored.</remarks>
634         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
635         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
636         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
637         /// <exception cref="ArgumentNullException"><paramref name="mediaIds"/> is null.</exception>
638         /// <exception cref="ArgumentException">
639         ///     <paramref name="mediaIds"/> has no element.<br/>
640         ///     -or-<br/>
641         ///     <paramref name="mediaIds"/> contains null value.<br/>
642         ///     -or-<br/>
643         ///     <paramref name="mediaIds"/> contains a zero-length string or white space.
644         /// </exception>
645         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
646         /// <since_tizen> 4 </since_tizen>
647         public bool AddMembers(int playlistId, IEnumerable<string> mediaIds)
648         {
649             ValidateDatabase();
650
651             if (playlistId <= 0)
652             {
653                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
654                     "Playlist id can't be less than or equal to zero.");
655             }
656
657             if (mediaIds == null)
658             {
659                 throw new ArgumentNullException(nameof(mediaIds));
660             }
661
662             if (mediaIds.Count() == 0)
663             {
664                 throw new ArgumentException("mediaIds has no element.", nameof(mediaIds));
665             }
666
667             if (CommandHelper.Count(
668                 Interop.Playlist.GetPlaylistCount, $"{PlaylistColumns.Id}={playlistId}") == 0)
669             {
670                 return false;
671             }
672
673             IntPtr handle = IntPtr.Zero;
674             Interop.Playlist.Create(out handle).ThrowIfError("Failed to add member");
675
676             try
677             {
678                 foreach (var mediaId in mediaIds)
679                 {
680                     if (mediaId == null)
681                     {
682                         throw new ArgumentException("Media id should not be null.", nameof(mediaIds));
683                     }
684
685                     if (string.IsNullOrWhiteSpace(mediaId))
686                     {
687                         throw new ArgumentException("Media id should not be empty.", nameof(mediaId));
688                     }
689
690                     Interop.Playlist.AddMedia(handle, mediaId).ThrowIfError("Failed to add member");
691                 }
692
693                 Interop.Playlist.Update(playlistId, handle).ThrowIfError("Failed to add member");
694                 return true;
695             }
696             finally
697             {
698                 if (handle != IntPtr.Zero)
699                 {
700                     Interop.Playlist.Destroy(handle);
701                 }
702             }
703         }
704
705         /// <summary>
706         /// Removes a member from the playlist.
707         /// </summary>
708         /// <param name="playlistId">The playlist ID.</param>
709         /// <param name="memberId">The member ID to be removed.</param>
710         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
711         /// <remarks>The invalid ID will be ignored.</remarks>
712         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
713         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
714         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
715         /// <exception cref="ArgumentOutOfRangeException">
716         ///     <paramref name="playlistId"/> is less than or equal to zero.<br/>
717         ///     -or-<br/>
718         ///     <paramref name="memberId"/> is less than or equal to zero.
719         /// </exception>
720         /// <since_tizen> 4 </since_tizen>
721         public bool RemoveMember(int playlistId, int memberId)
722         {
723             if (memberId <= 0)
724             {
725                 throw new ArgumentOutOfRangeException(nameof(memberId), memberId,
726                     "Member id can't be less than or equal to zero.");
727             }
728
729             return RemoveMembers(playlistId, new int[] { memberId });
730         }
731
732         /// <summary>
733         /// Removes a media set from the playlist.
734         /// </summary>
735         /// <param name="playlistId">The playlist ID.</param>
736         /// <param name="memberIds">The collection of member ID to remove from to the playlist.</param>
737         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
738         /// <remarks>The invalid IDs will be ignored.</remarks>
739         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
740         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
741         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
742         /// <exception cref="ArgumentNullException"><paramref name="memberIds"/> is null.</exception>
743         /// <exception cref="ArgumentException">
744         ///     <paramref name="memberIds"/> has no element.<br/>
745         ///     -or-<br/>
746         ///     <paramref name="memberIds"/> contains a value which is less than or equal to zero.
747         /// </exception>
748         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
749         /// <since_tizen> 4 </since_tizen>
750         public bool RemoveMembers(int playlistId, IEnumerable<int> memberIds)
751         {
752             ValidateDatabase();
753
754             if (playlistId <= 0)
755             {
756                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
757                     "Playlist id can't be less than or equal to zero.");
758             }
759
760             if (memberIds == null)
761             {
762                 throw new ArgumentNullException(nameof(memberIds));
763             }
764
765             if (memberIds.Count() == 0)
766             {
767                 throw new ArgumentException("memberIds has no element.", nameof(memberIds));
768             }
769
770             if (CommandHelper.Count(
771                 Interop.Playlist.GetPlaylistCount, $"{PlaylistColumns.Id}={playlistId}") == 0)
772             {
773                 return false;
774             }
775
776             IntPtr handle = IntPtr.Zero;
777             Interop.Playlist.Create(out handle).ThrowIfError("Failed to add member");
778
779             try
780             {
781                 foreach (var memberId in memberIds)
782                 {
783                     if (memberId <= 0)
784                     {
785                         throw new ArgumentException(nameof(memberIds),
786                             "Member id can't be less than or equal to zero.");
787                     }
788
789                     Interop.Playlist.RemoveMedia(handle, memberId).ThrowIfError("Failed to add member");
790                 }
791
792                 Interop.Playlist.Update(playlistId, handle).ThrowIfError("Failed to add member");
793                 return true;
794             }
795             finally
796             {
797                 if (handle != IntPtr.Zero)
798                 {
799                     Interop.Playlist.Destroy(handle);
800                 }
801             }
802         }
803
804         /// <summary>
805         /// Updates a play order of the playlist.
806         /// </summary>
807         /// <param name="playlistId">The playlist ID.</param>
808         /// <param name="playOrder">The <see cref="PlayOrder"/> to apply.</param>
809         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
810         /// <remarks>The <see cref="PlayOrder.MemberId"/> that is invalid will be ignored.</remarks>
811         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
812         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
813         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
814         /// <exception cref="ArgumentNullException"><paramref name="playOrder"/> is null.</exception>
815         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
816         /// <since_tizen> 4 </since_tizen>
817         public bool UpdatePlayOrder(int playlistId, PlayOrder playOrder)
818         {
819             if (playOrder == null)
820             {
821                 throw new ArgumentNullException(nameof(playOrder));
822             }
823             return UpdatePlayOrders(playlistId, new PlayOrder[] { playOrder });
824         }
825
826         /// <summary>
827         /// Updates play orders of the playlist.
828         /// </summary>
829         /// <param name="playlistId">The playlist ID.</param>
830         /// <param name="orders">The collection of the <see cref="PlayOrder"/> to apply.</param>
831         /// <returns>true if the matched record was found and updated, otherwise false.</returns>
832         /// <remarks>The <see cref="PlayOrder.MemberId"/> that is invalid will be ignored.</remarks>
833         /// <exception cref="InvalidOperationException">The <see cref="MediaDatabase"/> is disconnected.</exception>
834         /// <exception cref="ObjectDisposedException">The <see cref="MediaDatabase"/> has already been disposed of.</exception>
835         /// <exception cref="MediaDatabaseException">An error occurred while executing the command.</exception>
836         /// <exception cref="ArgumentNullException"><paramref name="orders"/> is null.</exception>
837         /// <exception cref="ArgumentException">
838         ///     <paramref name="orders"/> has no element.<br/>
839         ///     -or-<br/>
840         ///     <paramref name="orders"/> contains a null value.
841         /// </exception>
842         /// <exception cref="ArgumentOutOfRangeException"><paramref name="playlistId"/> is less than or equal to zero.</exception>
843         /// <since_tizen> 4 </since_tizen>
844         public bool UpdatePlayOrders(int playlistId, IEnumerable<PlayOrder> orders)
845         {
846             ValidateDatabase();
847
848             if (playlistId <= 0)
849             {
850                 throw new ArgumentOutOfRangeException(nameof(playlistId), playlistId,
851                     "Playlist id can't be less than or equal to zero.");
852             }
853
854             if (orders == null)
855             {
856                 throw new ArgumentNullException(nameof(orders));
857             }
858
859             if (orders.Count() == 0)
860             {
861                 throw new ArgumentException("memberIds has no element.", nameof(orders));
862             }
863
864             if (CommandHelper.Count(
865                 Interop.Playlist.GetPlaylistCount, $"{PlaylistColumns.Id}={playlistId}") == 0)
866             {
867                 return false;
868             }
869
870             IntPtr handle = IntPtr.Zero;
871             Interop.Playlist.Create(out handle).ThrowIfError("Failed to add member");
872
873             try
874             {
875                 foreach (var order in orders)
876                 {
877                     if (order == null)
878                     {
879                         throw new ArgumentException(nameof(orders),
880                             "orders should not contain null value.");
881                     }
882                     Interop.Playlist.SetPlayOrder(handle, order.MemberId, order.Value).ThrowIfError("Failed to add member");
883                 }
884
885                 Interop.Playlist.Update(playlistId, handle).ThrowIfError("Failed to add member");
886                 return true;
887             }
888             finally
889             {
890                 if (handle != IntPtr.Zero)
891                 {
892                     Interop.Playlist.Destroy(handle);
893                 }
894             }
895         }
896     }
897 }