[MediaController] Add new APIs for subtitle, 360 mode, display mode/rotation (#997)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / MediaController / MediaController.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.Linq;
19 using System.Collections.Generic;
20 using System.Diagnostics;
21 using System.Threading.Tasks;
22 using Tizen.Applications;
23 using Native = Interop.MediaControllerClient;
24 using NativePlaylist = Interop.MediaControllerPlaylist;
25
26 namespace Tizen.Multimedia.Remoting
27 {
28     /// <summary>
29     /// Provides a means to send commands to and handle events from media control server.
30     /// </summary>
31     /// <since_tizen> 4 </since_tizen>
32     public partial class MediaController
33     {
34         internal MediaController(MediaControllerManager manager, string serverAppId)
35         {
36             Debug.Assert(manager != null);
37             Debug.Assert(serverAppId != null);
38
39             Manager = manager;
40             ServerAppId = serverAppId;
41         }
42
43         private MediaControllerManager Manager { get; }
44
45         /// <summary>
46         /// Gets the application id of the server.
47         /// </summary>
48         /// <value>The server application id.</value>
49         /// <since_tizen> 4 </since_tizen>
50         public string ServerAppId { get; }
51
52         /// <summary>
53         /// Gets a value indicating whether the sever has been stopped.
54         /// </summary>
55         /// <value>true if the server has been stopped; otherwise, false.</value>
56         /// <since_tizen> 4 </since_tizen>
57         public bool IsStopped
58         {
59             get;
60             private set;
61         }
62
63         private void ThrowIfStopped()
64         {
65             if (IsStopped)
66             {
67                 throw new InvalidOperationException("The server has already been stopped.");
68             }
69         }
70
71
72         #region Get information
73         /// <summary>
74         /// Returns the playback state set by the server.
75         /// </summary>
76         /// <returns>The playback state.</returns>
77         /// <exception cref="InvalidOperationException">
78         ///     The server has already been stopped.<br/>
79         ///     -or-<br/>
80         ///     An internal error occurs.
81         /// </exception>
82         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
83         /// <seealso cref="MediaControlServer.SetPlaybackState(MediaControlPlaybackState, long)"/>
84         /// <since_tizen> 4 </since_tizen>
85         public MediaControlPlaybackState GetPlaybackState()
86         {
87             ThrowIfStopped();
88
89             IntPtr playbackHandle = IntPtr.Zero;
90
91             try
92             {
93                 Native.GetServerPlaybackHandle(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
94
95                 Native.GetPlaybackState(playbackHandle, out var playbackCode).ThrowIfError("Failed to get state.");
96
97                 return playbackCode.ToPublic();
98             }
99             finally
100             {
101                 if (playbackHandle != IntPtr.Zero)
102                 {
103                     Native.DestroyPlayback(playbackHandle);
104                 }
105             }
106         }
107
108         /// <summary>
109         /// Returns the playback position set by the server.
110         /// </summary>
111         /// <returns>The playback position in milliseconds.</returns>
112         /// <exception cref="InvalidOperationException">
113         ///     The server has already been stopped.<br/>
114         ///     -or-<br/>
115         ///     An internal error occurs.
116         /// </exception>
117         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
118         /// <seealso cref="MediaControlServer.SetPlaybackState(MediaControlPlaybackState, long)"/>
119         /// <since_tizen> 4 </since_tizen>
120         public long GetPlaybackPosition()
121         {
122             ThrowIfStopped();
123
124             IntPtr playbackHandle = IntPtr.Zero;
125
126             try
127             {
128                 Native.GetServerPlaybackHandle(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
129
130                 Native.GetPlaybackPosition(playbackHandle, out var position).ThrowIfError("Failed to get position.");
131
132                 return (long)position;
133             }
134             finally
135             {
136                 if (playbackHandle != IntPtr.Zero)
137                 {
138                     Native.DestroyPlayback(playbackHandle);
139                 }
140             }
141         }
142
143         /// <summary>
144         /// Returns the metadata set by the server.
145         /// </summary>
146         /// <returns>The metadata.</returns>
147         /// <exception cref="InvalidOperationException">
148         ///     The server has already been stopped.<br/>
149         ///     -or-<br/>
150         ///     An internal error occurs.
151         /// </exception>
152         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
153         /// <seealso cref="MediaControlServer.SetMetadata(MediaControlMetadata)"/>
154         /// <since_tizen> 4 </since_tizen>
155         public MediaControlMetadata GetMetadata()
156         {
157             ThrowIfStopped();
158
159             IntPtr metadataHandle = IntPtr.Zero;
160
161             try
162             {
163                 NativePlaylist.GetServerMetadata(Manager.Handle, ServerAppId, out metadataHandle).
164                     ThrowIfError("Failed to get metadata.");
165
166                 return new MediaControlMetadata(metadataHandle);
167             }
168             finally
169             {
170                 if (metadataHandle != IntPtr.Zero)
171                 {
172                     NativePlaylist.DestroyMetadata(metadataHandle);
173                 }
174             }
175         }
176
177         /// <summary>
178         /// Returns the all playlists.
179         /// </summary>
180         /// <returns>The set of <see cref="MediaControlPlaylist"/>.</returns>
181         /// <exception cref="InvalidOperationException">
182         ///     The server has already been stopped.<br/>
183         ///     -or-<br/>
184         ///     An internal error occurs.
185         /// </exception>
186         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
187         /// <since_tizen> 5 </since_tizen>
188         public IEnumerable<MediaControlPlaylist> GetPlaylists()
189         {
190             ThrowIfStopped();
191
192             var playlists = new List<MediaControlPlaylist>();
193
194             Exception caught = null;
195
196             NativePlaylist.PlaylistCallback playlistCallback = (handle, _) =>
197             {
198                 try
199                 {
200                     playlists.Add(new MediaControlPlaylist(handle));
201                     return true;
202                 }
203                 catch (Exception e)
204                 {
205                     caught = e;
206                     return false;
207                 }
208             };
209
210             NativePlaylist.ForeachPlaylist(ServerAppId, playlistCallback, IntPtr.Zero).
211                 ThrowIfError("Failed to get playlist.");
212
213             if (caught != null)
214             {
215                 throw caught;
216             }
217
218             return playlists.AsReadOnly();
219         }
220
221         /// <summary>
222         /// Returns the playlist name of current playing media.
223         /// </summary>
224         /// <returns>The playlist name.</returns>
225         /// <exception cref="InvalidOperationException">
226         ///     The server has already been stopped.<br/>
227         ///     -or-<br/>
228         ///     An internal error occurs.
229         /// </exception>
230         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
231         /// <since_tizen> 5 </since_tizen>
232         public MediaControlPlaylist GetPlaylistOfCurrentPlayingMedia()
233         {
234             ThrowIfStopped();
235
236             IntPtr playbackHandle = IntPtr.Zero;
237
238             // Get the playlist name of current playing media.
239             try
240             {
241                 Native.GetServerPlaybackHandle(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
242
243                 var (name, index) = NativePlaylist.GetPlaylistInfo(playbackHandle);
244
245                 return GetPlaylists().FirstOrDefault(playlist => playlist.Name == name);
246             }
247             finally
248             {
249                 if (playbackHandle != IntPtr.Zero)
250                 {
251                     Native.DestroyPlayback(playbackHandle).ThrowIfError("Failed to destroy playback handle.");
252                 }
253             }
254         }
255
256         /// <summary>
257         /// Returns the index of current playing media.
258         /// </summary>
259         /// <returns>The index of current playing media.</returns>
260         /// <exception cref="InvalidOperationException">
261         ///     The server has already been stopped.<br/>
262         ///     -or-<br/>
263         ///     An internal error occurs.
264         /// </exception>
265         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
266         /// <since_tizen> 5 </since_tizen>
267         public string GetIndexOfCurrentPlayingMedia()
268         {
269             ThrowIfStopped();
270
271             IntPtr playbackHandle = IntPtr.Zero;
272
273             try
274             {
275                 Native.GetServerPlaybackHandle(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
276
277                 var (name, index) = NativePlaylist.GetPlaylistInfo(playbackHandle);
278                 return index;
279             }
280             finally
281             {
282                 if (playbackHandle != IntPtr.Zero)
283                 {
284                     Native.DestroyPlayback(playbackHandle).ThrowIfError("Failed to destroy playback handle.");
285                 }
286             }
287         }
288
289         /// <summary>
290         /// Returns whether the shuffle mode is enabled.
291         /// </summary>
292         /// <returns>A value indicating whether the shuffle mode is enabled.</returns>
293         /// <exception cref="InvalidOperationException">
294         ///     The server has already been stopped.<br/>
295         ///     -or-<br/>
296         ///     An internal error occurs.
297         /// </exception>
298         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
299         /// <seealso cref="MediaControlServer.SetShuffleModeEnabled(bool)"/>
300         /// <since_tizen> 4 </since_tizen>
301         public bool IsShuffleModeEnabled()
302         {
303             ThrowIfStopped();
304
305             Native.GetServerShuffleMode(Manager.Handle, ServerAppId, out var shuffleMode).
306                 ThrowIfError("Failed to get shuffle mode state.");
307
308             return shuffleMode == MediaControllerNativeShuffleMode.On;
309         }
310
311         /// <summary>
312         /// Returns the repeat mode.
313         /// </summary>
314         /// <returns>A <see cref="MediaControlRepeatMode"/> set by the server.</returns>
315         /// <exception cref="InvalidOperationException">
316         ///     The server has already been stopped.<br/>
317         ///     -or-<br/>
318         ///     An internal error occurs.
319         /// </exception>
320         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
321         /// <seealso cref="MediaControlServer.SetRepeatMode(MediaControlRepeatMode)"/>
322         /// <since_tizen> 4 </since_tizen>
323         public MediaControlRepeatMode GetRepeatMode()
324         {
325             ThrowIfStopped();
326
327             Native.GetServerRepeatMode(Manager.Handle, ServerAppId, out var repeatMode).
328                 ThrowIfError("Failed to get repeat mode state.");
329
330             return repeatMode.ToPublic();
331         }
332
333         /// <summary>
334         /// Gets the content type of current playing media.
335         /// </summary>
336         /// <returns>The <see cref="MediaControlContentType"/>.</returns>
337         /// <exception cref="InvalidOperationException">
338         ///     The server has already been stopped.<br/>
339         ///     -or-<br/>
340         ///     An internal error occurs.
341         /// </exception>
342         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
343         /// <since_tizen> 5 </since_tizen>
344         public MediaControlContentType GetContentTypeOfCurrentPlayingMedia()
345         {
346             ThrowIfStopped();
347
348             IntPtr playbackHandle = IntPtr.Zero;
349
350             try
351             {
352                 Native.GetServerPlaybackHandle(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
353
354                 Native.GetPlaybackContentType(playbackHandle, out MediaControlContentType type).
355                     ThrowIfError("Failed to get playback content type");
356
357                 return type;
358             }
359             finally
360             {
361                 if (playbackHandle != IntPtr.Zero)
362                 {
363                     Native.DestroyPlayback(playbackHandle);
364                 }
365             }
366         }
367
368         /// <summary>
369         /// Gets the icon path.
370         /// </summary>
371         /// <returns>The icon path.</returns>
372         /// <exception cref="InvalidOperationException">
373         ///     The server has already been stopped.<br/>
374         ///     -or-<br/>
375         ///     An internal error occurs.
376         /// </exception>
377         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
378         /// <since_tizen> 5 </since_tizen>
379         public string GetIconPath()
380         {
381             ThrowIfStopped();
382
383             Native.GetServerIcon(Manager.Handle, ServerAppId, out string uri).
384                 ThrowIfError("Failed to get icon path.");
385
386             return uri;
387         }
388
389         /// <summary>
390         /// Gets the age rating of current playing media.
391         /// </summary>
392         /// <returns>The Age rating of current playing media. The range is 0 to 19, inclusive.</returns>
393         /// <exception cref="InvalidOperationException">
394         ///     The server has already been stopped.<br/>
395         ///     -or-<br/>
396         ///     An internal error occurs.
397         /// </exception>
398         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
399         /// <since_tizen> 5 </since_tizen>
400         public int GetAgeRatingOfCurrentPlayingMedia()
401         {
402             ThrowIfStopped();
403
404             IntPtr playbackHandle = IntPtr.Zero;
405
406             try
407             {
408                 Native.GetServerPlaybackHandle(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
409
410                 Native.GetAgeRating(playbackHandle, out int ageRating).ThrowIfError("Failed to get age rating.");
411
412                 return ageRating;
413             }
414             finally
415             {
416                 if (playbackHandle != IntPtr.Zero)
417                 {
418                     Native.DestroyPlayback(playbackHandle);
419                 }
420             }
421         }
422
423         /// <summary>
424         /// Gets whether the subtitle mode is enabled or not.
425         /// </summary>
426         /// <returns>A value indicating whether the subtitle mode is enabled or not.</returns>
427         /// <value>true if the subtitle mode is enabled; otherwise, false.</value>
428         /// <exception cref="InvalidOperationException">
429         ///     The server has already been stopped.<br/>
430         ///     -or-<br/>
431         ///     An internal error occurs.
432         /// </exception>
433         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
434         /// <since_tizen> 6 </since_tizen>
435         public bool IsSubtitleModeEnabled()
436         {
437             ThrowIfStopped();
438
439             Native.IsSubtitleEnabled(Manager.Handle, ServerAppId, out var isEnabled).
440                 ThrowIfError("Failed to get subtitle mode state.");
441
442             return isEnabled;
443         }
444
445         /// <summary>
446         /// Gets whether the 360 mode is enabled or not.
447         /// </summary>
448         /// <returns>A value indicating whether the 360 mode is enabled or not.</returns>
449         /// <value>true if the 360 mode is enabled; otherwise, false.</value>
450         /// <exception cref="InvalidOperationException">
451         ///     The server has already been stopped.<br/>
452         ///     -or-<br/>
453         ///     An internal error occurs.
454         /// </exception>
455         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
456         /// <since_tizen> 6 </since_tizen>
457         public bool IsMode360Enabled()
458         {
459             ThrowIfStopped();
460
461             Native.IsMode360Enabled(Manager.Handle, ServerAppId, out var isEnabled).
462                 ThrowIfError("Failed to get 360 mode state.");
463
464             return isEnabled;
465         }
466
467         /// <summary>
468         /// Gets the current display mode.
469         /// </summary>
470         /// <returns>The <see cref="MediaControlDisplayMode"/>.</returns>
471         /// <exception cref="InvalidOperationException">
472         ///     The server has already been stopped.<br/>
473         ///     -or-<br/>
474         ///     An internal error occurs.
475         /// </exception>
476         /// <exception cref="ObjectDisposedException">
477         /// The <see cref="MediaControllerManager"/> has already been disposed.
478         /// </exception>
479         /// <since_tizen> 6 </since_tizen>
480         public MediaControlDisplayMode GetDisplayMode()
481         {
482             ThrowIfStopped();
483
484             Native.GetDisplayMode(Manager.Handle, ServerAppId, out var mode).
485                 ThrowIfError("Failed to get display mode state.");
486
487             return mode.ToPublic();
488         }
489
490         /// <summary>
491         /// Gets the current display rotation.
492         /// </summary>
493         /// <returns>The <see cref="Rotation"/>.</returns>
494         /// <exception cref="InvalidOperationException">
495         ///     The server has already been stopped.<br/>
496         ///     -or-<br/>
497         ///     An internal error occurs.
498         /// </exception>
499         /// <exception cref="ObjectDisposedException">
500         /// The <see cref="MediaControllerManager"/> has already been disposed.
501         /// </exception>
502         /// <since_tizen> 6 </since_tizen>
503         public Rotation GetDisplayRotation()
504         {
505             ThrowIfStopped();
506
507             Native.GetDisplayRotation(Manager.Handle, ServerAppId, out var rotation).
508                 ThrowIfError("Failed to get display rotation state.");
509
510             return rotation.ToPublic();
511         }
512         #endregion Get information
513
514
515         #region Capability
516         /// <summary>
517         /// Gets the value whether <see cref="MediaControlPlaybackCommand"/> is supported or not.
518         /// </summary>
519         /// <returns>
520         /// the set of <see cref="MediaControlPlaybackCommand"/> and <see cref="MediaControlCapabilitySupport"/>.
521         /// </returns>
522         /// <exception cref="InvalidOperationException">
523         ///     The server has already been stopped.<br/>
524         ///     -or-<br/>
525         ///     An internal error occurs.
526         /// </exception>
527         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
528         /// <since_tizen> 5 </since_tizen>
529         public Dictionary<MediaControlPlaybackCommand, MediaControlCapabilitySupport> GetPlaybackCapabilities()
530         {
531             ThrowIfStopped();
532
533             IntPtr playbackCapaHandle = IntPtr.Zero;
534
535             var playbackCapabilities = new Dictionary<MediaControlPlaybackCommand, MediaControlCapabilitySupport>();
536
537             try
538             {
539                 Native.GetPlaybackCapabilityHandle(Manager.Handle, ServerAppId, out playbackCapaHandle).
540                     ThrowIfError("Failed to get playback capability handle.");
541
542                 foreach (MediaControllerNativePlaybackAction action in Enum.GetValues(typeof(MediaControllerNativePlaybackAction)))
543                 {
544                     Native.GetPlaybackCapability(playbackCapaHandle, action, out MediaControlCapabilitySupport support);
545                     playbackCapabilities.Add(action.ToPublic(), support);
546                 }
547
548                 return playbackCapabilities;
549             }
550             finally
551             {
552                 if (playbackCapaHandle != IntPtr.Zero)
553                 {
554                     Native.DestroyCapability(playbackCapaHandle);
555                 }
556             }
557         }
558
559         /// <summary>
560         /// Gets the value whether <paramref name="action"/> is supported or not.
561         /// </summary>
562         /// <param name="action">A playback command.</param>
563         /// <returns>A <see cref="MediaControlCapabilitySupport"/>.</returns>
564         /// <exception cref="ArgumentException"><paramref name="action"/> is not valid.</exception>
565         /// <exception cref="InvalidOperationException">
566         ///     The server has already been stopped.<br/>
567         ///     -or-<br/>
568         ///     An internal error occurs.
569         /// </exception>
570         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
571         /// <since_tizen> 5 </since_tizen>
572         public MediaControlCapabilitySupport GetPlaybackCapability(MediaControlPlaybackCommand action)
573         {
574             ThrowIfStopped();
575
576             ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), action, nameof(action));
577
578             IntPtr playbackCapaHandle = IntPtr.Zero;
579
580             try
581             {
582                 Native.GetPlaybackCapabilityHandle(Manager.Handle, ServerAppId, out playbackCapaHandle).
583                     ThrowIfError("Failed to get playback capability handle.");
584
585                 Native.GetPlaybackCapability(playbackCapaHandle, action.ToNative(), out MediaControlCapabilitySupport support);
586
587                 return support;
588             }
589             finally
590             {
591                 if (playbackCapaHandle != IntPtr.Zero)
592                 {
593                     Native.DestroyCapability(playbackCapaHandle);
594                 }
595             }
596         }
597
598         /// <summary>
599         /// Gets the value whether the shuffle mode is supported or not.
600         /// </summary>
601         /// <returns>A <see cref="MediaControlCapabilitySupport"/>.</returns>
602         /// <exception cref="InvalidOperationException">
603         ///     The server has already been stopped.<br/>
604         ///     -or-<br/>
605         ///     An internal error occurs.
606         /// </exception>
607         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
608         /// <since_tizen> 5 </since_tizen>
609         public MediaControlCapabilitySupport GetShuffleModeCapability()
610         {
611             ThrowIfStopped();
612
613             Native.GetSimpleCapability(Manager.Handle, ServerAppId, MediaControlNativeCapabilityCategory.Shuffle, out MediaControlCapabilitySupport support).
614                 ThrowIfError("Failed to get shuffle mode capability");
615
616             return support;
617         }
618
619         /// <summary>
620         /// Gets the value whether the repeat mode is supported or not.
621         /// </summary>
622         /// <returns>A <see cref="MediaControlCapabilitySupport"/>.</returns>
623         /// <exception cref="InvalidOperationException">
624         ///     The server has already been stopped.<br/>
625         ///     -or-<br/>
626         ///     An internal error occurs.
627         /// </exception>
628         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
629         /// <since_tizen> 5 </since_tizen>
630         public MediaControlCapabilitySupport GetRepeatModeCapability()
631         {
632             ThrowIfStopped();
633
634             Native.GetSimpleCapability(Manager.Handle, ServerAppId, MediaControlNativeCapabilityCategory.Repeat, out MediaControlCapabilitySupport support).
635                 ThrowIfError("Failed to get repeat mode capability");
636
637             return support;
638         }
639
640         /// <summary>
641         /// Gets the value whether the repeat mode is supported or not.
642         /// </summary>
643         /// <returns>
644         /// If there's no supported display mode by server, it will return null.
645         /// otherwise, it will return the supported list of <see cref="MediaControlDisplayMode"/>.
646         /// </returns>
647         /// <exception cref="InvalidOperationException">
648         ///     The server has already been stopped.<br/>
649         ///     -or-<br/>
650         ///     An internal error occurs.
651         /// </exception>
652         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
653         /// <since_tizen> 6 </since_tizen>
654         public IEnumerable<MediaControlDisplayMode> GetDisplayModeCapability()
655         {
656             ThrowIfStopped();
657
658             Native.GetDisplayModeCapability(Manager.Handle, ServerAppId, out uint support).
659                 ThrowIfError("Failed to get display mode capability");
660
661             return support != 0 ? ((MediaControlNativeDisplayMode)support).ToPublicList() : null;
662         }
663
664         /// <summary>
665         /// Gets the value whether the display mode is supported or not.
666         /// </summary>
667         /// <returns>
668         /// If there's no supported display rotation by server, it will return null.
669         /// otherwise, it will return the supported list of <see cref="Rotation"/>.
670         /// </returns>
671         /// <exception cref="InvalidOperationException">
672         ///     The server has already been stopped.<br/>
673         ///     -or-<br/>
674         ///     An internal error occurs.
675         /// </exception>
676         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
677         /// <since_tizen> 6 </since_tizen>
678         public IEnumerable<Rotation> GetDisplayRotationapability()
679         {
680             ThrowIfStopped();
681
682             Native.GetDisplayRotationCapability(Manager.Handle, ServerAppId, out uint support).
683                 ThrowIfError("Failed to get display mode capability");
684
685             return support != 0 ? ((MediaControlNativeDisplayRotation)support).ToPublicList() : null;
686         }
687         #endregion Capability
688
689
690         #region Command
691         /// <summary>
692         /// Requests command to the server.
693         /// </summary>
694         /// <remarks>
695         /// The client can request the server to execute <see cref="PlaybackCommand"/> or <see cref="ShuffleModeCommand"/> or
696         /// <see cref="RepeatModeCommand"/> or <see cref="CustomCommand"/>, <br/>
697         /// and then, the client receive the result of each request(command).
698         /// </remarks>
699         /// <param name="command">A <see cref="Command"/> class.</param>
700         /// <returns><see cref="Bundle"/> represents the extra data from server and it can be null.</returns>
701         /// <exception cref="ArgumentNullException"><paramref name="command"/> is null.</exception>
702         /// <exception cref="InvalidOperationException">
703         ///     The server has already been stopped.<br/>
704         ///     -or-<br/>
705         ///     An internal error occurs.
706         /// </exception>
707         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
708         /// <since_tizen> 5 </since_tizen>
709         public async Task<Bundle> RequestAsync(Command command)
710         {
711             if (command == null)
712             {
713                 throw new ArgumentNullException(nameof(command));
714             }
715
716             ThrowIfStopped();
717
718             command.SetRequestInformation(ServerAppId);
719
720             var tcs = new TaskCompletionSource<MediaControllerError>();
721             string reqeustId = null;
722             Bundle bundle = null;
723
724             EventHandler<CommandCompletedEventArgs> eventHandler = (s, e) =>
725             {
726                 if (e.RequestId == reqeustId)
727                 {
728                     bundle = e.Bundle;
729                     tcs.TrySetResult(e.Result);
730                 }
731             };
732
733             try
734             {
735                 CommandCompleted += eventHandler;
736
737                 reqeustId = command.Request(Manager.Handle);
738
739                 (await tcs.Task).ThrowIfError("Failed to request command");
740
741                 return bundle;
742             }
743             finally
744             {
745                 CommandCompleted -= eventHandler;
746             }
747         }
748
749         /// <summary>
750         /// Sends the result of each command.
751         /// </summary>
752         /// <param name="command">The command that return to client.</param>
753         /// <param name="result">The result of <paramref name="command"/>.</param>
754         /// <param name="bundle">The extra data.</param>
755         /// <exception cref="ArgumentNullException"><paramref name="command"/> is null.</exception>
756         /// <exception cref="InvalidOperationException">
757         ///     The server is not running .<br/>
758         ///     -or-<br/>
759         ///     An internal error occurs.
760         /// </exception>
761         /// <since_tizen> 5 </since_tizen>
762         public void Response(Command command, int result, Bundle bundle)
763         {
764             if (command == null)
765             {
766                 throw new ArgumentNullException(nameof(command));
767             }
768
769             command.Response(Manager.Handle, result, bundle);
770         }
771
772         /// <summary>
773         /// Sends the result of each command.
774         /// </summary>
775         /// <param name="command">The command that return to client.</param>
776         /// <param name="result">The result of <paramref name="command"/>.</param>
777         /// <exception cref="ArgumentNullException"><paramref name="command"/> is null.</exception>
778         /// <exception cref="InvalidOperationException">
779         ///     The server is not running .<br/>
780         ///     -or-<br/>
781         ///     An internal error occurs.
782         /// </exception>
783         /// <since_tizen> 5 </since_tizen>
784         public void Response(Command command, int result)
785         {
786             if (command == null)
787             {
788                 throw new ArgumentNullException(nameof(command));
789             }
790
791             command.Response(Manager.Handle, result, null);
792         }
793
794         /// <summary>
795         /// Sends playback command to the server.
796         /// </summary>
797         /// <param name="command">A playback command.</param>
798         /// <exception cref="InvalidOperationException">
799         ///     The server has already been stopped.<br/>
800         ///     -or-<br/>
801         ///     An internal error occurs.
802         /// </exception>
803         /// <exception cref="ArgumentException"><paramref name="command"/> is not valid.</exception>
804         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed.</exception>
805         /// <seealso cref="MediaControlServer.PlaybackCommandReceived"/>
806         /// <since_tizen> 4 </since_tizen>
807         [Obsolete("Please do not use! This will be deprecated. Please use Request instead.")]
808         public void SendPlaybackCommand(MediaControlPlaybackCommand command)
809         {
810             ThrowIfStopped();
811
812             ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), command, nameof(command));
813
814             Native.SendPlaybackActionCommandWithoutReqId(Manager.Handle, ServerAppId, command.ToNative()).
815                 ThrowIfError("Failed to send command.");
816         }
817         #endregion Command
818     }
819 }