Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / MediaController / MediaControllerClient.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.Runtime.InteropServices;
20 using System.Threading.Tasks;
21 using Tizen.Applications;
22 using Native = Interop.MediaControllerClient;
23
24 namespace Tizen.Multimedia.MediaController
25 {
26
27     /// <summary>
28     /// The MediaControllerClient class provides APIs required for media-controller-client.
29     /// </summary>
30     /// <privilege>
31     /// http://tizen.org/privilege/mediacontroller.client
32     /// </privilege>
33     /// <remarks>
34     /// The MediaControllerClient APIs provides functions to get media information from server.
35     /// </remarks>
36     public class MediaControllerClient : IDisposable
37     {
38         internal IntPtr _handle = IntPtr.Zero;
39
40         private bool _disposed = false;
41         private EventHandler<ServerUpdatedEventArgs> _serverUpdated;
42         private Native.ServerUpdatedCallback _serverUpdatedCallback;
43         private EventHandler<PlaybackUpdatedEventArgs> _playbackUpdated;
44         private Native.PlaybackUpdatedCallback _playbackUpdatedCallback;
45         private EventHandler<MetadataUpdatedEventArgs> _metadataUpdated;
46         private Native.MetadataUpdatedCallback _metadataUpdatedCallback;
47         private EventHandler<ShuffleModeUpdatedEventArgs> _shufflemodeUpdated;
48         private Native.ShuffleModeUpdatedCallback _shufflemodeUpdatedCallback;
49         private EventHandler<RepeatModeUpdatedEventArgs> _repeatmodeUpdated;
50         private Native.RepeatModeUpdatedCallback _repeatmodeUpdatedCallback;
51         private EventHandler<CustomCommandReplyEventArgs> _customcommandReply;
52         private Native.CommandReplyRecievedCallback _customcommandReplyCallback;
53
54         private bool IsValidHandle
55         {
56             get { return (_handle != IntPtr.Zero); }
57         }
58
59         private IntPtr SafeHandle
60         {
61             get
62             {
63                 if (!IsValidHandle)
64                 {
65                     throw new ObjectDisposedException(nameof(MediaControllerClient), "Fail to operate MediaControllerClient");
66                 }
67
68                 return _handle;
69             }
70         }
71
72         /// <summary>
73         /// The constructor of MediaControllerClient class.
74         /// </summary>
75         /// <since_tizen> 3 </since_tizen>
76         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
77         /// <exception cref="UnauthorizedAccessException">Thrown when the access is denied for media controller client</exception>
78         public MediaControllerClient()
79         {
80             MediaControllerValidator.ThrowIfError(
81                 Native.Create(out _handle), "Create client failed");
82         }
83
84         ~MediaControllerClient()
85         {
86             Dispose(false);
87         }
88
89         public void Dispose()
90         {
91             Dispose(true);
92             GC.SuppressFinalize(this);
93         }
94
95         protected virtual void Dispose(bool disposing)
96         {
97             if (!_disposed)
98             {
99                 if (disposing)
100                 {
101                     // To be used if there are any other disposable objects
102                 }
103
104                 if (IsValidHandle)
105                 {
106                     Native.Destroy(_handle);
107                     _handle = IntPtr.Zero;
108                 }
109
110                 _disposed = true;
111             }
112         }
113
114         /// <summary>
115         /// ServerUpdated event is raised when server is changed
116         /// </summary>
117         /// <since_tizen> 3 </since_tizen>
118         public event EventHandler<ServerUpdatedEventArgs> ServerUpdated
119         {
120             add
121             {
122                 if (_serverUpdated == null)
123                 {
124                     RegisterServerUpdatedEvent();
125                 }
126
127                 _serverUpdated += value;
128
129             }
130
131             remove
132             {
133                 _serverUpdated -= value;
134                 if (_serverUpdated == null)
135                 {
136                     UnregisterServerUpdatedEvent();
137                 }
138             }
139         }
140
141         /// <summary>
142         /// PlaybackUpdated event is raised when playback is changed
143         /// </summary>
144         /// <since_tizen> 3 </since_tizen>
145         public event EventHandler<PlaybackUpdatedEventArgs> PlaybackUpdated
146         {
147             add
148             {
149                 if (_playbackUpdated == null)
150                 {
151                     RegisterPlaybackUpdatedEvent();
152                 }
153
154                 _playbackUpdated += value;
155
156             }
157
158             remove
159             {
160                 _playbackUpdated -= value;
161                 if (_playbackUpdated == null)
162                 {
163                     UnregisterPlaybackUpdatedEvent();
164                 }
165             }
166         }
167
168         /// <summary>
169         /// MetadataUpdated event is raised when metadata is changed
170         /// </summary>
171         /// <since_tizen> 3 </since_tizen>
172         public event EventHandler<MetadataUpdatedEventArgs> MetadataUpdated
173         {
174             add
175             {
176                 if (_metadataUpdated == null)
177                 {
178                     RegisterMetadataUpdatedEvent();
179                 }
180
181                 _metadataUpdated += value;
182
183             }
184
185             remove
186             {
187                 _metadataUpdated -= value;
188                 if (_metadataUpdated == null)
189                 {
190                     UnregisterMetadataUpdatedEvent();
191                 }
192             }
193         }
194
195         /// <summary>
196         /// ShuffleModeUpdated event is raised when shuffle mode is changed
197         /// </summary>
198         /// <since_tizen> 3 </since_tizen>
199         public event EventHandler<ShuffleModeUpdatedEventArgs> ShuffleModeUpdated
200         {
201             add
202             {
203                 if (_shufflemodeUpdated == null)
204                 {
205                     RegisterShuffleModeUpdatedEvent();
206                 }
207
208                 _shufflemodeUpdated += value;
209
210             }
211
212             remove
213             {
214                 _shufflemodeUpdated -= value;
215                 if (_shufflemodeUpdated == null)
216                 {
217                     UnregisterShuffleModeUpdatedEvent();
218                 }
219             }
220         }
221
222         /// <summary>
223         /// RepeatModeUpdated event is raised when server is changed
224         /// </summary>
225         /// <since_tizen> 3 </since_tizen>
226         public event EventHandler<RepeatModeUpdatedEventArgs> RepeatModeUpdated
227         {
228             add
229             {
230                 if (_repeatmodeUpdated == null)
231                 {
232                     RegisterRepeatModeUpdatedEvent();
233                 }
234
235                 _repeatmodeUpdated += value;
236             }
237
238             remove
239             {
240                 _repeatmodeUpdated -= value;
241                 if (_repeatmodeUpdated == null)
242                 {
243                     UnregisterRepeatModeUpdatedEvent();
244                 }
245             }
246         }
247
248         /// <summary>
249         /// CommandReply event is raised when reply for command is recieved
250         /// </summary>
251         /// <since_tizen> 3 </since_tizen>
252         public event EventHandler<CustomCommandReplyEventArgs> CustomCommandReply
253         {
254             add
255             {
256                 if (_customcommandReply == null)
257                 {
258                     _customcommandReplyCallback = (IntPtr serverName, int result, IntPtr bundle, IntPtr userData) =>
259                     {
260                         SafeBundleHandle safeBundleHandle = new SafeBundleHandle(bundle, true);
261                         Bundle bundleData = new Bundle(safeBundleHandle);
262                         CustomCommandReplyEventArgs eventArgs = new CustomCommandReplyEventArgs(Marshal.PtrToStringAnsi(serverName), result, bundleData);
263                         _customcommandReply?.Invoke(this, eventArgs);
264                     };
265                 }
266
267                 _customcommandReply += value;
268
269             }
270
271             remove
272             {
273                 _customcommandReply -= value;
274                 if (_customcommandReply == null)
275                 {
276                     _customcommandReplyCallback = null;
277                 }
278             }
279         }
280
281         /// <summary>
282         /// gets latest server information </summary>
283         /// <since_tizen> 3 </since_tizen>
284         /// <returns>The name and state of the latest media controller server application: ServerInformation object</returns>
285         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
286         public ServerInformation GetLatestServer()
287         {
288             IntPtr name = IntPtr.Zero;
289             MediaControllerServerState state = MediaControllerServerState.None;
290
291             try
292             {
293                 MediaControllerValidator.ThrowIfError(
294                     Native.GetLatestServer(SafeHandle, out name, out state), "Get Latest server failed");
295                 return new ServerInformation(Marshal.PtrToStringAnsi(name), (MediaControllerServerState)state);
296             }
297             finally
298             {
299                 LibcSupport.Free(name);
300             }
301         }
302
303         /// <summary>
304         /// gets playback information for specific server </summary>
305         /// <since_tizen> 3 </since_tizen>
306         /// <param name="serverName"> Server Name  </param>
307         /// <returns>The playback state and playback position of the specific media controller server application:MediaControllerPlayback object</returns>
308         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
309         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
310         public MediaControllerPlayback GetPlayback(string serverName)
311         {
312             IntPtr playbackHandle = IntPtr.Zero;
313             MediaControllerPlayback playback = null;
314
315             try
316             {
317                 MediaControllerValidator.ThrowIfError(
318                     Native.GetServerPlayback(SafeHandle, serverName, out playbackHandle), "Get Playback handle failed");
319                 playback = new MediaControllerPlayback(playbackHandle);
320             }
321             finally
322             {
323                 if (playbackHandle != IntPtr.Zero)
324                 {
325                     MediaControllerValidator.ThrowIfError(
326                         Native.DestroyPlayback(playbackHandle), "Destroy playback failed");
327                 }
328             }
329
330             return playback;
331         }
332
333         /// <summary>
334         /// gets metadata information for specific server </summary>
335         /// <since_tizen> 3 </since_tizen>
336         /// <param name="serverName"> Server Name  </param>
337         /// <returns>The metadata information of the specific media controller server application:MediaControllerMetadata object</returns>
338         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
339         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
340         public MediaControllerMetadata GetMetadata(string serverName)
341         {
342             IntPtr metadataHandle = IntPtr.Zero;
343             MediaControllerMetadata metadata = null;
344
345             try
346             {
347                 MediaControllerValidator.ThrowIfError(
348                     Native.GetServerMetadata(SafeHandle, serverName, out metadataHandle), "Get Metadata handle failed");
349                 metadata = new MediaControllerMetadata(metadataHandle);
350             }
351             finally
352             {
353                 if (metadataHandle != IntPtr.Zero)
354                 {
355                     MediaControllerValidator.ThrowIfError(
356                     Native.DestroyMetadata(metadataHandle), "Destroy metadata failed");
357                 }
358             }
359
360             return metadata;
361         }
362
363         /// <summary>
364         /// gets shuffle mode for specific server </summary>
365         /// <since_tizen> 3 </since_tizen>
366         /// <param name="serverName"> Server Name  </param>
367         /// <returns>The shuffle mode of the specific media controller server application:MediaControllerShuffleMode enum</returns>
368         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
369         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
370         public MediaControllerShuffleMode GetShuffleMode(string serverName)
371         {
372             MediaControllerShuffleMode shuffleMode = MediaControllerShuffleMode.Off;
373
374             MediaControllerValidator.ThrowIfError(
375                 Native.GetServerShuffleMode(SafeHandle, serverName, out shuffleMode), "Get ShuffleMode failed");
376
377             return shuffleMode;
378         }
379
380         /// <summary>
381         /// gets repeat mode for specific server </summary>\
382         /// <since_tizen> 3 </since_tizen>
383         /// <param name="serverName"> Server Name  </param>
384         /// <returns>The repeat mode of the specific media controller server application:MediaControllerRepeatMode enum</returns>
385         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
386         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
387         public MediaControllerRepeatMode GetRepeatMode(string serverName)
388         {
389             MediaControllerRepeatMode repeatMode = MediaControllerRepeatMode.Off;
390
391             MediaControllerValidator.ThrowIfError(
392                 Native.GetServerRepeatMode(SafeHandle, serverName, out repeatMode), "Get RepeatMode failed");
393
394             return repeatMode;
395         }
396
397         /// <summary>
398         /// Send command of playback state to server application </summary>
399         /// <param name="serverName"> Server Name  </param>
400         /// <param name="state"> Playback State  </param>
401         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
402         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
403         public void SendPlaybackStateCommand(string serverName, MediaControllerPlaybackState state)
404         {
405             MediaControllerValidator.ThrowIfError(
406                 Native.SendPlaybackStateCommand(SafeHandle, serverName, state), "Send playback state command failed");
407         }
408
409         /// <summary>
410         /// Send customized command to server application </summary>
411         /// <since_tizen> 3 </since_tizen>
412         /// <param name="serverName"> Server Name  </param>
413         /// <param name="command"> Command  </param>
414         /// <param name="bundle"> Bundle data  </param>
415         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
416         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
417         public void SendCustomCommand(string serverName, string command, Bundle bundle)
418         {
419             MediaControllerValidator.ThrowIfError(
420                 Native.SendCustomCommand(SafeHandle, serverName, command, bundle.SafeBundleHandle, _customcommandReplyCallback, IntPtr.Zero),
421                 "Send custom command failed");
422         }
423
424         /// <summary>
425         /// Subscribe subscription type from specific server application </summary>
426         /// <since_tizen> 3 </since_tizen>
427         /// <param name="type"> Subscription Type  </param>
428         /// <param name="serverName"> Server Name  </param>
429         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
430         public void Subscribe(MediaControllerSubscriptionType type, string serverName)
431         {
432             MediaControllerValidator.ThrowIfError(
433                 Native.Subscribe(SafeHandle, type, serverName), "Subscribe failed");
434         }
435
436         /// <summary>
437         /// Subscribe subscription type from specific server application </summary>
438         /// <since_tizen> 3 </since_tizen>
439         /// <param name="type"> Subscription Type  </param>
440         /// <param name="serverName"> Server Name  </param>
441         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
442         public void Unsubscribe(MediaControllerSubscriptionType type, string serverName)
443         {
444             MediaControllerValidator.ThrowIfError(
445                 Native.Unsubscribe(SafeHandle, type, serverName), "Unsubscribe failed");
446         }
447
448         /// <summary>
449         /// gets activated server list </summary>
450         /// <since_tizen> 3 </since_tizen>
451         /// <returns>The list of activated media controller server applications: IEnumerable of string</returns>
452         public Task<IEnumerable<string>> GetActivatedServerList()
453         {
454             var task = new TaskCompletionSource<IEnumerable<string>>();
455
456             List<string> collectionList = ForEachActivatedServer(SafeHandle);
457             task.TrySetResult((IEnumerable<string>)collectionList);
458
459             return task.Task;
460         }
461
462         /// <summary>
463         /// gets subscribed server list </summary>
464         /// <since_tizen> 3 </since_tizen>
465         /// <param name="subscriptionType"> Subscription Type  </param>
466         /// <returns>The list of subscribed media controller server applications: IEnumerable of string</returns>
467         /// <exception cref="ArgumentException">Thrown when an invalid argument is used</exception>
468         /// <exception cref="InvalidOperationException">Thrown when the operation is invalid for the current state</exception>
469         public Task<IEnumerable<string>> GetSubscribedServerList(MediaControllerSubscriptionType subscriptionType)
470         {
471             var task = new TaskCompletionSource<IEnumerable<string>>();
472
473             List<string> collectionList = ForEachSubscribedServer(SafeHandle, subscriptionType);
474             task.TrySetResult((IEnumerable<string>)collectionList);
475
476             return task.Task;
477         }
478
479         private void RegisterServerUpdatedEvent()
480         {
481             _serverUpdatedCallback = (IntPtr serverName, MediaControllerServerState serverState, IntPtr userData) =>
482             {
483                 ServerUpdatedEventArgs eventArgs = new ServerUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), serverState);
484                 _serverUpdated?.Invoke(this, eventArgs);
485             };
486             Native.SetServerUpdatedCb(SafeHandle, _serverUpdatedCallback, IntPtr.Zero);
487         }
488
489         private void UnregisterServerUpdatedEvent()
490         {
491             Native.UnsetServerUpdatedCb(SafeHandle);
492         }
493
494         private void RegisterPlaybackUpdatedEvent()
495         {
496             _playbackUpdatedCallback = (IntPtr serverName, IntPtr playback, IntPtr userData) =>
497             {
498                 PlaybackUpdatedEventArgs eventArgs = new PlaybackUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), playback);
499                 _playbackUpdated?.Invoke(this, eventArgs);
500             };
501             Native.SetPlaybackUpdatedCb(SafeHandle, _playbackUpdatedCallback, IntPtr.Zero);
502         }
503
504         private void UnregisterPlaybackUpdatedEvent()
505         {
506             Native.UnsetPlaybackUpdatedCb(SafeHandle);
507         }
508
509         private void RegisterMetadataUpdatedEvent()
510         {
511             _metadataUpdatedCallback = (IntPtr serverName, IntPtr metadata, IntPtr userData) =>
512             {
513                 MetadataUpdatedEventArgs eventArgs = new MetadataUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), metadata);
514                 _metadataUpdated?.Invoke(this, eventArgs);
515             };
516             Native.SetMetadataUpdatedCb(SafeHandle, _metadataUpdatedCallback, IntPtr.Zero);
517         }
518
519         private void UnregisterMetadataUpdatedEvent()
520         {
521             Native.UnsetMetadataUpdatedCb(SafeHandle);
522         }
523
524         private void RegisterShuffleModeUpdatedEvent()
525         {
526             _shufflemodeUpdatedCallback = (IntPtr serverName, MediaControllerShuffleMode shuffleMode, IntPtr userData) =>
527             {
528                 ShuffleModeUpdatedEventArgs eventArgs = new ShuffleModeUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), shuffleMode);
529                 _shufflemodeUpdated?.Invoke(this, eventArgs);
530             };
531
532             MediaControllerValidator.ThrowIfError(
533                 Native.SetShuffleModeUpdatedCb(SafeHandle, _shufflemodeUpdatedCallback, IntPtr.Zero),
534                 "Set ShuffleModeUpdated callback failed");
535         }
536
537         private void UnregisterShuffleModeUpdatedEvent()
538         {
539             Native.UnsetShuffleModeUpdatedCb(SafeHandle);
540         }
541
542         private void RegisterRepeatModeUpdatedEvent()
543         {
544             _repeatmodeUpdatedCallback = (IntPtr serverName, MediaControllerRepeatMode repeatMode, IntPtr userData) =>
545             {
546                 RepeatModeUpdatedEventArgs eventArgs = new RepeatModeUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), repeatMode);
547                 _repeatmodeUpdated?.Invoke(this, eventArgs);
548             };
549
550             MediaControllerValidator.ThrowIfError(
551                 Native.SetRepeatModeUpdatedCb(SafeHandle, _repeatmodeUpdatedCallback, IntPtr.Zero),
552                 "Set RepeatModeUpdated callback failed");
553         }
554
555         private void UnregisterRepeatModeUpdatedEvent()
556         {
557             Native.UnsetRepeatModeUpdatedCb(SafeHandle);
558         }
559
560         private static List<string> ForEachSubscribedServer(IntPtr handle, MediaControllerSubscriptionType subscriptionType)
561         {
562             List<string> subscribedServerCollections = new List<string>();
563
564             Native.SubscribedServerCallback serverCallback = (IntPtr serverName, IntPtr userData) =>
565             {
566                 subscribedServerCollections.Add(Marshal.PtrToStringAnsi(serverName));
567                 return true;
568             };
569
570             MediaControllerValidator.ThrowIfError(
571                 Native.ForeachSubscribedServer(handle, subscriptionType, serverCallback, IntPtr.Zero),
572                 "Foreach Subscribed server failed");
573
574             return subscribedServerCollections;
575         }
576
577         private static List<string> ForEachActivatedServer(IntPtr handle)
578         {
579             List<string> activatedServerCollections = new List<string>();
580
581             Native.ActivatedServerCallback serverCallback = (IntPtr serverName, IntPtr userData) =>
582             {
583                 activatedServerCollections.Add(Marshal.PtrToStringAnsi(serverName));
584                 return true;
585             };
586
587             MediaControllerValidator.ThrowIfError(
588                 Native.ForeachActivatedServer(handle, serverCallback, IntPtr.Zero),
589                 "Foreach Activated server failed");
590
591             return activatedServerCollections;
592         }
593     }
594 }
595