using System;
using System.Runtime.InteropServices;
+using Tizen.Multimedia;
internal static partial class Interop
{
internal static partial class ScreenMirroring
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- internal delegate void StateChangedCallback(IntPtr userData, int state, int error);
+ internal delegate void StateChangedCallback(IntPtr userData,
+ ScreenMirroringState state, ScreenMirroringErrorCode error);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_create")]
- internal static extern int Create(out IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode Create(out IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_state_changed_cb")]
- internal static extern int SetStateChangedCb(IntPtr scmirroringSink, StateChangedCallback cb, IntPtr userData);
+ internal static extern ScreenMirroringErrorCode SetStateChangedCb(IntPtr handle,
+ StateChangedCallback cb, IntPtr userData = default(IntPtr));
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_ip_and_port")]
- internal static extern int SetIpAndPort(IntPtr scmirroringSink, string ip, string port);
+ internal static extern ScreenMirroringErrorCode SetIpAndPort(IntPtr handle, string ip, string port);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_display")]
- internal static extern int SetDisplay(IntPtr scmirroringSink, int type, IntPtr display);
+ internal static extern ScreenMirroringErrorCode SetDisplay(IntPtr handle, int type, IntPtr display);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_resolution")]
- internal static extern int SetResolution(IntPtr scmirroringSink, int resolution);
+ internal static extern ScreenMirroringErrorCode SetResolution(IntPtr handle, ScreenMirroringResolutions resolution);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_prepare")]
- internal static extern int Prepare(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode Prepare(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_connect")]
- internal static extern int ConnectAsync(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode Connect(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_start")]
- internal static extern int StartAsync(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode StartAsync(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_pause")]
- internal static extern int PauseAsync(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode PauseAsync(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_resume")]
- internal static extern int ResumeAsync(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode ResumeAsync(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_disconnect")]
- internal static extern int Disconnect(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode Disconnect(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_unprepare")]
- internal static extern int Unprepare(IntPtr scmirroringSink);
+ internal static extern ScreenMirroringErrorCode Unprepare(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_unset_state_changed_cb")]
- internal static extern int UnsetStateChangedCb(IntPtr scmirroringSink);
+ internal static extern int UnsetStateChangedCb(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_destroy")]
- internal static extern int Destroy(IntPtr scmirroringSink);
+ internal static extern int Destroy(IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_video_codec")]
- internal static extern int GetNegotiatedVideoCodec(ref IntPtr scmirroringSink, out int codec);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedVideoCodec(ref IntPtr handle,
+ out ScreenMirroringVideoCodec codec);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_video_resolution")]
- internal static extern int GetNegotiatedVideoResolution(ref IntPtr scmirroringSink, out int width, out int height);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedVideoResolution(ref IntPtr handle,
+ out int width, out int height);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_video_frame_rate")]
- internal static extern int GetNegotiatedVideoFrameRate(ref IntPtr scmirroringSink, out int frameRate);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedVideoFrameRate(ref IntPtr handle,
+ out int frameRate);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_audio_codec")]
- internal static extern int GetNegotiatedAudioCodec(ref IntPtr scmirroringSink, out int codec);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedAudioCodec(ref IntPtr handle,
+ out ScreenMirroringAudioCodec codec);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_audio_channel")]
- internal static extern int GetNegotiatedAudioChannel(ref IntPtr scmirroringSink, out int channel);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedAudioChannel(ref IntPtr handle,
+ out int channel);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_audio_sample_rate")]
- internal static extern int GetNegotiatedAudioSampleRate(ref IntPtr scmirroringSink, out int sampleRate);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedAudioSampleRate(ref IntPtr handle,
+ out int sampleRate);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_audio_bitwidth")]
- internal static extern int GetNegotiatedAudioBitwidth(ref IntPtr scmirroringSink, out int bitwidth);
+ internal static extern ScreenMirroringErrorCode GetNegotiatedAudioBitwidth(ref IntPtr handle,
+ out int bitwidth);
}
}
+++ /dev/null
-/*
- * 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.ScreenMirroring;
-
-namespace Tizen.Multimedia
-{
- /// <summary>
- /// Audio Information class provides audio information which is negotiated with source device for screen mirroring. e.g codec
- /// </summary>
- /// <remarks>
- /// This class provides properties and API that are required for setting audio information.
- /// For getting property using this api, we should call it after connectAsync() api.
- /// </remarks>
- public class AudioInformation
- {
- internal IntPtr _handle;
- private int _codec;
- private int _channel;
- private int _sampleRate;
- private int _bitWidth;
-
- internal AudioInformation()
- {
- }
-
- /// <summary>
- /// Get audio codec.
- /// </summary>
- /// <value> Get audio codec which is one of enums in 'AudioCodec' which is negotiaged with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public AudioCodec Codec
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedAudioCodec(ref _handle, out _codec);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get audio codec" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get audio codec");
- }
-
- return (AudioCodec)_codec;
- }
- }
-
- /// <summary>
- /// Get audio channel.
- /// </summary>
- /// <value> Get audio channel property of audio information which is negotiated with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public int Channel
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedAudioChannel(ref _handle, out _channel);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get audio channel" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get audio channel");
- }
-
- return _channel;
- }
- }
-
- /// <summary>
- /// Get audio sample rate.
- /// </summary>
- /// <value> Get audio sample rate property which is negotiated with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public int SampleRate
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedAudioSampleRate(ref _handle, out _sampleRate);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get audio sample rate" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get audio sample rate");
- }
-
- return _sampleRate;
- }
- }
-
- /// <summary>
- /// Get audio bitwidth.
- /// </summary>
- /// <value> Get audio bitwidth property which is negotiated with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public int BitWidth
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedAudioBitwidth(ref _handle, out _bitWidth);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get audio bitwidth" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get audio bitwidth");
- }
-
- return _bitWidth;
- }
- }
- }
-}
--- /dev/null
+/*
+ * 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;
+
+namespace Tizen.Multimedia
+{
+ /// <summary>
+ /// Provides data for the <see cref="ScreenMirroring.StateChanged"/> event.
+ /// </summary>
+ public class ScreenMirroringStateChangedEventArgs : EventArgs
+ {
+ internal ScreenMirroringStateChangedEventArgs(ScreenMirroringState state)
+ {
+ State = state;
+ }
+
+ /// <summary>
+ /// Gets the current state of screen mirroring.
+ /// </summary>
+ public ScreenMirroringState State { get; }
+ }
+
+ /// <summary>
+ /// Provides data for the <see cref="ScreenMirroring.ErrorOccurred"/> event.
+ /// </summary>
+ public class ScreenMirroringErrorOccurredEventArgs : EventArgs
+ {
+ internal ScreenMirroringErrorOccurredEventArgs(ScreenMirroringError error)
+ {
+ Error = error;
+ }
+
+ /// <summary>
+ /// Gets the error that occurred.
+ /// </summary>
+ public ScreenMirroringError Error { get; }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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;
+
+namespace Tizen.Multimedia
+{
+ internal static class InteropHelper
+ {
+ internal delegate ScreenMirroringErrorCode GetFunc<T>(ref IntPtr handle, out T value);
+
+ internal static ScreenMirroringErrorCode GetValue<T>(GetFunc<T> func, IntPtr handle, out T value)
+ {
+ return func(ref handle, out value);
+ }
+ }
+}
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
using System;
using System.Diagnostics;
+using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using Native = Interop.ScreenMirroring;
namespace Tizen.Multimedia
{
- static internal class ScreenMirroringLog
- {
- internal const string LogTag = "Tizen.Multimedia.ScreenMirroring";
- }
-
/// <summary>
- /// ScreenMirroring class provides methods to function as screen mirroring application as sink.
- /// It gives the ability to connect to and disconnect from a screen mirroring source, and
- /// start, pause, and resume the screen mirroring sink, set the resolution or display,
- /// register state change callback function.
+ /// Provides the ability to connect to and disconnect from a screen mirroring source,
+ /// start, pause, and resume the screen mirroring as a sink.
/// </summary>
- public class ScreenMirroring : IDisposable, IDisplayable<int>
+ public class ScreenMirroring : IDisposable, IDisplayable<ScreenMirroringErrorCode>
{
- internal VideoInformation _videoInfo;
- internal AudioInformation _audioInfo;
- internal IntPtr _handle;
- internal string _ip;
- internal string _port;
+ private const string LogTag = "Tizen.Multimedia.ScreenMirroring";
+
+ private const int Port = 2022;
+
+ private ScreenMirroringVideoInfo _videoInfo;
+ private ScreenMirroringAudioInfo _audioInfo;
+ private IntPtr _handle;
+
+ private AtomicState _state;
private bool _disposed = false;
- private EventHandler<StateChangedEventArgs> _stateChanged;
- private Native.StateChangedCallback _stateChangedCallback;
- /// <summary>
- /// Initializes a new instance of the ScreenMirroring class with parameters Ip, Port and Display handle.
- /// Object should be created only when Ip and Port are available.
- /// Create(i.e constructor) api will create a new handle with the given parameters.
- /// </summary>
- /// <param name="display">Display.</param>
- /// <param name="ip">Ip.</param>
- /// <param name="port">Port.</param>
- /// <exception cref="ArgumentException">Thrown when method fail due to an invalid parameter</exception>
- public ScreenMirroring(Display display, string ip, string port)
+ internal IntPtr Handle
{
- int ret = Native.Create(out _handle);
- if (ret != (int)ScreenMirroringError.None)
+ get
{
- ScreenMirroringErrorFactory.ThrowException(ret, "Failed to create Screen Mirroring Sink");
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(nameof(ScreenMirroring));
+ }
+
+ return _handle;
}
+ }
- // initiate values
- _ip = ip;
- _port = port;
+ /// <summary>
+ /// Initializes a new instance of the ScreenMirroring class.
+ /// </summary>
+ /// <feature>http://tizen.org/feature/network.wifi.direct.display</feature>
+ /// <exception cref="NotSupportedException">The feature is not supported.</exception>
+ public ScreenMirroring()
+ {
+ Native.Create(out _handle).ThrowIfError("Failed to create ScreenMirroring.");
- // Set ip and port
- int ret1 = Native.SetIpAndPort(_handle, _ip, _port);
- if (ret1 != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Set ip and port failed" + (ScreenMirroringError)ret1);
- ScreenMirroringErrorFactory.ThrowException(ret, "set ip and port failed");
- }
+ _state = new AtomicState();
- Display = display;
+ _audioInfo = new ScreenMirroringAudioInfo(this);
+ _videoInfo = new ScreenMirroringVideoInfo(this);
- // AudioInfo
- _audioInfo = new AudioInformation();
- _audioInfo._handle = _handle;
- // VideoInfo
- _videoInfo = new VideoInformation();
- _videoInfo._handle = _handle;
+ RegisterStateChangedEvent();
- Log.Debug(ScreenMirroringLog.LogTag, "screen mirroring sink created : " + _handle);
+ Log.Debug(LogTag, "screen mirroring sink created : " + _handle);
}
- /// <summary>
- /// Screen Mirroring destructor.
- /// </summary>
~ScreenMirroring()
{
Dispose(false);
}
/// <summary>
- /// StateChanged event is raised when state change happens.
- /// Must be called after Create() API.
+ /// Occurs when the state is changed.
/// </summary>
- public event EventHandler<StateChangedEventArgs> StateChanged
- {
- add
- {
- if (_stateChanged == null)
- {
- RegisterStateChangedEvent();
- }
-
- _stateChanged += value;
- }
-
- remove
- {
- _stateChanged -= value;
- if (_stateChanged == null)
- {
- UnregisterStateChangedEvent();
- }
- }
- }
+ public event EventHandler<ScreenMirroringStateChangedEventArgs> StateChanged;
/// <summary>
- /// Sets the server ip and port.
- /// This must be called before connect() and after create().
+ /// Occurs when an error occurs.
/// </summary>
- /// <example> If only one handle is used for toggling between more than two source devices,
- /// then this API ahould be used to assign the parameters to the handle.
- /// </example>
- /// <param name="ip">Ip.</param>
- /// <param name="port">Port.</param>
- /// <exception cref="ArgumentException">Thrown when method fail due to an invalid parameter</exception>
- public void SetIpAndPort(string ip, string port)
+ public event EventHandler<ScreenMirroringErrorOccurredEventArgs> ErrorOccurred;
+
+ #region Display support
+
+ private Display _display;
+
+ private void DetachDisplay()
{
- int ret = Native.SetIpAndPort(_handle, ip, port);
- if (ret != (int)ScreenMirroringError.None)
+ if (_display != null)
{
- Log.Error(ScreenMirroringLog.LogTag, "Set ip and port failed" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "set ip and port failed");
+ _display.SetOwner(null);
+ _display = null;
}
}
- /// <summary>
- /// Set Resolution.
- /// valid state: NULL..
- /// </summary>
- /// <param name="resolution"> example: (R1920x1080P30 | R1280x720P30) </param>
- /// <exception cref="ArgumentException">Thrown when method fail due to an invalid parameter</exception>
- public void SetResolution(ResolutionType resolution)
+ private void SetDisplay(Display display)
{
- int ret = Native.SetResolution(_handle, (int)resolution);
- if (ret != (int)ScreenMirroringError.None)
+ if (display == null)
{
- Log.Error(ScreenMirroringLog.LogTag, "Set resolution failed" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "set resolution failed");
+ throw new ArgumentNullException(nameof(Display));
}
- }
- private Display _display;
+ display.SetOwner(this);
+ display.ApplyTo(this).ThrowIfError("Failed to set display.");
- private int ApplyDisplay(Display display)
- {
- return display.ApplyTo(this);
+ _display = display;
}
- private void ReplaceDisplay(Display newDisplay)
+ ScreenMirroringErrorCode IDisplayable<ScreenMirroringErrorCode>.ApplyEvasDisplay(DisplayType type,
+ ElmSharp.EvasObject evasObject)
{
- _display?.SetOwner(null);
- _display = newDisplay;
- _display?.SetOwner(this);
+ Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
+
+ return Native.SetDisplay(Handle, (int)type, evasObject);
}
+ #endregion
/// <summary>
- /// Sets the display.
- /// This must be called before prepare() and after create().
+ /// Gets the negotiated audio info.
/// </summary>
- /// <example> If only one handle is used for toggling between more than two source devices,
- /// then this API should be used to assign the parameters to the handle.
- /// </example>
- /// <exception cref="ArgumentException">Thrown when method fail due to an invalid parameter</exception>
- public Display Display
+ /// <value>The <see cref="ScreenMirroringAudioInfo"/> if it has been connected, otherwise null.</value>
+ public ScreenMirroringAudioInfo AudioInfo
{
get
{
- return _display;
- }
- set
- {
- if (value == null)
+ if (IsConnected == false)
{
- throw new ArgumentNullException(nameof(Display));
+ return null;
}
- int ret = ApplyDisplay(value);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Set display failed" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "set display failed");
- }
+ return _audioInfo;
}
}
- int IDisplayable<int>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
+ /// <summary>
+ /// Gets the negotiated video info.
+ /// </summary>
+ /// <value>The <see cref="ScreenMirroringVideoInfo"/> if it has been connected, otherwise null.</value>
+ public ScreenMirroringVideoInfo VideoInfo
{
- Debug.Assert(_disposed == false);
-
- Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
+ get
+ {
+ if (IsConnected == false)
+ {
+ return null;
+ }
- return Native.SetDisplay(_handle, (int)type, evasObject);
+ return _videoInfo;
+ }
}
- /// <summary>
- /// Prepare this instance.
- /// This must be called after Create().
- /// </summary>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public void Prepare()
+ private bool IsConnected
{
- int ret = Native.Prepare(_handle);
- if (ret != (int)ScreenMirroringError.None)
+ get
{
- ScreenMirroringErrorFactory.ThrowException(ret, "Failed to prepare sink for screen mirroring");
+ return _state.IsOneOf(ScreenMirroringState.Connected, ScreenMirroringState.Playing,
+ ScreenMirroringState.Paused);
}
}
/// <summary>
- /// Creates connection and prepare for receiving data from ScreenMirroring source.
- /// This must be called after prepare().
+ /// Prepares the screen mirroring with the specified display.
/// </summary>
- /// <remarks> It will not give the current state. Need to subscribe for event to get the current state </remarks>
- /// <returns>bool value</returns>
- /// <privilege>http://tizen.org/privilege/internet</privilege>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public Task<bool> ConnectAsync()
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Idle"/>.\n
+ /// \n
+ /// All supported resolutions will be candidates.
+ /// </remarks>
+ /// <param name="display">The display where the mirroring will be played on.</param>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="display"/> has already been assigned to another.
+ /// </exception>
+ /// <exception cref="ArgumentNullException"><paramref name="display"/> is null.</exception>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public void Prepare(Display display)
{
- int ret = Native.ConnectAsync(_handle);
- var task = new TaskCompletionSource<bool>();
-
- Task.Factory.StartNew(() =>
- {
- if (ret == (int)ScreenMirroringError.None)
- {
- task.SetResult(true);
- }
-
- else if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to start screen mirroring" + (ScreenMirroringError)ret);
- InvalidOperationException e = new InvalidOperationException("Operation Failed");
- task.TrySetException(e);
- }
- });
-
- return task.Task;
+ PrepareCore(display, (ScreenMirroringResolutions)0);
}
/// <summary>
- /// Get AudioInfo.
- /// This must be called after connectasync().
- /// valid states: connected/playback/paused.
- /// If audio file changes during playback again
- /// then the current info should be retrieved from the audio information class.
+ /// Prepares the screen mirroring with the specified display and resolutions.
/// </summary>
- /// <value> AudioInfo object </value>
- public AudioInformation AudioInfo
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Idle"/>.
+ /// </remarks>
+ /// <param name="display">The display where the mirroring will be played on.</param>
+ /// <param name="resolutions">The desired resolutions.</param>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="resolutions"/> contain invalid flags.\n
+ /// -or-\n
+ /// <paramref name="display"/> has already been assigned to another.
+ /// </exception>
+ /// <exception cref="ArgumentNullException"><paramref name="display"/> is null.</exception>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public void Prepare(Display display, ScreenMirroringResolutions resolutions)
{
- get
+ ValidationUtil.ValidateFlagsEnum(resolutions, (ScreenMirroringResolutions)((1 << 7) - 1), nameof(resolutions));
+
+ PrepareCore(display, resolutions);
+ }
+
+ private void PrepareCore(Display display, ScreenMirroringResolutions resolutions)
+ {
+ ValidateState(ScreenMirroringState.Idle);
+
+ Native.SetResolution(Handle, resolutions).ThrowIfError("Failed to set resolutions.");
+
+ try
{
- return _audioInfo;
+ SetDisplay(display);
+
+ Native.Prepare(Handle).ThrowIfError("Failed to prepare.");
+ }
+ catch
+ {
+ DetachDisplay();
+ throw;
}
}
/// <summary>
- /// Get VideoInfo.
- /// This must be called after connectasync().
- /// valid states: connected/playback/paused.
- /// If video file changes during playback again
- /// then the current info should be retrieved from the video information class.
+ /// Creates the connection and ready for receiving data from a mirroring source.
/// </summary>
- /// <value> VideoInfo object </value>
- public VideoInformation VideoInfo
+ /// <param name="sourceIp">The source ip address to connect.</param>
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Prepared"/> state by
+ /// <see cref="Prepare(Display, ScreenMirroringResolutions)"/>.
+ /// </remarks>
+ /// <returns>A task that represents the asynchronous operation.</returns>
+ /// <privilege>http://tizen.org/privilege/internet</privilege>
+ /// <exception cref="ArgumentNullException"><paramref name="sourceIp"/> is null.</exception>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ArgumentException"><paramref name="sourceIp"/> is a zero-length string, contains only white space.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ /// <exception cref="UnauthorizedAccessException">Caller does not have required permission.</exception>
+ public Task ConnectAsync(string sourceIp)
{
- get
+ if (sourceIp == null)
{
- return _videoInfo;
+ throw new ArgumentNullException(nameof(sourceIp));
}
+
+ if (string.IsNullOrWhiteSpace(sourceIp))
+ {
+ throw new ArgumentException($"{nameof(sourceIp)} is a zero-length string.", nameof(sourceIp));
+ }
+
+ ValidateState(ScreenMirroringState.Prepared);
+
+ Native.SetIpAndPort(Handle, sourceIp, Port.ToString()).ThrowIfError("Failed to set ip.");
+
+ var tcs = new TaskCompletionSource<bool>();
+
+ Task.Factory.StartNew(() =>
+ {
+ Native.Connect(Handle).ThrowIfError("Failed to connect");
+ tcs.SetResult(true);
+ });
+
+ return tcs.Task;
}
/// <summary>
- /// Start receiving data from the ScreenMirroring source and display it(Mirror).
- /// This must be called after connectasync().
- /// </summary>
- /// <remarks> It will not give the current state. Need to subscribe for event to get the current state </remarks>
- /// <returns>bool value<returns>
+ /// Starts mirroring from the source.
+ /// </summary>
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Connected"/> state by
+ /// <see cref="ConnectAsync(string)"/>.
+ /// </remarks>
+ /// <returns>A task that represents the asynchronous operation.</returns>
/// <privilege>http://tizen.org/privilege/internet</privilege>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public Task<bool> StartAsync()
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ /// <exception cref="UnauthorizedAccessException">Caller does not have required permission.</exception>
+ public Task StartAsync()
{
- int ret = Native.StartAsync(_handle);
- var task = new TaskCompletionSource<bool>();
+ ValidateState(ScreenMirroringState.Connected);
+
+ var tcs = new TaskCompletionSource<bool>();
Task.Factory.StartNew(() =>
- {
- if (ret == (int)ScreenMirroringError.None)
- {
- task.SetResult(true);
- }
-
- else if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to start screen mirroring" + (ScreenMirroringError)ret);
- InvalidOperationException e = new InvalidOperationException("Operation Failed");
- task.TrySetException(e);
- }
- });
-
- return task.Task;
+ {
+ Native.StartAsync(Handle).ThrowIfError("Failed to start.");
+ tcs.TrySetResult(true);
+ });
+
+ return tcs.Task;
}
/// <summary>
- /// Pauses receiving data from the ScreenMirroring source.
- /// This must be called after startasync().
+ /// Pauses mirroring from the source.
/// </summary>
- /// <remarks> It will not give the current state. Need to subscribe for event to get the current state </remarks>
- /// <returns>bool value</returns>
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Playing"/> state by
+ /// <see cref="StartAsync"/>.
+ /// </remarks>
+ /// <returns>A task that represents the asynchronous operation.</returns>
/// <privilege>http://tizen.org/privilege/internet</privilege>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public Task<bool> PauseAsync()
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ /// <exception cref="UnauthorizedAccessException">Caller does not have required permission.</exception>
+ public Task PauseAsync()
{
- int ret = Native.PauseAsync(_handle);
- var task = new TaskCompletionSource<bool>();
+ ValidateState(ScreenMirroringState.Playing);
+
+ var tcs = new TaskCompletionSource<bool>();
Task.Factory.StartNew(() =>
- {
- if (ret == (int)ScreenMirroringError.None)
- {
- task.SetResult(true);
- }
-
- else if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to start screen mirroring" + (ScreenMirroringError)ret);
- InvalidOperationException e = new InvalidOperationException("Operation Failed");
- task.TrySetException(e);
- }
- });
-
- return task.Task;
+ {
+ Native.PauseAsync(Handle).ThrowIfError("Failed to prepare.");
+ tcs.TrySetResult(true);
+ });
+
+ return tcs.Task;
}
/// <summary>
- /// Resumes receiving data from the ScreenMirroring source.
- /// This must be called after pauseasync().
+ /// Resumes mirroring from the source.
/// </summary>
- /// <remarks> It will not give the current state. Need to subscribe for event to get the current state </remarks>
- /// <returns>bool value</returns>
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Paused"/> state by
+ /// <see cref="PauseAsync"/>.
+ /// </remarks>
+ /// <returns>A task that represents the asynchronous operation.</returns>
/// <privilege>http://tizen.org/privilege/internet</privilege>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public Task<bool> ResumeAsync()
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ /// <exception cref="UnauthorizedAccessException">Caller does not have required permission.</exception>
+ public Task ResumeAsync()
{
- int ret = Native.ResumeAsync(_handle);
- var task = new TaskCompletionSource<bool>();
+ ValidateState(ScreenMirroringState.Paused);
+
+ var tcs = new TaskCompletionSource<bool>();
Task.Factory.StartNew(() =>
- {
- if (ret == (int)ScreenMirroringError.None)
- {
- task.SetResult(true);
- }
-
- else if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to start screen mirroring" + (ScreenMirroringError)ret);
- InvalidOperationException e = new InvalidOperationException("Operation Failed");
- task.TrySetException(e);
- }
- });
-
- return task.Task;
+ {
+ Native.ResumeAsync(Handle).ThrowIfError("Failed to resume.");
+ tcs.TrySetResult(true);
+ });
+
+ return tcs.Task;
}
/// <summary>
- /// Disconnect this instance.
- /// valid states: connected/playing/paused
+ /// Disconnects from the source.
/// </summary>
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Connected"/>,
+ /// <see cref="ScreenMirroringState.Playing"/> or <see cref="ScreenMirroringState.Paused"/>.
+ /// </remarks>
/// <privilege>http://tizen.org/privilege/internet</privilege>
- /// <exception cref="ArgumentException">Thrown when method fail due to no connection between devices</exception>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ /// <exception cref="UnauthorizedAccessException">Caller does not have required permission.</exception>
public void Disconnect()
{
- int ret = Native.Disconnect(_handle);
- if (ret != (int)ScreenMirroringError.None)
- {
- ScreenMirroringErrorFactory.ThrowException(ret, "Failed to disconnect sink for screen mirroring");
- }
+ ValidateState(ScreenMirroringState.Connected, ScreenMirroringState.Playing,
+ ScreenMirroringState.Paused);
+
+ Native.Disconnect(Handle).ThrowIfError("Failed to disconnect.");
}
/// <summary>
- /// Unprepare this instance.
- /// valid states: prepared/disconnected.
+ /// Unprepares the screen mirroring.
/// </summary>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
+ /// <remarks>
+ /// The state must be <see cref="ScreenMirroringState.Prepared"/>,
+ /// or <see cref="ScreenMirroringState.Disconnected"/>.
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.\n
+ /// -or-\n
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
public void Unprepare()
{
- int ret = Native.Unprepare(_handle);
- if (ret != (int)ScreenMirroringError.None)
- {
- ScreenMirroringErrorFactory.ThrowException(ret, "Failed to reset the screen mirroring sink");
- }
+ ValidateState(ScreenMirroringState.Prepared, ScreenMirroringState.Disconnected);
+
+ Native.Unprepare(Handle).ThrowIfError("Failed to reset.");
+
+ DetachDisplay();
}
/// <summary>
- /// Releases all resource used by the <see cref="Tizen.Multimedia.ScreenMirroring"/> object.
+ /// Releases all resource used by the <see cref="ScreenMirroring"/> object.
/// </summary>
- /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="Tizen.Multimedia.ScreenMirroring"/>.
- /// The <see cref="Dispose"/> method leaves the <see cref="Tizen.Multimedia.ScreenMirroring"/> in an unusable
- /// state. After calling <see cref="Dispose"/>, you must release all references to the
- /// <see cref="Tizen.Multimedia.ScreenMirroring"/> so the garbage collector can reclaim the memory that the
- /// <see cref="Tizen.Multimedia.ScreenMirroring"/> was occupying.</remarks>
+ /// <remarks>
+ /// Call <see cref="Dispose()"/> when you are finished using the <see cref="ScreenMirroring"/>.
+ /// The <see cref="Dispose()"/> method leaves the <see cref="ScreenMirroring"/> in an unusable
+ /// state. After calling <see cref="Dispose"()/>, you must release all references to the
+ /// <see cref="ScreenMirroring"/> so the garbage collector can reclaim the memory that the
+ /// <see cref="ScreenMirroring"/> was occupying.
+ /// </remarks>
public void Dispose()
{
Dispose(true);
}
/// <summary>
- /// Dispose the specified handle.
+ /// Releases the resources used by the ScreenMirroring.
/// </summary>
- /// <param name="disposing">If set to <c>true</c> disposing.</param>
+ /// <param name="disposing">
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ /// </param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
- if (disposing)
- {
- // To be used if there are any other disposable objects
- }
+ DetachDisplay();
if (_handle != IntPtr.Zero)
{
}
}
- /// <summary>
- /// Invoke the event for state or error.
- /// </summary>
- /// <param name="state"> state </param>
- /// <param name="error"> error </param>
- private void StateError(int state, int error)
- {
- ///if _stateChanged is subscribe, this will be invoke.
- StateChangedEventArgs eventArgsState = new StateChangedEventArgs(state, error);
- _stateChanged?.Invoke(this, eventArgsState);
- }
+ private Native.StateChangedCallback _stateChangedCallback;
- /// <summary>
- /// Registers the state changed event.
- /// </summary>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
private void RegisterStateChangedEvent()
{
- _stateChangedCallback = (IntPtr userData, int state, int error) =>
+ _stateChangedCallback = (_, state, error) =>
+ {
+ var prevState = _state.Value;
+
+ _state.Value = state;
+
+ if (prevState != state)
{
- StateError(state, error);
- };
+ StateChanged?.Invoke(this, new ScreenMirroringStateChangedEventArgs(state));
+
+ }
+
+ if (error != ScreenMirroringErrorCode.None)
+ {
+ ErrorOccurred?.Invoke(this, new ScreenMirroringErrorOccurredEventArgs(
+ ScreenMirroringError.InvalidOperation));
+ }
+ };
+
+ Native.SetStateChangedCb(Handle, _stateChangedCallback).
+ ThrowIfError("Failed to initialize StateChanged event.");
+ }
+
+ private void ValidateState(params ScreenMirroringState[] required)
+ {
+ Debug.Assert(required.Length > 0);
- int ret = Native.SetStateChangedCb(_handle, _stateChangedCallback, IntPtr.Zero);
- if (ret != (int)ScreenMirroringError.None)
+ if (_disposed)
{
- Log.Error(ScreenMirroringLog.LogTag, "Setting StateChanged callback failed" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "Setting StateChanged callback failed");
+ throw new ObjectDisposedException(nameof(ScreenMirroring));
+ }
+
+ var curState = _state.Value;
+ if (!required.Contains(curState))
+ {
+ throw new InvalidOperationException($"The screen mirroring is not in a valid state. " +
+ $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
}
}
- /// <summary>
- /// Unregisters the state changed event.
- /// </summary>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- private void UnregisterStateChangedEvent()
+ }
+
+ internal class AtomicState
+ {
+ private int _value;
+
+ public AtomicState()
{
- int ret = Native.UnsetStateChangedCb(_handle);
- if (ret != (int)ScreenMirroringError.None)
+ _value = (int)ScreenMirroringState.Idle;
+ }
+
+ public ScreenMirroringState Value
+ {
+ get
{
- Log.Error(ScreenMirroringLog.LogTag, "Unsetting StateChnaged callback failed" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "Unsetting StateChanged callback failed");
+ return (ScreenMirroringState)Interlocked.CompareExchange(ref _value, 0, 0);
}
+ set
+ {
+ Interlocked.Exchange(ref _value, (int)value);
+ }
+ }
+
+ public bool IsOneOf(params ScreenMirroringState[] states)
+ {
+ return states.Contains(Value);
}
}
}
--- /dev/null
+/*
+ * 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 static Tizen.Multimedia.InteropHelper;
+using Native = Interop.ScreenMirroring;
+
+namespace Tizen.Multimedia
+{
+ /// <summary>
+ /// Provides a means to retrieve the audio information which is negotiated with the source device.
+ /// </summary>
+ /// <seealso cref="ScreenMirroring"/>
+ public class ScreenMirroringAudioInfo
+ {
+ private readonly ScreenMirroring _owner;
+
+ internal ScreenMirroringAudioInfo(ScreenMirroring owner)
+ {
+ _owner = owner;
+ }
+
+ /// <summary>
+ /// Gets the negotiated audio codec.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public ScreenMirroringAudioCodec Codec
+ {
+ get
+ {
+ GetValue(Native.GetNegotiatedAudioCodec, _owner.Handle, out ScreenMirroringAudioCodec value).
+ ThrowIfError("Failed to get audio codec.");
+
+ return value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the negotiated audio channels.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public int Channels
+ {
+ get
+ {
+ GetValue(Native.GetNegotiatedAudioChannel, _owner.Handle, out int value).
+ ThrowIfError("Failed to get audio channels.");
+
+ return value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the negotiated audio sample rate.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public int SampleRate
+ {
+ get
+ {
+ GetValue(Native.GetNegotiatedAudioSampleRate, _owner.Handle, out int value).
+ ThrowIfError("Failed to get audio sample rate.");
+
+ return value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the negotiated audio bit width.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public int BitWidth
+ {
+ get
+ {
+ GetValue(Native.GetNegotiatedAudioBitwidth, _owner.Handle, out int value).
+ ThrowIfError("Failed to get audio bit width.");
+
+ return value;
+ }
+ }
+ }
+}
* limitations under the License.
*/
+using System;
+
namespace Tizen.Multimedia
{
/// <summary>
- /// Enumeration for audio codec.
+ /// Specifies audio codecs for <see cref="ScreenMirroring"/>.
/// </summary>
- public enum AudioCodec
+ /// <seealso cref="ScreenMirroringAudioInfo"/>
+ public enum ScreenMirroringAudioCodec
{
/// <summary>
- /// Screen mirroring is not negotiated yet
+ /// Screen mirroring is not negotiated yet.
/// </summary>
None,
/// <summary>
- /// AAC codec for audio
+ /// AAC codec for audio.
/// </summary>
Aac,
/// <summary>
- /// AC3 codec for audio
+ /// AC3 codec for audio.
/// </summary>
Ac3,
/// <summary>
- /// LPCM codec for audio
+ /// LPCM codec for audio.
/// </summary>
Lpcm
}
+
/// <summary>
- /// Enumeration for video codec.
+ /// Specifies video codecs for <see cref="ScreenMirroring"/>.
/// </summary>
- public enum VideoCodec
+ /// <seealso cref="ScreenMirroringVideoInfo"/>
+ public enum ScreenMirroringVideoCodec
{
/// <summary>
- /// Screen mirroring is not negotiated yet
+ /// Screen mirroring is not negotiated yet.
/// </summary>
None,
/// <summary>
- /// H.264 codec for video
+ /// H.264 codec for video.
/// </summary>
H264
}
/// <summary>
- /// Enumeration for screen mirroring resolution.
+ /// Specifies available combinations of resolutions and fps for <see cref="ScreenMirroring"/>.
/// </summary>
- public enum ResolutionType
+ [Flags]
+ public enum ScreenMirroringResolutions
{
/// <summary>
- /// W-1920, H-1080, 30 fps
+ /// W-1920, H-1080, 30 fps.
/// </summary>
R1920x1080P30 = (1 << 0),
/// <summary>
- /// W-1280, H-720, 30 fps
+ /// W-1280, H-720, 30 fps.
/// </summary>
R1280x720P30 = (1 << 1),
/// <summary>
- /// W-960, H-540, 30 fps
+ /// W-960, H-540, 30 fps.
/// </summary>
R960x540P30 = (1 << 2),
/// <summary>
- /// W-864, H-480, 30 fps
+ /// W-864, H-480, 30 fps.
/// </summary>
R864x480P30 = (1 << 3),
/// <summary>
- /// W-720, H-480, 60 fps
+ /// W-720, H-480, 60 fps.
/// </summary>
R720x480P60 = (1 << 4),
/// <summary>
- /// W-640, H-480, 60 fps
+ /// W-640, H-480, 60 fps.
/// </summary>
R640x480P60 = (1 << 5),
/// <summary>
- /// W-640, H-360, 30 fps
+ /// W-640, H-360, 30 fps.
/// </summary>
R640x360P30 = (1 << 6)
}
/// <summary>
- /// Enumeration for screen mirroring sink state
+ /// Specifies the states of <see cref="ScreenMirroring"/>.
/// </summary>
- public enum ScreenMirroringSinkState
+ public enum ScreenMirroringState
{
/// <summary>
- /// Screen mirroring is not created yet
- /// </summary>
- None,
- /// <summary>
- /// Screen mirroring is created, but not prepared yet
+ /// Idle.
/// </summary>
- Null,
+ Idle = 1,
+
/// <summary>
- /// Screen mirroring is prepared to play media
+ /// Prepared.
/// </summary>
+ /// <seealso cref="ScreenMirroring.Prepare(Display, ScreenMirroringResolutions)"/>
Prepared,
+
/// <summary>
- /// Screen mirroring is connected
+ /// Connected to a source.
/// </summary>
+ /// <seealso cref="ScreenMirroring.ConnectAsync(string)"/>
Connected,
+
/// <summary>
- /// Screen mirroring is now playing media
+ /// Playing.
/// </summary>
+ /// <seealso cref="ScreenMirroring.StartAsync"/>
Playing,
+
/// <summary>
- /// Screen mirroring is paused while playing media
+ /// Paused while playing media.
/// </summary>
+ /// <seealso cref="ScreenMirroring.PauseAsync"/>
Paused,
+
/// <summary>
- /// Screen mirroring is disconnected
+ /// Disconnected from source.
/// </summary>
+ /// <seealso cref="ScreenMirroring.Disconnect"/>
Disconnected
}
/// <summary>
- /// Enumeration for screen mirroring error.
+ /// Specifies errors for <see cref="ScreenMirroring"/>.
/// </summary>
- public enum ScreenMirroringErrorCode
+ public enum ScreenMirroringError
{
/// <summary>
- /// Successful
- /// </summary>
- None = ScreenMirroringError.None,
- /// <summary>
- /// Invalid operation
+ /// Invalid operation.
/// </summary>
- InvalidOperation = ScreenMirroringError.InvalidOperation
+ InvalidOperation = ScreenMirroringErrorCode.InvalidOperation
}
}
--- /dev/null
+/*
+ * 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 Tizen.Internals.Errors;
+
+namespace Tizen.Multimedia
+{
+ internal enum ScreenMirroringErrorCode
+ {
+ None = ErrorCode.None,
+ InvalidParameter = ErrorCode.InvalidParameter,
+ OutOfMemory = ErrorCode.OutOfMemory,
+ InvalidOperation = ErrorCode.InvalidOperation,
+ ConnectionTimeOut = ErrorCode.ConnectionTimeout,
+ PermissionDenied = ErrorCode.PermissionDenied,
+ NotSupported = ErrorCode.NotSupported,
+ Unknown = ErrorCode.Unknown
+ }
+
+ internal static class ScreenMirroringErrorExtensions
+ {
+ internal static void ThrowIfError(this ScreenMirroringErrorCode err, string message)
+ {
+ if (err == ScreenMirroringErrorCode.None)
+ {
+ return;
+ }
+
+ switch (err)
+ {
+ case ScreenMirroringErrorCode.InvalidParameter:
+ throw new ArgumentException(message);
+
+ case ScreenMirroringErrorCode.OutOfMemory:
+ throw new OutOfMemoryException(message);
+
+ case ScreenMirroringErrorCode.PermissionDenied:
+ throw new UnauthorizedAccessException(message);
+
+ case ScreenMirroringErrorCode.NotSupported:
+ throw new NotSupportedException(message);
+
+ case ScreenMirroringErrorCode.InvalidOperation:
+ throw new InvalidOperationException(message);
+
+ case ScreenMirroringErrorCode.ConnectionTimeOut:
+ throw new TimeoutException(message);
+
+ default:
+ throw new InvalidOperationException($"Unknown error : {err.ToString()}.");
+ }
+ }
+ }
+}
+
+++ /dev/null
-/*
- * 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 Tizen.Internals.Errors;
-namespace Tizen.Multimedia
-{
- internal enum ScreenMirroringError
- {
- None = ErrorCode.None,
- InvalidParameter = ErrorCode.InvalidParameter,
- OutOfMemory = ErrorCode.OutOfMemory,
- InvalidOperation = ErrorCode.InvalidOperation,
- ConnectionTimeOut = ErrorCode.ConnectionTimeout,
- PermissionDenied = ErrorCode.PermissionDenied,
- NotSupported = ErrorCode.NotSupported,
- Unknown = ErrorCode.Unknown
- };
- internal static class ScreenMirroringErrorFactory
- {
- private const string LogTag = "Tizen.Multimedia.ScreenMirroring";
- internal static void ThrowException(int errorCode, string errorMessage = null)
- {
- ScreenMirroringError err = (ScreenMirroringError)errorCode;
-
- if (err == ScreenMirroringError.None)
- {
- return;
- }
-
- Log.Error(LogTag,"errorCode is : " + errorCode);
- if (string.IsNullOrEmpty(errorMessage))
- {
- errorMessage = err.ToString();
- }
-
- switch (err)
- {
- case ScreenMirroringError.InvalidParameter:
- throw new ArgumentException(errorMessage);
-
- case ScreenMirroringError.OutOfMemory:
- throw new OutOfMemoryException(errorMessage);
-
- case ScreenMirroringError.PermissionDenied:
- throw new UnauthorizedAccessException(errorMessage);
-
- case ScreenMirroringError.NotSupported:
- throw new NotSupportedException(errorMessage);
-
- case ScreenMirroringError.ConnectionTimeOut:
- case ScreenMirroringError.InvalidOperation:
- throw new InvalidOperationException(errorMessage);
-
- default:
- throw new Exception("Unknown error : " + errorCode);
- }
- }
- }
-}
-
--- /dev/null
+/*
+ * 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 static Tizen.Multimedia.InteropHelper;
+using Native = Interop.ScreenMirroring;
+
+namespace Tizen.Multimedia
+{
+ /// <summary>
+ /// Provides a means to retrieve the video information which is negotiated with the source device.
+ /// </summary>
+ public class ScreenMirroringVideoInfo
+ {
+ private readonly ScreenMirroring _owner;
+
+ internal ScreenMirroringVideoInfo(ScreenMirroring owner)
+ {
+ _owner = owner;
+ }
+
+ /// <summary>
+ /// Gets the negotiated video codec.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public ScreenMirroringVideoCodec Codec
+ {
+ get
+ {
+ GetValue(Native.GetNegotiatedVideoCodec, _owner.Handle, out ScreenMirroringVideoCodec value).
+ ThrowIfError("Failed to get video codec.");
+
+ return value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the negotiated video resolution.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public Size Resolution
+ {
+ get
+ {
+ var handle = _owner.Handle;
+ Native.GetNegotiatedVideoResolution(ref handle, out var width, out var height).
+ ThrowIfError("Failed to get resolution.");
+
+ return new Size(width, height);
+ }
+ }
+
+ /// <summary>
+ /// Gets the negotiated video frame rate.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ public int FrameRate
+ {
+ get
+ {
+ GetValue(Native.GetNegotiatedVideoFrameRate, _owner.Handle, out int value).
+ ThrowIfError("Failed to get video frame rate.");
+
+ return value;
+ }
+ }
+ }
+}
+++ /dev/null
-/*
- * 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;
-
-namespace Tizen.Multimedia
-{
- /// <summary>
- /// Get value of changed state. It provides getting state values which are returned when state is changed.
- /// </summary>
- /// <remarks>
- /// Return error and state code.
- /// </remarks>
- public class StateChangedEventArgs : EventArgs
- {
- internal int _state;
- internal int _error;
-
- /// <summary>
- /// Constructor.
- /// </summary>
- /// <param name="state"> State Changed </param>
- /// <param name="error"> Error Occurred </param>
- internal StateChangedEventArgs(int state, int error)
- {
- _state = state;
- _error = error;
- }
-
- /// <summary>
- /// Get the error code of screen mirroring.
- /// </summary>
- /// <value> Get the error code which is one of enums in 'ScreenMirroringErrorCode' when screen mirroring error is occurred.</value>
- public ScreenMirroringErrorCode Error
- {
- get
- {
- return (ScreenMirroringErrorCode)_error;
- }
- }
-
- /// <summary>
- /// Get the current state of screen mirroring.
- /// </summary>
- /// <value> Get state code which is one of enums in 'ScreenMirroringSinkState' when screen mirroring state is changed. </value>
- public ScreenMirroringSinkState State
- {
- get
- {
- return (ScreenMirroringSinkState)_state;
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/// Video Information
-/*
- * 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.ScreenMirroring;
-
-namespace Tizen.Multimedia
-{
- /// <summary>
- /// Video Information class provides video information which is negotiated with source device for screen mirroring. e.g codec
- /// </summary>
- /// <remarks>
- /// This class provides properties and API that are required for setting video information.
- /// For getting property using this api, we should call it after connectAsync() api.
- /// </remarks>
- public class VideoInformation
- {
- internal IntPtr _handle;
- private int _codec;
- private int _height;
- private int _width;
- private int _frameRate;
-
- internal VideoInformation()
- {
- }
-
- /// <summary>
- /// Get video codec.
- /// </summary>
- /// <value> Get video codec which is one of enums in 'VideoCodec' which is negotiaged with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public VideoCodec Codec
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedVideoCodec(ref _handle, out _codec);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get video codec" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get video codec");
- }
-
- return (VideoCodec)_codec;
- }
- }
-
- /// <summary>
- /// Get height of video resolution.
- /// </summary>
- /// <value> Get height property of video resolution which is negotiated with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public int Height
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedVideoResolution(ref _handle, out _width, out _height);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get height" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get video height");
- }
-
- return _height;
- }
- }
-
- /// <summary>
- /// Get width of video.
- /// </summary>
- /// <value> Get width property of video resolution which is negotiated with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public int Width
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedVideoResolution(ref _handle, out _width, out _height);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get width" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get video width");
- }
-
- return _width;
- }
- }
-
- /// <summary>
- /// Get video frame rate.
- /// </summary>
- /// <value> Get video frame rate property which is negotiated with source device. </value>
- /// <exception cref="InvalidOperationException">Thrown when method fail due to an internal error</exception>
- public int FrameRate
- {
- get
- {
- int ret;
- ret = Native.GetNegotiatedVideoFrameRate(ref _handle, out _frameRate);
- if (ret != (int)ScreenMirroringError.None)
- {
- Log.Error(ScreenMirroringLog.LogTag, "Failed to get frame rate" + (ScreenMirroringError)ret);
- ScreenMirroringErrorFactory.ThrowException(ret, "failed to get video frame rate");
- }
-
- return _frameRate;
- }
- }
- }
-}
<Import Project="../build/build.props" />
<PropertyGroup>
- <Version>1.0.0</Version>
+ <Version>1.0.1</Version>
<Description>Provides the Multimedia Remoting API(MediaController, ScreenMirroring) for Tizen .NET</Description>
</PropertyGroup>