2 * Copyright (c) 2018 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.
17 using Tizen.Applications;
19 using System.Collections.Generic;
20 using NativeClient = Interop.MediaControllerClient;
21 using NativeServer = Interop.MediaControllerServer;
22 using NativeClientHandle = Interop.MediaControllerClientHandle;
24 namespace Tizen.Multimedia.Remoting
27 /// Provides a means to send command to media control server.
29 /// <since_tizen> 5 </since_tizen>
30 public abstract class Command
32 private string _requestId;
35 /// The id for command receiver.
37 /// <since_tizen> 5 </since_tizen>
38 protected string ReceiverId { get; private set; }
41 /// Initializes a <see cref="Command"/> base class.
43 /// <since_tizen> 5 </since_tizen>
44 protected Command() { }
47 /// Sets the server information.
49 /// <param name="receiverId">The receiver Id that receives command.</param>
50 internal void SetRequestInformation(string receiverId)
52 ReceiverId = receiverId;
56 /// Sets the client information.
58 /// <param name="receiverId">The receiver Id that receives response for command.</param>
59 /// <param name="requestId">The request Id for each command.</param>
60 internal void SetResponseInformation(string receiverId, string requestId)
62 ReceiverId = receiverId;
63 _requestId = requestId;
67 /// Requests command to server.
69 /// <returns>The request id for each command.</returns>
70 internal abstract string Request(NativeClientHandle clientHandle);
73 /// Requests command to client.
75 /// <param name="serverHandle"></param>
76 /// <returns>The request id for each command.</returns>
77 internal virtual string Request(IntPtr serverHandle) => throw new NotImplementedException();
80 /// Represents a method that is called when an response command completes.
82 /// <since_tizen> 5 </since_tizen>
83 protected virtual void OnResponseCompleted() { }
86 /// Responses command to the client.
88 /// <param name="serverHandle">The server handle.</param>
89 /// <param name="result">The result of each command.</param>
90 /// <param name="bundle">The extra data.</param>
91 internal void Response(IntPtr serverHandle, int result, Bundle bundle)
97 NativeServer.SendCommandReplyBundle(serverHandle, ReceiverId, _requestId, result, bundle.SafeBundleHandle)
98 .ThrowIfError("Failed to response command.");
102 NativeServer.SendCommandReply(serverHandle, ReceiverId, _requestId, result, IntPtr.Zero)
103 .ThrowIfError("Failed to response command.");
108 OnResponseCompleted();
113 /// Responses command to the server.
115 /// <param name="clientHandle">The client handle.</param>
116 /// <param name="result">The result of each command.</param>
117 /// <param name="bundle">The extra data.</param>
118 internal void Response(NativeClientHandle clientHandle, int result, Bundle bundle)
124 NativeClient.SendCustomEventReplyBundle(clientHandle, ReceiverId, _requestId, result, bundle.SafeBundleHandle)
125 .ThrowIfError("Failed to response event.");
129 NativeClient.SendCustomEventReply(clientHandle, ReceiverId, _requestId, result, IntPtr.Zero)
130 .ThrowIfError("Failed to repose event.");
135 OnResponseCompleted();
142 /// Provides a means to send playback command to media control server.
144 public sealed class PlaybackCommand : Command
147 /// Initializes a new instance of the <see cref="PlaybackCommand"/> class.
149 /// <param name="action">A <see cref="MediaControlPlaybackCommand"/>.</param>
150 /// <since_tizen> 5 </since_tizen>
151 public PlaybackCommand(MediaControlPlaybackCommand action)
157 /// Gets the playback action.
159 /// <since_tizen> 5 </since_tizen>
160 public MediaControlPlaybackCommand Action { get; }
162 internal override string Request(NativeClientHandle clientHandle)
164 ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), Action, nameof(MediaControlPlaybackCommand));
166 NativeClient.SendPlaybackActionCommand(clientHandle, ReceiverId, Action.ToNative(), out string requestId)
167 .ThrowIfError("Failed to send playback command.");
174 /// Provides a means to send playback command to order specific time position.
176 public sealed class PlaybackPositionCommand : Command
179 /// Initializes a new instance of the <see cref="PlaybackPositionCommand"/> class.
181 /// <param name="position">The playback position in milliseconds.</param>
182 /// <since_tizen> 5 </since_tizen>
183 public PlaybackPositionCommand(ulong position)
189 /// Gets the position to play.
191 /// <since_tizen> 5 </since_tizen>
192 public ulong Position { get; }
194 internal override string Request(NativeClientHandle clientHandle)
196 NativeClient.SendPlaybackPositionCommand(clientHandle, ReceiverId, Position, out string requestId)
197 .ThrowIfError("Failed to send playback position command.");
204 /// Provides a means to send playback command with playlist information.
206 public sealed class PlaylistCommand : Command
209 /// Initializes a new instance of the <see cref="PlaybackCommand"/> class.
211 /// <param name="action">A <see cref="MediaControlPlaybackCommand"/>.</param>
212 /// <param name="playlistName">The playlist name of the server.</param>
213 /// <param name="index">The index of the media in the playlist.</param>
214 /// <param name="position">The playback position in milliseconds.</param>
215 /// <exception cref="ArgumentException"><paramref name="index"/> cannot be converted to number.</exception>
216 /// <exception cref="ArgumentNullException">
217 /// <paramref name="playlistName"/> or <paramref name="index"/> is not vailed.
219 /// <since_tizen> 5 </since_tizen>
220 public PlaylistCommand(MediaControlPlaybackCommand action, string playlistName, string index, ulong position)
223 Index = index ?? throw new ArgumentNullException(nameof(index));
224 Name = playlistName ?? throw new ArgumentNullException(nameof(playlistName));
229 /// Initializes a new instance of the <see cref="PlaybackCommand"/> class.
231 /// <param name="action">A <see cref="MediaControlPlaybackCommand"/>.</param>
232 /// <param name="playlistName">The playlist name of the server.</param>
233 /// <param name="index">The index of the media in the playlist.</param>
234 /// <exception cref="ArgumentException"><paramref name="index"/> cannot be converted to number.</exception>
235 /// <exception cref="ArgumentNullException">
236 /// <paramref name="playlistName"/> or <paramref name="index"/> is null.
238 /// <since_tizen> 5 </since_tizen>
239 public PlaylistCommand(MediaControlPlaybackCommand action, string playlistName, string index)
240 : this(action, playlistName, index, 0)
245 /// Gets the playback action.
247 /// <since_tizen> 5 </since_tizen>
248 public MediaControlPlaybackCommand Action { get; }
251 /// Gets the position to play.
253 /// <since_tizen> 5 </since_tizen>
254 public ulong Position { get; }
257 /// Gets the index of playlist.
259 /// <since_tizen> 5 </since_tizen>
260 public string Index { get; }
263 /// Gets the name of playlist.
265 /// <since_tizen> 5 </since_tizen>
266 public string Name { get; }
268 internal override string Request(NativeClientHandle clientHandle)
270 ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), Action, nameof(MediaControlPlaybackCommand));
272 NativeClient.SendPlaylistCommand(clientHandle, ReceiverId, Name, Index, Action.ToNative(),
273 Position, out string requestId).ThrowIfError("Failed to send playlist command.");
280 /// Provides a means to to send shuffle mode commands.
282 /// <since_tizen> 5 </since_tizen>
283 public sealed class ShuffleModeCommand : Command
286 /// Initializes a new instance of the <see cref="ShuffleModeCommand"/> class.
288 /// <param name="enabled">A shuffle mode.</param>
289 /// <since_tizen> 5 </since_tizen>
290 public ShuffleModeCommand(bool enabled)
296 /// Gets a value indicating whether the shuffle mode is enabled.
298 public bool Enabled { get; }
300 internal override string Request(NativeClientHandle clientHandle)
302 var mode = Enabled ? MediaControllerNativeShuffleMode.On : MediaControllerNativeShuffleMode.Off;
304 NativeClient.SendShuffleModeCommand(clientHandle, ReceiverId, mode, out string requestId).
305 ThrowIfError("Failed to send playback shuffle command.");
312 /// Provides a means to to send repeat mode commands.
314 /// <since_tizen> 5 </since_tizen>
315 public sealed class RepeatModeCommand : Command
318 /// Initializes a new instance of the <see cref="RepeatModeCommand"/> class.
320 /// <param name="mode">The <see cref="MediaControlRepeatMode"/>.</param>
321 /// <since_tizen> 5 </since_tizen>
322 public RepeatModeCommand(MediaControlRepeatMode mode)
328 /// Gets the repeat mode.
330 /// <since_tizen> 5 </since_tizen>
331 public MediaControlRepeatMode Mode { get; }
333 internal override string Request(NativeClientHandle clientHandle)
335 ValidationUtil.ValidateEnum(typeof(MediaControlRepeatMode), Mode, nameof(MediaControlRepeatMode));
337 NativeClient.SendRepeatModeCommand(clientHandle, ReceiverId, Mode.ToNative(), out string requestId).
338 ThrowIfError("Failed to send playback repeat command.");
345 /// Provides a means to to send custom commands.
347 /// <remarks>This command can be used by both client and server to send predefined command or data.</remarks>
348 /// <since_tizen> 5 </since_tizen>
349 public sealed class CustomCommand : Command
352 /// Initializes a new instance of the <see cref="CustomCommand"/> class.
354 /// <param name="action">A predefined custom command.</param>
355 /// <since_tizen> 5 </since_tizen>
356 public CustomCommand(string action)
358 Action = action ?? throw new ArgumentNullException(nameof(action));
362 /// Initializes a new instance of the <see cref="CustomCommand"/> class.
364 /// <param name="action">A predefined custom command.</param>
365 /// <param name="bundle">The extra data for custom command.</param>
366 /// <since_tizen> 5 </since_tizen>
367 public CustomCommand(string action, Bundle bundle)
374 /// Gets the custom action.
376 /// <since_tizen> 5 </since_tizen>
377 public string Action { get; }
380 /// Gets the extra data.
382 /// <since_tizen> 5 </since_tizen>
383 public Bundle Bundle { get; }
385 internal override string Request(NativeClientHandle clientHandle)
387 string requestId = null;
391 NativeClient.SendCustomCommandBundle(clientHandle, ReceiverId, Action, Bundle.SafeBundleHandle, out requestId).
392 ThrowIfError("Failed to send custom command.");
396 NativeClient.SendCustomCommand(clientHandle, ReceiverId, Action, IntPtr.Zero, out requestId).
397 ThrowIfError("Failed to send custom command.");
403 internal override string Request(IntPtr serverHandle)
405 string requestId = null;
409 NativeServer.SendCustomEventBundle(serverHandle, ReceiverId, Action, Bundle.SafeBundleHandle, out requestId)
410 .ThrowIfError("Failed to send costom event.");
414 NativeServer.SendCustomEvent(serverHandle, ReceiverId, Action, IntPtr.Zero, out requestId)
415 .ThrowIfError("Failed to send costom event.");
423 /// Provides a means to to send search commands.
425 /// <since_tizen> 5 </since_tizen>
426 public sealed class SearchCommand : Command
428 private readonly IntPtr _searchHandle;
431 /// Initializes a new instance of the <see cref="SearchCommand"/> class.
433 /// <remarks>User can search maximum 20 items once.</remarks>
434 /// <exception cref="ArgumentNullException"><paramref name="conditions"/> is not set.</exception>
435 /// <exception cref="ArgumentException">
436 /// <paramref name="conditions.Count"/> is greater than maximum value(20).<br/>
438 /// <paramref name="conditions.Count"/> is less than 1.
440 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
441 /// <param name="conditions">The set of <see cref="MediaControlSearchCondition"/>.</param>
442 /// <since_tizen> 5 </since_tizen>
443 public SearchCommand(List<MediaControlSearchCondition> conditions)
445 if (conditions == null)
447 throw new ArgumentNullException(nameof(conditions));
449 if (conditions.Count <= 0 || conditions.Count > 20)
451 var errMessage = $"Invalid number of search conditions. : {conditions.Count}. " +
452 $"Valid range is 1 ~ 20.";
453 throw new ArgumentException(errMessage);
456 NativeClient.CreateSearchHandle(out _searchHandle).ThrowIfError("Failed to create search handle.");
460 foreach (var condition in conditions)
462 if (condition.Bundle != null)
464 NativeClient.SetSearchConditionBundle(_searchHandle, condition.ContentType, condition.Category,
465 condition.Keyword, condition.Bundle.SafeBundleHandle).
466 ThrowIfError("Failed to set search condition.");
470 NativeClient.SetSearchCondition(_searchHandle, condition.ContentType, condition.Category,
471 condition.Keyword, IntPtr.Zero).
472 ThrowIfError("Failed to set search condition.");
478 if (_searchHandle != IntPtr.Zero)
480 NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle");
487 /// Initializes a new instance of the <see cref="SearchCommand"/> class.
489 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
490 /// <param name="condition">The set of <see cref="MediaControlSearchCondition"/>.</param>
491 /// <since_tizen> 5 </since_tizen>
492 public SearchCommand(MediaControlSearchCondition condition)
494 NativeClient.CreateSearchHandle(out _searchHandle).ThrowIfError("Failed to create search handle.");
498 if (condition.Bundle != null)
500 NativeClient.SetSearchConditionBundle(_searchHandle, condition.ContentType, condition.Category,
501 condition.Keyword, condition.Bundle.SafeBundleHandle).
502 ThrowIfError("Failed to set search condition.");
506 NativeClient.SetSearchCondition(_searchHandle, condition.ContentType, condition.Category,
507 condition.Keyword, IntPtr.Zero).
508 ThrowIfError("Failed to set search condition.");
513 if (_searchHandle != IntPtr.Zero)
515 NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle");
521 internal SearchCommand(List<MediaControlSearchCondition> conditions, IntPtr searchHandle)
523 _searchHandle = searchHandle;
527 foreach (var condition in conditions)
529 if (condition.Bundle != null)
531 NativeClient.SetSearchConditionBundle(_searchHandle, condition.ContentType, condition.Category,
532 condition.Keyword, condition.Bundle.SafeBundleHandle).
533 ThrowIfError("Failed to set search condition.");
537 NativeClient.SetSearchCondition(_searchHandle, condition.ContentType, condition.Category,
538 condition.Keyword, IntPtr.Zero).
539 ThrowIfError("Failed to set search condition.");
545 if (_searchHandle != IntPtr.Zero)
547 NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle");
553 internal override string Request(NativeClientHandle clientHandle)
555 NativeClient.SendSearchCommand(clientHandle, ReceiverId, _searchHandle, out string requestId).
556 ThrowIfError("Failed to send search command.");
558 if (_searchHandle != IntPtr.Zero)
560 NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle");
567 /// Represents a method that is called when an response command completes.
569 /// <since_tizen> 5 </since_tizen>
570 protected override void OnResponseCompleted()
572 base.OnResponseCompleted();
574 if (_searchHandle != IntPtr.Zero)
576 NativeClient.DestroySearchHandle(_searchHandle).ThrowIfError("Failed to destroy search handle");