Release 4.0.0-preview1-00151
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / MediaController / MediaController.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.Diagnostics;
19 using Native = Interop.MediaControllerClient;
20
21 namespace Tizen.Multimedia.Remoting
22 {
23     /// <summary>
24     /// Provides a means to to send commands to and handle events from media control server.
25     /// </summary>
26     public class MediaController
27     {
28         internal MediaController(MediaControllerManager manager, string serverAppId)
29         {
30             Debug.Assert(manager != null);
31             Debug.Assert(serverAppId != null);
32
33             Manager = manager;
34             ServerAppId = serverAppId;
35         }
36
37         private MediaControllerManager Manager { get; }
38
39         /// <summary>
40         /// Gets the application id of the server.
41         /// </summary>
42         /// <value>The server application id.</value>
43         public string ServerAppId { get; }
44
45         /// <summary>
46         /// Gets a value indicating whether the sever has been stopped.
47         /// </summary>
48         /// <value>true if the server has been stopped; otherwise, false.</value>
49         public bool IsStopped
50         {
51             get;
52             private set;
53         }
54
55         private void ThrowIfStopped()
56         {
57             if (IsStopped)
58             {
59                 throw new InvalidOperationException("The server has already been stopped.");
60             }
61         }
62
63         /// <summary>
64         /// Occurs when the server is stopped.
65         /// </summary>
66         public event EventHandler ServerStopped;
67
68         internal void RaiseStoppedEvent()
69         {
70             IsStopped = true;
71             ServerStopped?.Invoke(this, EventArgs.Empty);
72         }
73
74         /// <summary>
75         /// Occurs when the playback state is updated.
76         /// </summary>
77         public event EventHandler<PlaybackStateUpdatedEventArgs> PlaybackStateUpdated;
78
79         private PlaybackStateUpdatedEventArgs CreatePlaybackUpdatedEventArgs(IntPtr playbackHandle)
80         {
81             try
82             {
83                 Native.GetPlaybackState(playbackHandle, out var playbackCode).ThrowIfError("Failed to get state.");
84
85                 Native.GetPlaybackPosition(playbackHandle, out var position).ThrowIfError("Failed to get position.");
86
87                 return new PlaybackStateUpdatedEventArgs(playbackCode.ToState(), (long)position);
88             }
89             catch (Exception e)
90             {
91                 Log.Error(GetType().FullName, e.ToString());
92             }
93             return null;
94         }
95
96         internal void RaisePlaybackUpdatedEvent(IntPtr playbackHandle)
97         {
98             var eventHandler = PlaybackStateUpdated;
99
100             if (eventHandler == null)
101             {
102                 return;
103             }
104
105             var args = CreatePlaybackUpdatedEventArgs(playbackHandle);
106
107             if (args != null)
108             {
109                 eventHandler.Invoke(this, args);
110             }
111         }
112
113         /// <summary>
114         /// Occurs when the metadata is updated.
115         /// </summary>
116         public event EventHandler<MetadataUpdatedEventArgs> MetadataUpdated;
117
118         private MetadataUpdatedEventArgs CreateMetadataUpdatedEventArgs(IntPtr metadataHandle)
119         {
120             try
121             {
122                 return new MetadataUpdatedEventArgs(new MediaControlMetadata(metadataHandle));
123             }
124             catch (Exception e)
125             {
126                 Log.Error(GetType().FullName, e.ToString());
127             }
128             return null;
129         }
130
131         internal void RaiseMetadataUpdatedEvent(IntPtr metadataHandle)
132         {
133             var eventHandler = MetadataUpdated;
134
135             if (eventHandler == null)
136             {
137                 return;
138             }
139
140             var args = CreateMetadataUpdatedEventArgs(metadataHandle);
141
142             if (args != null)
143             {
144                 eventHandler.Invoke(this, args);
145             }
146         }
147
148         /// <summary>
149         /// Occurs when the shuffle mode is updated.
150         /// </summary>
151         public event EventHandler<ShuffleModeUpdatedEventArgs> ShuffleModeUpdated;
152
153         internal void RaiseShuffleModeUpdatedEvent(MediaControllerShuffleMode mode)
154         {
155             ShuffleModeUpdated?.Invoke(this, new ShuffleModeUpdatedEventArgs(mode == MediaControllerShuffleMode.On));
156         }
157
158         /// <summary>
159         /// Occurs when the repeat mode is updated.
160         /// </summary>
161         public event EventHandler<RepeatModeUpdatedEventArgs> RepeatModeUpdated;
162
163         internal void RaiseRepeatModeUpdatedEvent(MediaControlRepeatMode mode)
164         {
165             RepeatModeUpdated?.Invoke(this, new RepeatModeUpdatedEventArgs(mode));
166         }
167
168         /// <summary>
169         /// Returns the playback state set by the server.
170         /// </summary>
171         /// <returns>The playback state.</returns>
172         /// <exception cref="InvalidOperationException">
173         ///     The server has already been stopped.
174         ///     -or-\n
175         ///     An internal error occurs.
176         /// </exception>
177         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed of.</exception>
178         /// <seealso cref="MediaControlServer.SetPlaybackState(MediaControlPlaybackState, long)"/>
179         public MediaControlPlaybackState GetPlaybackState()
180         {
181             ThrowIfStopped();
182
183             IntPtr playbackHandle = IntPtr.Zero;
184
185             try
186             {
187                 Native.GetServerPlayback(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
188
189                 Native.GetPlaybackState(playbackHandle, out var playbackCode).ThrowIfError("Failed to get state.");
190
191                 return playbackCode.ToState();
192             }
193             finally
194             {
195                 if (playbackHandle != IntPtr.Zero)
196                 {
197                     Native.DestroyPlayback(playbackHandle);
198                 }
199             }
200         }
201
202         /// <summary>
203         /// Returns the playback position set by the server.
204         /// </summary>
205         /// <returns>The playback position in milliseconds.</returns>
206         /// <exception cref="InvalidOperationException">
207         ///     The server has already been stopped.
208         ///     -or-\n
209         ///     An internal error occurs.
210         /// </exception>
211         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed of.</exception>
212         /// <seealso cref="MediaControlServer.SetPlaybackState(MediaControlPlaybackState, long)"/>
213         public long GetPlaybackPosition()
214         {
215             ThrowIfStopped();
216
217             IntPtr playbackHandle = IntPtr.Zero;
218
219             try
220             {
221                 Native.GetServerPlayback(Manager.Handle, ServerAppId, out playbackHandle).ThrowIfError("Failed to get playback.");
222
223                 Native.GetPlaybackPosition(playbackHandle, out var position).ThrowIfError("Failed to get position.");
224
225                 return (long)position;
226             }
227             finally
228             {
229                 if (playbackHandle != IntPtr.Zero)
230                 {
231                     Native.DestroyPlayback(playbackHandle);
232                 }
233             }
234         }
235
236         /// <summary>
237         /// Returns the metadata set by the server.
238         /// </summary>
239         /// <returns>The metadata.</returns>
240         /// <exception cref="InvalidOperationException">
241         ///     The server has already been stopped.
242         ///     -or-\n
243         ///     An internal error occurs.
244         /// </exception>
245         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed of.</exception>
246         /// <seealso cref="MediaControlServer.SetMetadata(MediaControlMetadata)"/>
247         public MediaControlMetadata GetMetadata()
248         {
249             ThrowIfStopped();
250
251             IntPtr metadataHandle = IntPtr.Zero;
252
253             try
254             {
255                 Native.GetServerMetadata(Manager.Handle, ServerAppId, out metadataHandle).
256                     ThrowIfError("Failed to get metadata.");
257
258                 return new MediaControlMetadata(metadataHandle);
259             }
260             finally
261             {
262                 if (metadataHandle != IntPtr.Zero)
263                 {
264                     Native.DestroyMetadata(metadataHandle);
265                 }
266             }
267         }
268
269         /// <summary>
270         /// Returns whether the shuffle mode is enabled.
271         /// </summary>
272         /// <returns>A value indicating whether the shuffle mode is enabled.</returns>
273         /// <exception cref="InvalidOperationException">
274         ///     The server has already been stopped.
275         ///     -or-\n
276         ///     An internal error occurs.
277         /// </exception>
278         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed of.</exception>
279         /// <seealso cref="MediaControlServer.SetShuffleModeEnabled(bool)"/>
280         public bool IsShuffleModeEnabled()
281         {
282             ThrowIfStopped();
283
284             Native.GetServerShuffleMode(Manager.Handle, ServerAppId, out var shuffleMode).
285                 ThrowIfError("Failed to get shuffle mode state.");
286
287             return shuffleMode == MediaControllerShuffleMode.On;
288         }
289
290         /// <summary>
291         /// Returns the repeat mode.
292         /// </summary>
293         /// <returns>A <see cref="MediaControlRepeatMode"/> set by the server.</returns>
294         /// <exception cref="InvalidOperationException">
295         ///     The server has already been stopped.
296         ///     -or-\n
297         ///     An internal error occurs.
298         /// </exception>
299         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed of.</exception>
300         /// <seealso cref="MediaControlServer.SetRepeatMode(MediaControlRepeatMode)"/>
301         public MediaControlRepeatMode GetRepeatMode()
302         {
303             ThrowIfStopped();
304
305             Native.GetServerRepeatMode(Manager.Handle, ServerAppId, out var repeatMode).
306                 ThrowIfError("Failed to get repeat mode state.");
307
308             return repeatMode.ToPublic();
309         }
310
311         /// <summary>
312         /// Sends playback command to the server.</summary>
313         /// <param name="command">A playback command.</param>
314         /// <exception cref="InvalidOperationException">
315         ///     The server has already been stopped.
316         ///     -or-\n
317         ///     An internal error occurs.
318         /// </exception>
319         /// <exception cref="ArgumentException"><paramref name="command"/> is not valid.</exception>
320         /// <exception cref="ObjectDisposedException">The <see cref="MediaControllerManager"/> has already been disposed of.</exception>
321         /// <seealso cref="MediaControlServer.PlaybackCommandReceived"/>
322         public void SendPlaybackCommand(MediaControlPlaybackCommand command)
323         {
324             ThrowIfStopped();
325
326             ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackCommand), command, nameof(command));
327
328             Native.SendPlaybackStateCommand(Manager.Handle, ServerAppId, command.ToCode()).
329                 ThrowIfError("Failed to send command.");
330         }
331     }
332 }