2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.Threading.Tasks;
21 using Tizen.Applications;
22 using Native = Interop.MediaControllerClient;
24 namespace Tizen.Multimedia.MediaController
28 /// The MediaControllerClient class provides APIs required for media-controller-client.
31 /// http://tizen.org/privilege/mediacontroller.client
34 /// The MediaControllerClient APIs provides functions to get media information from server.
36 public class MediaControllerClient : IDisposable
38 internal IntPtr _handle = IntPtr.Zero;
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;
54 private bool IsValidHandle
56 get { return (_handle != IntPtr.Zero); }
59 private IntPtr SafeHandle
65 throw new ObjectDisposedException(nameof(MediaControllerClient), "Fail to operate MediaControllerClient");
73 /// The constructor of MediaControllerClient class.
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()
80 MediaControllerValidator.ThrowIfError(
81 Native.Create(out _handle), "Create client failed");
84 ~MediaControllerClient()
92 GC.SuppressFinalize(this);
95 protected virtual void Dispose(bool disposing)
101 // To be used if there are any other disposable objects
106 Native.Destroy(_handle);
107 _handle = IntPtr.Zero;
115 /// ServerUpdated event is raised when server is changed
117 /// <since_tizen> 3 </since_tizen>
118 public event EventHandler<ServerUpdatedEventArgs> ServerUpdated
122 if (_serverUpdated == null)
124 RegisterServerUpdatedEvent();
127 _serverUpdated += value;
133 _serverUpdated -= value;
134 if (_serverUpdated == null)
136 UnregisterServerUpdatedEvent();
142 /// PlaybackUpdated event is raised when playback is changed
144 /// <since_tizen> 3 </since_tizen>
145 public event EventHandler<PlaybackUpdatedEventArgs> PlaybackUpdated
149 if (_playbackUpdated == null)
151 RegisterPlaybackUpdatedEvent();
154 _playbackUpdated += value;
160 _playbackUpdated -= value;
161 if (_playbackUpdated == null)
163 UnregisterPlaybackUpdatedEvent();
169 /// MetadataUpdated event is raised when metadata is changed
171 /// <since_tizen> 3 </since_tizen>
172 public event EventHandler<MetadataUpdatedEventArgs> MetadataUpdated
176 if (_metadataUpdated == null)
178 RegisterMetadataUpdatedEvent();
181 _metadataUpdated += value;
187 _metadataUpdated -= value;
188 if (_metadataUpdated == null)
190 UnregisterMetadataUpdatedEvent();
196 /// ShuffleModeUpdated event is raised when shuffle mode is changed
198 /// <since_tizen> 3 </since_tizen>
199 public event EventHandler<ShuffleModeUpdatedEventArgs> ShuffleModeUpdated
203 if (_shufflemodeUpdated == null)
205 RegisterShuffleModeUpdatedEvent();
208 _shufflemodeUpdated += value;
214 _shufflemodeUpdated -= value;
215 if (_shufflemodeUpdated == null)
217 UnregisterShuffleModeUpdatedEvent();
223 /// RepeatModeUpdated event is raised when server is changed
225 /// <since_tizen> 3 </since_tizen>
226 public event EventHandler<RepeatModeUpdatedEventArgs> RepeatModeUpdated
230 if (_repeatmodeUpdated == null)
232 RegisterRepeatModeUpdatedEvent();
235 _repeatmodeUpdated += value;
240 _repeatmodeUpdated -= value;
241 if (_repeatmodeUpdated == null)
243 UnregisterRepeatModeUpdatedEvent();
249 /// CommandReply event is raised when reply for command is recieved
251 /// <since_tizen> 3 </since_tizen>
252 public event EventHandler<CustomCommandReplyEventArgs> CustomCommandReply
256 if (_customcommandReply == null)
258 _customcommandReplyCallback = (IntPtr serverName, int result, IntPtr bundle, IntPtr userData) =>
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);
267 _customcommandReply += value;
273 _customcommandReply -= value;
274 if (_customcommandReply == null)
276 _customcommandReplyCallback = null;
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()
288 IntPtr name = IntPtr.Zero;
289 MediaControllerServerState state = MediaControllerServerState.None;
293 MediaControllerValidator.ThrowIfError(
294 Native.GetLatestServer(SafeHandle, out name, out state), "Get Latest server failed");
295 return new ServerInformation(Marshal.PtrToStringAnsi(name), (MediaControllerServerState)state);
299 LibcSupport.Free(name);
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)
312 IntPtr playbackHandle = IntPtr.Zero;
313 MediaControllerPlayback playback = null;
317 MediaControllerValidator.ThrowIfError(
318 Native.GetServerPlayback(SafeHandle, serverName, out playbackHandle), "Get Playback handle failed");
319 playback = new MediaControllerPlayback(playbackHandle);
323 if (playbackHandle != IntPtr.Zero)
325 MediaControllerValidator.ThrowIfError(
326 Native.DestroyPlayback(playbackHandle), "Destroy playback failed");
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)
342 IntPtr metadataHandle = IntPtr.Zero;
343 MediaControllerMetadata metadata = null;
347 MediaControllerValidator.ThrowIfError(
348 Native.GetServerMetadata(SafeHandle, serverName, out metadataHandle), "Get Metadata handle failed");
349 metadata = new MediaControllerMetadata(metadataHandle);
353 if (metadataHandle != IntPtr.Zero)
355 MediaControllerValidator.ThrowIfError(
356 Native.DestroyMetadata(metadataHandle), "Destroy metadata failed");
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)
372 MediaControllerShuffleMode shuffleMode = MediaControllerShuffleMode.Off;
374 MediaControllerValidator.ThrowIfError(
375 Native.GetServerShuffleMode(SafeHandle, serverName, out shuffleMode), "Get ShuffleMode failed");
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)
389 MediaControllerRepeatMode repeatMode = MediaControllerRepeatMode.Off;
391 MediaControllerValidator.ThrowIfError(
392 Native.GetServerRepeatMode(SafeHandle, serverName, out repeatMode), "Get RepeatMode failed");
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)
405 MediaControllerValidator.ThrowIfError(
406 Native.SendPlaybackStateCommand(SafeHandle, serverName, state), "Send playback state command failed");
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)
419 MediaControllerValidator.ThrowIfError(
420 Native.SendCustomCommand(SafeHandle, serverName, command, bundle.SafeBundleHandle, _customcommandReplyCallback, IntPtr.Zero),
421 "Send custom command failed");
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)
432 MediaControllerValidator.ThrowIfError(
433 Native.Subscribe(SafeHandle, type, serverName), "Subscribe failed");
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)
444 MediaControllerValidator.ThrowIfError(
445 Native.Unsubscribe(SafeHandle, type, serverName), "Unsubscribe failed");
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()
454 var task = new TaskCompletionSource<IEnumerable<string>>();
456 List<string> collectionList = ForEachActivatedServer(SafeHandle);
457 task.TrySetResult((IEnumerable<string>)collectionList);
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)
471 var task = new TaskCompletionSource<IEnumerable<string>>();
473 List<string> collectionList = ForEachSubscribedServer(SafeHandle, subscriptionType);
474 task.TrySetResult((IEnumerable<string>)collectionList);
479 private void RegisterServerUpdatedEvent()
481 _serverUpdatedCallback = (IntPtr serverName, MediaControllerServerState serverState, IntPtr userData) =>
483 ServerUpdatedEventArgs eventArgs = new ServerUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), serverState);
484 _serverUpdated?.Invoke(this, eventArgs);
486 Native.SetServerUpdatedCb(SafeHandle, _serverUpdatedCallback, IntPtr.Zero);
489 private void UnregisterServerUpdatedEvent()
491 Native.UnsetServerUpdatedCb(SafeHandle);
494 private void RegisterPlaybackUpdatedEvent()
496 _playbackUpdatedCallback = (IntPtr serverName, IntPtr playback, IntPtr userData) =>
498 PlaybackUpdatedEventArgs eventArgs = new PlaybackUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), playback);
499 _playbackUpdated?.Invoke(this, eventArgs);
501 Native.SetPlaybackUpdatedCb(SafeHandle, _playbackUpdatedCallback, IntPtr.Zero);
504 private void UnregisterPlaybackUpdatedEvent()
506 Native.UnsetPlaybackUpdatedCb(SafeHandle);
509 private void RegisterMetadataUpdatedEvent()
511 _metadataUpdatedCallback = (IntPtr serverName, IntPtr metadata, IntPtr userData) =>
513 MetadataUpdatedEventArgs eventArgs = new MetadataUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), metadata);
514 _metadataUpdated?.Invoke(this, eventArgs);
516 Native.SetMetadataUpdatedCb(SafeHandle, _metadataUpdatedCallback, IntPtr.Zero);
519 private void UnregisterMetadataUpdatedEvent()
521 Native.UnsetMetadataUpdatedCb(SafeHandle);
524 private void RegisterShuffleModeUpdatedEvent()
526 _shufflemodeUpdatedCallback = (IntPtr serverName, MediaControllerShuffleMode shuffleMode, IntPtr userData) =>
528 ShuffleModeUpdatedEventArgs eventArgs = new ShuffleModeUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), shuffleMode);
529 _shufflemodeUpdated?.Invoke(this, eventArgs);
532 MediaControllerValidator.ThrowIfError(
533 Native.SetShuffleModeUpdatedCb(SafeHandle, _shufflemodeUpdatedCallback, IntPtr.Zero),
534 "Set ShuffleModeUpdated callback failed");
537 private void UnregisterShuffleModeUpdatedEvent()
539 Native.UnsetShuffleModeUpdatedCb(SafeHandle);
542 private void RegisterRepeatModeUpdatedEvent()
544 _repeatmodeUpdatedCallback = (IntPtr serverName, MediaControllerRepeatMode repeatMode, IntPtr userData) =>
546 RepeatModeUpdatedEventArgs eventArgs = new RepeatModeUpdatedEventArgs(Marshal.PtrToStringAnsi(serverName), repeatMode);
547 _repeatmodeUpdated?.Invoke(this, eventArgs);
550 MediaControllerValidator.ThrowIfError(
551 Native.SetRepeatModeUpdatedCb(SafeHandle, _repeatmodeUpdatedCallback, IntPtr.Zero),
552 "Set RepeatModeUpdated callback failed");
555 private void UnregisterRepeatModeUpdatedEvent()
557 Native.UnsetRepeatModeUpdatedCb(SafeHandle);
560 private static List<string> ForEachSubscribedServer(IntPtr handle, MediaControllerSubscriptionType subscriptionType)
562 List<string> subscribedServerCollections = new List<string>();
564 Native.SubscribedServerCallback serverCallback = (IntPtr serverName, IntPtr userData) =>
566 subscribedServerCollections.Add(Marshal.PtrToStringAnsi(serverName));
570 MediaControllerValidator.ThrowIfError(
571 Native.ForeachSubscribedServer(handle, subscriptionType, serverCallback, IntPtr.Zero),
572 "Foreach Subscribed server failed");
574 return subscribedServerCollections;
577 private static List<string> ForEachActivatedServer(IntPtr handle)
579 List<string> activatedServerCollections = new List<string>();
581 Native.ActivatedServerCallback serverCallback = (IntPtr serverName, IntPtr userData) =>
583 activatedServerCollections.Add(Marshal.PtrToStringAnsi(serverName));
587 MediaControllerValidator.ThrowIfError(
588 Native.ForeachActivatedServer(handle, serverCallback, IntPtr.Zero),
589 "Foreach Activated server failed");
591 return activatedServerCollections;