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 Native = Interop.MediaControllerServer;
20 namespace Tizen.Multimedia.Remoting
23 /// Provides a means to set playback information and metadata and receive commands from clients.
25 /// <seealso cref="MediaControllerManager"/>
26 /// <seealso cref="MediaController"/>
27 /// <since_tizen> 4 </since_tizen>
28 public static class MediaControlServer
30 private static IntPtr _handle = IntPtr.Zero;
31 private static bool? _isRunning;
34 /// Gets a value indicating whether the server is running.
36 /// <value>true if the server has started; otherwise, false.</value>
37 /// <seealso cref="Start"/>
38 /// <seealso cref="Stop"/>
39 /// <since_tizen> 4 </since_tizen>
40 public static bool IsRunning
44 if (_isRunning.HasValue == false)
46 _isRunning = GetRunningState();
49 return _isRunning.Value;
53 private static bool GetRunningState()
55 IntPtr handle = IntPtr.Zero;
58 Native.ConnectDb(out handle).ThrowIfError("Failed to retrieve the running state.");
60 Native.CheckServerExist(handle, Applications.Application.Current.ApplicationInfo.ApplicationId,
61 out var value).ThrowIfError("Failed to retrieve the running state.");
67 if (handle != IntPtr.Zero)
69 Native.DisconnectDb(handle);
74 private static void EnsureInitializedIfRunning()
76 if (_handle != IntPtr.Zero)
81 if (IsRunning == false)
83 throw new InvalidOperationException("The server is not running.");
89 private static IntPtr Handle
93 EnsureInitializedIfRunning();
99 private static void Initialize()
101 Native.Create(out _handle).ThrowIfError("Failed to create media controller server.");
105 RegisterPlaybackCommandReceivedEvent();
110 Native.Destroy(_handle);
111 _playbackCommandCallback = null;
112 _handle = IntPtr.Zero;
118 /// Starts the media control server.
121 /// When the server starts, <see cref="MediaControllerManager.ServerStarted"/> will be raised.
123 /// <privilege>http://tizen.org/privilege/mediacontroller.server</privilege>
124 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
125 /// <exception cref="UnauthorizedAccessException">Caller does not have required privilege.</exception>
126 /// <seealso cref="MediaControllerManager.ServerStarted"/>
127 /// <since_tizen> 4 </since_tizen>
128 public static void Start()
134 /// Stops the media control server.
137 /// When the server stops, <see cref="MediaControllerManager.ServerStopped"/> will be raised.
139 /// <exception cref="InvalidOperationException">
140 /// The server is not running .<br/>
142 /// An internal error occurs.
144 /// <seealso cref="MediaControllerManager.ServerStopped"/>
145 /// <since_tizen> 4 </since_tizen>
146 public static void Stop()
148 EnsureInitializedIfRunning();
150 Native.Destroy(_handle).ThrowIfError("Failed to stop the server.");
152 _handle = IntPtr.Zero;
153 _playbackCommandCallback = null;
158 /// Updates playback state and playback position.</summary>
159 /// <param name="state">The playback state.</param>
160 /// <param name="position">The playback position in milliseconds.</param>
161 /// <exception cref="ArgumentException"><paramref name="state"/> is not valid.</exception>
162 /// <exception cref="ArgumentOutOfRangeException"><paramref name="position"/> is less than zero.</exception>
163 /// <exception cref="InvalidOperationException">
164 /// The server is not running .<br/>
166 /// An internal error occurs.
168 /// <since_tizen> 4 </since_tizen>
169 public static void SetPlaybackState(MediaControlPlaybackState state, long position)
171 ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackState), state, nameof(state));
175 throw new ArgumentOutOfRangeException(nameof(position), position, "position can't be less than zero.");
178 Native.SetPlaybackState(Handle, state.ToCode()).ThrowIfError("Failed to set playback state.");
180 Native.SetPlaybackPosition(Handle, (ulong)position).ThrowIfError("Failed to set playback position.");
182 Native.UpdatePlayback(Handle).ThrowIfError("Failed to set playback.");
185 private static void SetMetadata(MediaControllerAttribute attribute, string value)
187 Native.SetMetadata(Handle, attribute, value).ThrowIfError($"Failed to set metadata({attribute}).");
191 /// Updates metadata information.
193 /// <param name="metadata">The metadata to update.</param>
194 /// <exception cref="ArgumentNullException"><paramref name="metadata"/> is null.</exception>
195 /// <exception cref="InvalidOperationException">
196 /// The server is not running .<br/>
198 /// An internal error occurs.
200 /// <since_tizen> 4 </since_tizen>
201 public static void SetMetadata(MediaControlMetadata metadata)
203 if (metadata == null)
205 throw new ArgumentNullException(nameof(metadata));
208 SetMetadata(MediaControllerAttribute.Title, metadata.Title);
209 SetMetadata(MediaControllerAttribute.Artist, metadata.Artist);
210 SetMetadata(MediaControllerAttribute.Album, metadata.Album);
211 SetMetadata(MediaControllerAttribute.Author, metadata.Author);
212 SetMetadata(MediaControllerAttribute.Genre, metadata.Genre);
213 SetMetadata(MediaControllerAttribute.Duration, metadata.Duration);
214 SetMetadata(MediaControllerAttribute.Date, metadata.Date);
215 SetMetadata(MediaControllerAttribute.Copyright, metadata.Copyright);
216 SetMetadata(MediaControllerAttribute.Description, metadata.Description);
217 SetMetadata(MediaControllerAttribute.TrackNumber, metadata.TrackNumber);
218 SetMetadata(MediaControllerAttribute.Picture, metadata.AlbumArtPath);
220 Native.UpdateMetadata(Handle).ThrowIfError("Failed to set metadata.");
224 /// Updates the shuffle mode.
226 /// <param name="enabled">A value indicating whether the shuffle mode is enabled.</param>
227 /// <exception cref="InvalidOperationException">
228 /// The server is not running .<br/>
230 /// An internal error occurs.
232 /// <since_tizen> 4 </since_tizen>
233 public static void SetShuffleModeEnabled(bool enabled)
235 Native.UpdateShuffleMode(Handle, enabled ? MediaControllerShuffleMode.On : MediaControllerShuffleMode.Off).
236 ThrowIfError("Failed to set shuffle mode.");
240 /// Updates the repeat mode.
242 /// <param name="mode">A value indicating the repeat mode.</param>
243 /// <exception cref="InvalidOperationException">
244 /// The server is not running .<br/>
246 /// An internal error occurs.
248 /// <exception cref="ArgumentException"><paramref name="mode"/> is invalid.</exception>
249 /// <since_tizen> 4 </since_tizen>
250 public static void SetRepeatMode(MediaControlRepeatMode mode)
252 ValidationUtil.ValidateEnum(typeof(MediaControlRepeatMode), mode, nameof(mode));
254 Native.UpdateRepeatMode(Handle, mode.ToNative()).ThrowIfError("Failed to set repeat mode.");
258 /// Occurs when a client sends playback command.
260 /// <since_tizen> 4 </since_tizen>
261 public static event EventHandler<PlaybackCommandReceivedEventArgs> PlaybackCommandReceived;
263 private static Native.PlaybackStateCommandReceivedCallback _playbackCommandCallback;
265 private static void RegisterPlaybackCommandReceivedEvent()
267 _playbackCommandCallback = (clientName, playbackCode, _) =>
269 PlaybackCommandReceived?.Invoke(null, new PlaybackCommandReceivedEventArgs(clientName, playbackCode.ToCommand()));
271 Native.SetPlaybackStateCmdRecvCb(Handle, _playbackCommandCallback).
272 ThrowIfError("Failed to init PlaybackStateCommandReceived event."); ;