/* * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using Tizen.Applications; using System; using System.Collections.Generic; using NativeClient = Interop.MediaControllerClient; using NativeServer = Interop.MediaControllerServer; using NativeClientHandle = Interop.MediaControllerClientHandle; namespace Tizen.Multimedia.Remoting { /// /// Provides a means to send command to media control server. /// /// 5 public abstract class Command { private string _requestId; /// /// The id for command receiver. /// /// 5 protected string ReceiverId { get; private set; } /// /// Initializes a base class. /// /// 5 protected Command() { } /// /// Sets the server information. /// /// The receiver Id that receives command. internal void SetRequestInformation(string receiverId) { ReceiverId = receiverId ?? throw new ArgumentNullException(nameof(receiverId)); } /// /// Sets the client information. /// /// The receiver Id that receives response for command. /// The request Id for each command. internal void SetResponseInformation(string receiverId, string requestId) { ReceiverId = receiverId ?? throw new ArgumentNullException(nameof(receiverId)); ; _requestId = requestId ?? throw new ArgumentNullException(nameof(requestId)); ; } /// /// Requests command to server. /// /// The request id for each command. internal abstract string Request(NativeClientHandle clientHandle); /// /// Requests command to client. /// /// /// The request id for each command. internal virtual string Request(IntPtr serverHandle) => throw new NotImplementedException(); /// /// Represents a method that is called when an response command completes. /// /// 5 protected virtual void OnResponseCompleted() { } /// /// Responses command to the client. /// /// The server handle. /// The result of each command. /// The extra data. internal void Response(IntPtr serverHandle, int result, Bundle bundle) { try { if (bundle != null) { NativeServer.SendCommandReplyBundle(serverHandle, ReceiverId, _requestId, result, bundle.SafeBundleHandle) .ThrowIfError("Failed to response command."); } else { NativeServer.SendCommandReply(serverHandle, ReceiverId, _requestId, result, IntPtr.Zero) .ThrowIfError("Failed to response command."); } } catch (ArgumentException) { throw new InvalidOperationException("Server is not running"); } finally { OnResponseCompleted(); } } /// /// Responses command to the server. /// /// The client handle. /// The result of each command. /// The extra data. internal void Response(NativeClientHandle clientHandle, int result, Bundle bundle) { try { if (bundle != null) { NativeClient.SendCustomEventReplyBundle(clientHandle, ReceiverId, _requestId, result, bundle.SafeBundleHandle) .ThrowIfError("Failed to response event."); } else { NativeClient.SendCustomEventReply(clientHandle, ReceiverId, _requestId, result, IntPtr.Zero) .ThrowIfError("Failed to response event."); } } catch (ArgumentException) { throw new InvalidOperationException("Server is not running"); } finally { OnResponseCompleted(); } } } /// /// Provides a means to send playback command to media control server. /// public sealed class PlaybackCommand : Command { /// /// Initializes a new instance of the class. /// /// A . /// is not valid. /// 5 public PlaybackCommand(MediaControlPlaybackCommand action) { ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), action, nameof(action)); Action = action; } /// /// Gets the playback action. /// /// 5 public MediaControlPlaybackCommand Action { get; } internal override string Request(NativeClientHandle clientHandle) { ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), Action, nameof(Action)); NativeClient.SendPlaybackActionCommand(clientHandle, ReceiverId, Action.ToNative(), out string requestId) .ThrowIfError("Failed to send playback command."); return requestId; } } /// /// Provides a means to send playback command to order specific time position. /// public sealed class PlaybackPositionCommand : Command { /// /// Initializes a new instance of the class. /// /// The playback position in milliseconds. /// 5 public PlaybackPositionCommand(ulong position) { Position = position; } /// /// Gets the position to play. /// /// 5 public ulong Position { get; } internal override string Request(NativeClientHandle clientHandle) { NativeClient.SendPlaybackPositionCommand(clientHandle, ReceiverId, Position, out string requestId) .ThrowIfError("Failed to send playback position command."); return requestId; } } /// /// Provides a means to send playback command with playlist information. /// public sealed class PlaylistCommand : Command { /// /// Initializes a new instance of the class. /// /// A . /// The playlist name of the server. /// The index of the media in the playlist. /// The playback position in milliseconds. /// is not valid. /// /// or is null. /// /// 5 public PlaylistCommand(MediaControlPlaybackCommand action, string playlistName, string index, ulong position) { ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), action, nameof(action)); Action = action; Index = index ?? throw new ArgumentNullException(nameof(index)); Name = playlistName ?? throw new ArgumentNullException(nameof(playlistName)); Position = position; } /// /// Initializes a new instance of the class. /// /// A . /// The playlist name of the server. /// The index of the media in the playlist. /// /// or is null. /// /// 5 public PlaylistCommand(MediaControlPlaybackCommand action, string playlistName, string index) : this(action, playlistName, index, 0) { } /// /// Gets the playback action. /// /// 5 public MediaControlPlaybackCommand Action { get; } /// /// Gets the position to play. /// /// 5 public ulong Position { get; } /// /// Gets the index of playlist. /// /// 5 public string Index { get; } /// /// Gets the name of playlist. /// /// 5 public string Name { get; } internal override string Request(NativeClientHandle clientHandle) { ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), Action, nameof(Action)); NativeClient.SendPlaylistCommand(clientHandle, ReceiverId, Name, Index, Action.ToNative(), Position, out string requestId).ThrowIfError("Failed to send playlist command."); return requestId; } } /// /// Provides a means to to send shuffle mode commands. /// /// 5 public sealed class ShuffleModeCommand : Command { /// /// Initializes a new instance of the class. /// /// A shuffle mode. /// 5 public ShuffleModeCommand(bool enabled) { Enabled = enabled; } /// /// Gets a value indicating whether the shuffle mode is enabled. /// public bool Enabled { get; } internal override string Request(NativeClientHandle clientHandle) { var mode = Enabled ? MediaControllerNativeShuffleMode.On : MediaControllerNativeShuffleMode.Off; NativeClient.SendShuffleModeCommand(clientHandle, ReceiverId, mode, out string requestId). ThrowIfError("Failed to send playback shuffle command."); return requestId; } } /// /// Provides a means to to send repeat mode commands. /// /// 5 public sealed class RepeatModeCommand : Command { /// /// Initializes a new instance of the class. /// /// The . /// is not valid. /// 5 public RepeatModeCommand(MediaControlRepeatMode mode) { ValidationUtil.ValidateEnum(typeof(MediaControlRepeatMode), mode, nameof(mode)); Mode = mode; } /// /// Gets the repeat mode. /// /// 5 public MediaControlRepeatMode Mode { get; } internal override string Request(NativeClientHandle clientHandle) { ValidationUtil.ValidateEnum(typeof(MediaControlRepeatMode), Mode, nameof(Mode)); NativeClient.SendRepeatModeCommand(clientHandle, ReceiverId, Mode.ToNative(), out string requestId). ThrowIfError("Failed to send playback repeat command."); return requestId; } } /// /// Provides a means to to send subtitle mode command. /// /// 6 public sealed class SubtitleModeCommand : Command { /// /// Initializes a new instance of the class. /// /// A value indicating whether subtitle mode is enabled. /// 6 public SubtitleModeCommand(bool isEnabled) { IsEnabled = isEnabled; } /// /// Gets a value indicating whether subtitle mode is enabled or not. /// /// 6 public bool IsEnabled { get; } internal override string Request(NativeClientHandle clientHandle) { NativeClient.SendSubtitleModeCommand(clientHandle, ReceiverId, IsEnabled, out string requestId). ThrowIfError("Failed to send subtitle mode command."); return requestId; } } /// /// Provides a means to to send 360 mode command. /// /// 6 public sealed class Mode360Command : Command { /// /// Initializes a new instance of the class. /// /// A value indicating whether 360 mode is enabled or not. /// 6 public Mode360Command(bool isEnabled) { IsEnabled = isEnabled; } /// /// Gets a value indicating whether 360 mode is enabled or not. /// /// 6 public bool IsEnabled { get; } internal override string Request(NativeClientHandle clientHandle) { NativeClient.SendMode360Command(clientHandle, ReceiverId, IsEnabled, out string requestId). ThrowIfError("Failed to send 360 mode command."); return requestId; } } /// /// Provides a means to to send display mode command. /// /// 6 public sealed class DisplayModeCommand : Command { /// /// Initializes a new instance of the class. /// /// The . /// is not valid. /// 6 public DisplayModeCommand(MediaControlDisplayMode mode) { ValidationUtil.ValidateEnum(typeof(MediaControlDisplayMode), mode, nameof(mode)); Mode = mode; } /// /// Gets the display mode. /// /// 6 public MediaControlDisplayMode Mode { get; } internal override string Request(NativeClientHandle clientHandle) { NativeClient.SendDisplayModeCommand(clientHandle, ReceiverId, Mode.ToNative(), out string requestId). ThrowIfError("Failed to send display mode command."); return requestId; } } /// /// Provides a means to to send display rotation command. /// /// 6 public sealed class DisplayRotationCommand : Command { /// /// Initializes a new instance of the class. /// /// The . /// is not valid. /// 6 public DisplayRotationCommand(Rotation rotation) { ValidationUtil.ValidateEnum(typeof(Rotation), rotation, nameof(rotation)); Rotation = rotation; } /// /// Gets the display rotation. /// /// 6 public Rotation Rotation { get; } internal override string Request(NativeClientHandle clientHandle) { NativeClient.SendDisplayRotationCommand(clientHandle, ReceiverId, Rotation.ToNative(), out string requestId). ThrowIfError("Failed to send display rotation command."); return requestId; } } /// /// Provides a means to to send custom commands. /// /// This command can be used by both client and server to send predefined command or data. /// 5 public sealed class CustomCommand : Command { /// /// Initializes a new instance of the class. /// /// A predefined custom command. /// 5 public CustomCommand(string action) { Action = action ?? throw new ArgumentNullException(nameof(action)); } /// /// Initializes a new instance of the class. /// /// A predefined custom command. /// The extra data for custom command. /// 5 public CustomCommand(string action, Bundle bundle) : this(action) { Bundle = bundle; } /// /// Gets the custom action. /// /// 5 public string Action { get; } /// /// Gets the extra data. /// /// 5 public Bundle Bundle { get; } internal override string Request(NativeClientHandle clientHandle) { string requestId = null; if (Bundle != null) { NativeClient.SendCustomCommandBundle(clientHandle, ReceiverId, Action, Bundle.SafeBundleHandle, out requestId). ThrowIfError("Failed to send custom command."); } else { NativeClient.SendCustomCommand(clientHandle, ReceiverId, Action, IntPtr.Zero, out requestId). ThrowIfError("Failed to send custom command."); } return requestId; } internal override string Request(IntPtr serverHandle) { string requestId = null; if (Bundle != null) { NativeServer.SendCustomEventBundle(serverHandle, ReceiverId, Action, Bundle.SafeBundleHandle, out requestId) .ThrowIfError("Failed to send costom event."); } else { NativeServer.SendCustomEvent(serverHandle, ReceiverId, Action, IntPtr.Zero, out requestId) .ThrowIfError("Failed to send costom event."); } return requestId; } } /// /// Provides a means to to send search commands. /// /// 5 public sealed class SearchCommand : Command { private readonly IntPtr _searchHandle; /// /// Initializes a new instance of the class. /// /// User can search maximum 20 items once. /// is not set. /// /// is greater than maximum value(20).
/// -or-
/// is less than 1. ///
/// An internal error occurs. /// The set of . /// 5 public SearchCommand(List conditions) { if (conditions == null) { throw new ArgumentNullException(nameof(conditions)); } if (conditions.Count <= 0 || conditions.Count > 20) { var errMessage = $"Invalid number of search conditions. : {conditions.Count}. " + $"Valid range is 1 ~ 20."; throw new ArgumentException(errMessage); } NativeClient.CreateSearchHandle(out _searchHandle).ThrowIfError("Failed to create search handle."); try { foreach (var condition in conditions) { if (condition.Bundle != null) { NativeClient.SetSearchConditionBundle(_searchHandle, condition.ContentType, condition.Category, condition.Keyword, condition.Bundle.SafeBundleHandle). ThrowIfError("Failed to set search condition."); } else { NativeClient.SetSearchCondition(_searchHandle, condition.ContentType, condition.Category, condition.Keyword, IntPtr.Zero). ThrowIfError("Failed to set search condition."); } } } catch { if (_searchHandle != IntPtr.Zero) { NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle"); } throw; } } /// /// Initializes a new instance of the class. /// /// is not set. /// An internal error occurs. /// The set of . /// 5 public SearchCommand(MediaControlSearchCondition condition) { if (condition == null) { throw new ArgumentNullException(nameof(condition)); } NativeClient.CreateSearchHandle(out _searchHandle).ThrowIfError("Failed to create search handle."); try { if (condition.Bundle != null) { NativeClient.SetSearchConditionBundle(_searchHandle, condition.ContentType, condition.Category, condition.Keyword, condition.Bundle.SafeBundleHandle). ThrowIfError("Failed to set search condition."); } else { NativeClient.SetSearchCondition(_searchHandle, condition.ContentType, condition.Category, condition.Keyword, IntPtr.Zero). ThrowIfError("Failed to set search condition."); } } catch { if (_searchHandle != IntPtr.Zero) { NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle"); } throw; } } /// /// Initializes a new instance of the class by server side. /// internal SearchCommand(List conditions, IntPtr searchHandle) { _searchHandle = searchHandle; Conditions = conditions; } /// /// Gets or sets the search conditions. /// /// This property is used by MediaControlServer. /// 5 public IEnumerable Conditions { get; private set; } internal override string Request(NativeClientHandle clientHandle) { NativeClient.SendSearchCommand(clientHandle, ReceiverId, _searchHandle, out string requestId). ThrowIfError("Failed to send search command."); return requestId; } /// /// Represents a method that is called when an response command completes. /// /// 5 protected override void OnResponseCompleted() { base.OnResponseCompleted(); } } }