/*
* Copyright (c) 2016 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 System;
using Native = Interop.MediaControllerServer;
namespace Tizen.Multimedia.Remoting
{
///
/// Provides a means to set playback information and metadata and receive commands from clients.
///
///
///
public static class MediaControlServer
{
private static IntPtr _handle = IntPtr.Zero;
private static bool? _isRunning;
///
/// Gets a value indicating whether the server is running.
///
/// true if the server has started; otherwise, false.
///
///
public static bool IsRunning
{
get
{
if (_isRunning.HasValue == false)
{
_isRunning = GetRunningState();
}
return _isRunning.Value;
}
}
private static bool GetRunningState()
{
IntPtr handle = IntPtr.Zero;
try
{
Native.ConnectDb(out handle).ThrowIfError("Failed to retrieve the running state.");
Native.CheckServerExist(handle, Applications.Application.Current.ApplicationInfo.ApplicationId,
out var value).ThrowIfError("Failed to retrieve the running state.");
return value;
}
finally
{
if (handle != IntPtr.Zero)
{
Native.DisconnectDb(handle);
}
}
}
private static void EnsureInitializedIfRunning()
{
if (_handle != IntPtr.Zero)
{
return;
}
if (IsRunning == false)
{
throw new InvalidOperationException("The server is not running.");
}
Initialize();
}
private static IntPtr Handle
{
get
{
EnsureInitializedIfRunning();
return _handle;
}
}
private static void Initialize()
{
Native.Create(out _handle).ThrowIfError("Failed to create media controller server.");
try
{
RegisterPlaybackCommandReceivedEvent();
_isRunning = true;
}
catch
{
Native.Destroy(_handle);
_playbackCommandCallback = null;
_handle = IntPtr.Zero;
throw;
}
}
///
/// Starts the media control server.
///
///
/// When the server starts, will be raised.
///
/// http://tizen.org/privilege/mediacontroller.server
/// An internal error occurs.
/// Caller does not have required privilege.
///
public static void Start()
{
Initialize();
}
///
/// Stops the media control server.
///
///
/// When the server stops, will be raised.
///
///
/// The server is not running .\n
/// -or-\n
/// An internal error occurs.
///
///
public static void Stop()
{
EnsureInitializedIfRunning();
Native.Destroy(_handle).ThrowIfError("Failed to stop the server.");
_handle = IntPtr.Zero;
_playbackCommandCallback = null;
_isRunning = false;
}
///
/// Updates playback state and playback position.
/// The playback state.
/// The playback position in milliseconds.
/// is not valid.
/// is less than zero.
///
/// The server is not running .\n
/// -or-\n
/// An internal error occurs.
///
public static void SetPlaybackState(MediaControlPlaybackState state, long position)
{
ValidationUtil.ValidateEnum(typeof(MediaControlPlaybackState), state, nameof(state));
if (position < 0)
{
throw new ArgumentOutOfRangeException(nameof(position), position, "position can't be less than zero.");
}
Native.SetPlaybackState(Handle, state.ToCode()).ThrowIfError("Failed to set playback state.");
Native.SetPlaybackPosition(Handle, (ulong)position).ThrowIfError("Failed to set playback position.");
Native.UpdatePlayback(Handle).ThrowIfError("Failed to set playback.");
}
private static void SetMetadata(MediaControllerAttribute attribute, string value)
{
Native.SetMetadata(Handle, attribute, value).ThrowIfError($"Failed to set metadata({attribute}).");
}
///
/// Updates metadata information.
///
/// The metadata to update.
/// is null.
///
/// The server is not running .\n
/// -or-\n
/// An internal error occurs.
///
public static void SetMetadata(MediaControlMetadata metadata)
{
if (metadata == null)
{
throw new ArgumentNullException(nameof(metadata));
}
SetMetadata(MediaControllerAttribute.Title, metadata.Title);
SetMetadata(MediaControllerAttribute.Artist, metadata.Artist);
SetMetadata(MediaControllerAttribute.Album, metadata.Album);
SetMetadata(MediaControllerAttribute.Author, metadata.Author);
SetMetadata(MediaControllerAttribute.Genre, metadata.Genre);
SetMetadata(MediaControllerAttribute.Duration, metadata.Duration);
SetMetadata(MediaControllerAttribute.Date, metadata.Date);
SetMetadata(MediaControllerAttribute.Copyright, metadata.Copyright);
SetMetadata(MediaControllerAttribute.Description, metadata.Description);
SetMetadata(MediaControllerAttribute.TrackNumber, metadata.TrackNumber);
SetMetadata(MediaControllerAttribute.Picture, metadata.AlbumArtPath);
Native.UpdateMetadata(Handle).ThrowIfError("Failed to set metadata.");
}
///
/// Updates the shuffle mode.
///
/// A value indicating whether the shuffle mode is enabled.
///
/// The server is not running .\n
/// -or-\n
/// An internal error occurs.
///
public static void SetShuffleModeEnabled(bool enabled)
{
Native.UpdateShuffleMode(Handle, enabled ? MediaControllerShuffleMode.On : MediaControllerShuffleMode.Off).
ThrowIfError("Failed to set shuffle mode.");
}
///
/// Updates the repeat mode.
///
/// A value indicating the repeat mode.
///
/// The server is not running .\n
/// -or-\n
/// An internal error occurs.
///
/// is invalid.
public static void SetRepeatMode(MediaControlRepeatMode mode)
{
ValidationUtil.ValidateEnum(typeof(MediaControlRepeatMode), mode, nameof(mode));
Native.UpdateRepeatMode(Handle, mode.ToNative()).ThrowIfError("Failed to set repeat mode.");
}
///
/// Occurs when a client sends playback command.
///
public static event EventHandler PlaybackCommandReceived;
private static Native.PlaybackStateCommandReceivedCallback _playbackCommandCallback;
private static void RegisterPlaybackCommandReceivedEvent()
{
_playbackCommandCallback = (clientName, playbackCode, _) =>
{
PlaybackCommandReceived?.Invoke(null, new PlaybackCommandReceivedEventArgs(clientName, playbackCode.ToCommand()));
};
Native.SetPlaybackStateCmdRecvCb(Handle, _playbackCommandCallback).
ThrowIfError("Failed to init PlaybackStateCommandReceived event."); ;
}
}
}