[ScreenMirroring] Redesigned apis
authorcoderhyme <jhyo.kim@samsung.com>
Fri, 9 Jun 2017 08:24:44 +0000 (17:24 +0900)
committercoderhyme <jhyo.kim@samsung.com>
Tue, 1 Aug 2017 23:33:40 +0000 (08:33 +0900)
Change-Id: Ifd3a36b850addea8154878d939de45a1a2237cb2
Signed-off-by: coderhyme <jhyo.kim@samsung.com>
13 files changed:
src/Tizen.Multimedia.Remoting/Interop/Interop.ScreenMirroring.cs
src/Tizen.Multimedia.Remoting/ScreenMirroring/AudioInformation.cs [deleted file]
src/Tizen.Multimedia.Remoting/ScreenMirroring/EventArgs.cs [new file with mode: 0644]
src/Tizen.Multimedia.Remoting/ScreenMirroring/InteropHelper.cs [new file with mode: 0644]
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroring.cs
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringAudioInfo.cs [new file with mode: 0644]
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringEnums.cs [moved from src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringEnumerations.cs with 55% similarity]
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringError.cs [new file with mode: 0644]
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringErrorFactory.cs [deleted file]
src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringVideoInfo.cs [new file with mode: 0644]
src/Tizen.Multimedia.Remoting/ScreenMirroring/StateChangedEventArgs.cs [deleted file]
src/Tizen.Multimedia.Remoting/ScreenMirroring/VideoInformation.cs [deleted file]
src/Tizen.Multimedia.Remoting/Tizen.Multimedia.Remoting.csproj

index 707a4c2..5c0a035 100644 (file)
 
 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);
     }
 }
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/AudioInformation.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/AudioInformation.cs
deleted file mode 100644 (file)
index a1d05a8..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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;
-            }
-        }
-    }
-}
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/EventArgs.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/EventArgs.cs
new file mode 100644 (file)
index 0000000..81332b1
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/InteropHelper.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/InteropHelper.cs
new file mode 100644 (file)
index 0000000..8e2a055
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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);
+        }
+    }
+}
index 63fee48..c81fcf3 100644 (file)
  * 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);
@@ -421,17 +437,16 @@ namespace Tizen.Multimedia
         }
 
         /// <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)
                 {
@@ -443,49 +458,76 @@ namespace Tizen.Multimedia
             }
         }
 
-        /// <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);
         }
     }
 }
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringAudioInfo.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringAudioInfo.cs
new file mode 100644 (file)
index 0000000..28adf75
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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
     }
 }
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringError.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringError.cs
new file mode 100644 (file)
index 0000000..805ca2a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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()}.");
+            }
+        }
+    }
+}
+
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringErrorFactory.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringErrorFactory.cs
deleted file mode 100644 (file)
index 01fc2a5..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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);
-            }
-        }
-    }
-}
-
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringVideoInfo.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/ScreenMirroringVideoInfo.cs
new file mode 100644 (file)
index 0000000..62d4625
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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;
+            }
+        }
+    }
+}
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/StateChangedEventArgs.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/StateChangedEventArgs.cs
deleted file mode 100644 (file)
index 7bf0c32..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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
diff --git a/src/Tizen.Multimedia.Remoting/ScreenMirroring/VideoInformation.cs b/src/Tizen.Multimedia.Remoting/ScreenMirroring/VideoInformation.cs
deleted file mode 100644 (file)
index 59f9a9c..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/// 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;
-            }
-        }
-    }
-}
index 6a9f436..3950881 100644 (file)
@@ -3,7 +3,7 @@
   <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>