using System;
using System.Drawing;
using System.Runtime.InteropServices;
+using Tizen.Internals;
using Tizen.Multimedia;
using Tizen.Multimedia.Remoting;
internal delegate void StateChangedCallback(ScreenMirroringErrorCode error,
ScreenMirroringState state, IntPtr userData);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void SrcDisplayOrientationReceivedCallback(ScreenMirroringDisplayOrientation orientation, IntPtr userData);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate void UibcInfoReceivedCallback(ScreenMirroringErrorCode error, IntPtr info, IntPtr userData);
+
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_create")]
internal static extern ScreenMirroringErrorCode Create(out IntPtr handle);
[DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_get_negotiated_audio_bitwidth")]
internal static extern ScreenMirroringErrorCode GetNegotiatedAudioBitwidth(ref IntPtr handle,
out int bitwidth);
+
+ // UIBC
+ [DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_src_display_orientation_notify_cb")]
+ internal static extern ScreenMirroringErrorCode SetSrcDisplayOrientationChangedCb(IntPtr handle,
+ SrcDisplayOrientationReceivedCallback callback, IntPtr userData = default);
+
+ [DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_uibc_info_received_cb")]
+ internal static extern ScreenMirroringErrorCode SetUibcInfoReceivedCb(IntPtr handle,
+ UibcInfoReceivedCallback callback, IntPtr userData = default);
+
+ [DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_set_window_size")]
+ internal static extern ScreenMirroringErrorCode SetWindowSize(IntPtr handle, int width, int height);
+
+ [DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_enable_uibc")]
+ internal static extern ScreenMirroringErrorCode EnableUibc(IntPtr handle, ScreenMirroringCaptureMode mode);
+
+ [DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_send_generic_mouse_event")]
+ internal static extern ScreenMirroringErrorCode SendGenericMouseEvent(IntPtr handle, IntPtr uibcEvent);
+
+ [DllImport(Libraries.ScreenMirroring, EntryPoint = "scmirroring_sink_send_generic_key_event")]
+ internal static extern ScreenMirroringErrorCode SendGenericKeyEvent(IntPtr handle, ScreenMirroringKeyEventType type, ushort keyCode1, ushort keyCode2);
+
+ [NativeStruct("scmirroring_uibc_input_s", Include = "scmirroring_type_internal.h", PkgConfig = "capi-media-screen-mirroring")]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct UibcInput
+ {
+ internal ScreenMirroringUibcInputType type;
+ internal ScreenMirroringUibcInputPath path;
+ }
+
+ [NativeStruct("scmirroring_uibc_info_s", Include = "scmirroring_type_internal.h", PkgConfig = "capi-media-screen-mirroring")]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct UibcInfo
+ {
+ internal string Ip;
+ internal uint Port;
+ internal uint GenCapability;
+ internal int Width;
+ internal int Height;
+ internal IntPtr hidcCapsList;
+ internal uint hidcCapsSize;
+ }
+
+ [NativeStruct("scmirroring_uibc_mouse_s", Include = "scmirroring_type_internal.h", PkgConfig = "capi-media-screen-mirroring")]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct UibcMouse
+ {
+ internal ushort id;
+ internal ushort x;
+ internal ushort y;
+ }
+
+ [NativeStruct("scmirroring_uibc_mouse_event_s", Include = "scmirroring_type_internal.h", PkgConfig = "capi-media-screen-mirroring")]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct UibcMouseEvent
+ {
+ internal int size;
+ internal ScreenMirroringMouseEventType type;
+ internal IntPtr uibcMouse;
+ }
}
}
*/
using System;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.InteropServices;
+using Native = Interop.ScreenMirroring;
namespace Tizen.Multimedia.Remoting
{
/// <since_tizen> 4 </since_tizen>
public ScreenMirroringError Error { get; }
}
-}
\ No newline at end of file
+
+ /// <summary>
+ /// Provides data for the <see cref="ScreenMirroring.DisplayOrientationChanged"/> event.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class ScreenMirroringDisplayOrientationChangedEventArgs : EventArgs
+ {
+ internal ScreenMirroringDisplayOrientationChangedEventArgs(ScreenMirroringDisplayOrientation orientation)
+ {
+ Orientation = orientation;
+ }
+
+ /// <summary>
+ /// Gets the display orientation of source.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ScreenMirroringDisplayOrientation Orientation { get; }
+ }
+
+ /// <summary>
+ /// Provides data for the <see cref="ScreenMirroring.UibcInfoReceived"/> event.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public class ScreenMirroringUibcInfoReceivedEventArgs : EventArgs
+ {
+ internal ScreenMirroringUibcInfoReceivedEventArgs(ScreenMirroringError error, IntPtr uibcInfo)
+ {
+ var unmanagedStruct = Marshal.PtrToStructure<Native.UibcInfo>(uibcInfo);
+
+ Error = error;
+ Ip = unmanagedStruct.Ip;
+ Port = unmanagedStruct.Port;
+ GenCapability = unmanagedStruct.GenCapability;
+ Resolution = new Size(unmanagedStruct.Width, unmanagedStruct.Height);
+ HidcCapabilities = GetUibcInputs(unmanagedStruct.hidcCapsList, unmanagedStruct.hidcCapsSize);
+ }
+
+ private ReadOnlyCollection<UibcInputs> GetUibcInputs(IntPtr unmanagedIntPtr, uint hidcCapsSize)
+ {
+ var size = Marshal.SizeOf(typeof(Native.UibcInput));
+ var unmanagedStruct = new Native.UibcInput[hidcCapsSize];
+ IntPtr unmanagedUibcInput;
+
+ for (int i = 0; i < hidcCapsSize; i++)
+ {
+ if (IntPtr.Size == 4)
+ {
+ unmanagedUibcInput = new IntPtr(unmanagedIntPtr.ToInt32() + i * size);
+ }
+ else
+ {
+ unmanagedUibcInput = new IntPtr(unmanagedIntPtr.ToInt64() + i * size);
+ }
+
+ unmanagedStruct[i] = Marshal.PtrToStructure<Native.UibcInput>(unmanagedUibcInput);
+ }
+
+ var hidcList = new List<UibcInputs>();
+ for (int i = 0; i < hidcCapsSize; i++)
+ {
+ hidcList.Add(new UibcInputs(unmanagedStruct[i].type, unmanagedStruct[i].path));
+ }
+
+ return new ReadOnlyCollection<UibcInputs>(hidcList);
+ }
+
+ /// <summary>
+ /// Gets the error that occurred.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ScreenMirroringError Error { get; }
+
+ /// <summary>
+ /// Gets the IP address
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public string Ip { get; }
+
+ /// <summary>
+ /// Gets the port number
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint Port { get; }
+
+ /// <summary>
+ /// Gets the gen capability
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public uint GenCapability { get; }
+
+ /// <summary>
+ /// Gets the resolution of window
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Size Resolution { get; }
+
+ /// <summary>
+ /// Gets the HIDC(Human Interface Device Command) capabilities
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ReadOnlyCollection<UibcInputs> HidcCapabilities { get; }
+ }
+}
*/
using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
+using System.Threading.Tasks.Dataflow;
+using Microsoft.VisualBasic;
using Native = Interop.ScreenMirroring;
namespace Tizen.Multimedia.Remoting
private bool _disposed = false;
+ private Native.StateChangedCallback _stateChangedCallback;
+ private Native.SrcDisplayOrientationReceivedCallback _displayOrientationReceivedCallback;
+ private Native.UibcInfoReceivedCallback _uibcInfoReceivedCallback;
+
internal IntPtr Handle
{
get
VideoInfo = new ScreenMirroringVideoInfo(this);
RegisterStateChangedEvent();
+ RegisterDisplayOrientationChangedEvent();
+ RegisterUibcInfoReceivedEvent();
}
/// <summary>
/// <since_tizen> 4 </since_tizen>
public event EventHandler<ScreenMirroringErrorOccurredEventArgs> ErrorOccurred;
+ /// <summary>
+ /// Occurs when the display orientation of source is changed.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public event EventHandler<ScreenMirroringDisplayOrientationChangedEventArgs> DisplayOrientationChanged;
+
+ /// <summary>
+ /// Occurs when the UIBC information is received from source.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public event EventHandler<ScreenMirroringUibcInfoReceivedEventArgs> UibcInfoReceived;
+
#region Display support
private Display _display;
DetachDisplay();
}
+ /// <summary>
+ /// Sets the information for UIBC(User Input Back Channel).
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.<br/>
+ /// -or-<br/>
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SetUibcInformation(Size windowSize, ScreenMirroringCaptureMode mode)
+ {
+ ValidateState(ScreenMirroringState.Idle);
+
+ Native.SetWindowSize(Handle, windowSize.Width, windowSize.Height).ThrowIfError("Failed to set uibc window size");
+ Native.EnableUibc(Handle, mode).ThrowIfError("Failed to set uibc capture mode");
+ }
+
+ /// <summary>
+ /// Sends mouse event for UIBC(User Input Back Channel).
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The current state is not in the valid.<br/>
+ /// -or-<br/>
+ /// An internal error occurs.
+ /// </exception>
+ /// <exception cref="ArgumentNullException"><paramref name="uibcMouseInfos"/> is null.</exception>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SendGenericMouseEvent(IEnumerable<UibcMouseInfo> uibcMouseInfos, ScreenMirroringMouseEventType type)
+ {
+ ValidateState(ScreenMirroringState.Connected);
+
+ if (!uibcMouseInfos.Any())
+ {
+ throw new ArgumentNullException(nameof(uibcMouseInfos));
+ }
+
+ var uibcMouseInfosSize = uibcMouseInfos.Count();
+ var uibcMouse = new Native.UibcMouse[uibcMouseInfosSize];
+ int i = 0;
+ IntPtr unmanagedUibcMousePtr;
+
+ foreach (var uibcMouseInfo in uibcMouseInfos)
+ {
+ uibcMouse[i].id = uibcMouseInfo.Id;
+ uibcMouse[i].x = uibcMouseInfo.X;
+ uibcMouse[i++].y = uibcMouseInfo.Y;
+ }
+
+ var size = Marshal.SizeOf(typeof(Native.UibcMouse));
+ IntPtr unmanagedUibcMouse = Marshal.AllocHGlobal(size * uibcMouseInfosSize);
+ for (i = 0; i < uibcMouseInfosSize; i++)
+ {
+ if (IntPtr.Size == 4)
+ {
+ unmanagedUibcMousePtr = new IntPtr(unmanagedUibcMouse.ToInt32() + i * size);
+ }
+ else
+ {
+ unmanagedUibcMousePtr = new IntPtr(unmanagedUibcMouse.ToInt64() + i * size);
+ }
+ Marshal.StructureToPtr(uibcMouse[i], unmanagedUibcMousePtr, false);
+ }
+
+ Native.UibcMouseEvent uibcObject;
+ uibcObject.size = uibcMouseInfosSize;
+ uibcObject.type = type;
+ uibcObject.uibcMouse = unmanagedUibcMouse;
+
+ var unmanagedUibcObject = Marshal.AllocHGlobal(Marshal.SizeOf(uibcObject));
+ Marshal.StructureToPtr(uibcObject, unmanagedUibcObject, false);
+
+ try
+ {
+ Native.SendGenericMouseEvent(Handle, unmanagedUibcObject).ThrowIfError("Failed to send generic mouse event");
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(unmanagedUibcMouse);
+ Marshal.FreeHGlobal(unmanagedUibcObject);
+ }
+ }
+
+ /// <summary>
+ /// Sends key event for UIBC(User Input Back Channel).
+ /// </summary>
+ /// <exception cref="ObjectDisposedException">The <see cref="ScreenMirroring"/> has already been disposed.</exception>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SendGenericKeyEvent(ScreenMirroringKeyEventType type, ushort keyCode1, ushort keyCode2)
+ {
+ ValidateState(ScreenMirroringState.Connected);
+
+ Native.SendGenericKeyEvent(Handle, type, keyCode1, keyCode2).ThrowIfError("Failed to send generic key event");
+ }
+
private void ThrowIfDisposed()
{
if (_disposed)
}
}
- private Native.StateChangedCallback _stateChangedCallback;
-
private void RegisterStateChangedEvent()
{
_stateChangedCallback = (error, state, _) =>
ThrowIfError("Failed to initialize StateChanged event.");
}
+ private void RegisterDisplayOrientationChangedEvent()
+ {
+ _displayOrientationReceivedCallback = (orientation, _) =>
+ {
+ DisplayOrientationChanged?.Invoke(this, new ScreenMirroringDisplayOrientationChangedEventArgs(orientation));
+ };
+
+ Native.SetSrcDisplayOrientationChangedCb(Handle, _displayOrientationReceivedCallback).
+ ThrowIfError("Failed to initialize DisplayOrientationChanged event.");
+ }
+
+ private void RegisterUibcInfoReceivedEvent()
+ {
+ _uibcInfoReceivedCallback = (error, uibcInfo, _) =>
+ {
+ UibcInfoReceived?.Invoke(this, new ScreenMirroringUibcInfoReceivedEventArgs(error.ToCsharp(), uibcInfo));
+ };
+
+ Native.SetUibcInfoReceivedCb(Handle, _uibcInfoReceivedCallback).
+ ThrowIfError("Failed to initialize UibcInfoReceived event.");
+ }
+
private void ValidateState(params ScreenMirroringState[] required)
{
Debug.Assert(required.Length > 0);
if (!required.Contains(curState))
{
throw new InvalidOperationException($"The screen mirroring is not in a valid state. " +
- $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
+ $"Current State : {curState}, Valid State : {string.Join(", ", required)}.");
}
}
-
}
internal class AtomicState
*/
using System;
+using System.ComponentModel;
namespace Tizen.Multimedia.Remoting
{
/// </summary>
Mobile
}
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) display orientation for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ScreenMirroringDisplayOrientation
+ {
+ /// <summary>
+ /// None
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// Portrait display
+ /// </summary>
+ PortraitDisplay,
+
+ /// <summary>
+ /// Portrait
+ /// </summary>
+ Portrait,
+
+ /// <summary>
+ /// Landscape
+ /// </summary>
+ Landscape
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) input type for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ScreenMirroringUibcInputType
+ {
+ /// <summary>
+ /// Unknown
+ /// </summary>
+ Unknown,
+
+ /// <summary>
+ /// Keyboard
+ /// </summary>
+ Keyboard = (1 << 0),
+
+ /// <summary>
+ /// Mouse
+ /// </summary>
+ Mouse = (1 << 1),
+
+ /// <summary>
+ /// Single touch
+ /// </summary>
+ SingleTouch = (1 << 2),
+
+ /// <summary>
+ /// Multi touch
+ /// </summary>
+ MultiTouch = (1 << 3),
+
+ /// <summary>
+ /// Joystick
+ /// </summary>
+ Joystick = (1 << 4),
+
+ /// <summary>
+ /// Camera
+ /// </summary>
+ Camera = (1 << 5),
+
+ /// <summary>
+ /// Gesture
+ /// </summary>
+ Gesture = (1 << 6),
+
+ /// <summary>
+ /// Remote control
+ /// </summary>
+ RemoteControl = (1 << 7),
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) input path for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ScreenMirroringUibcInputPath
+ {
+ /// <summary>
+ /// Unknown
+ /// </summary>
+ Unknown,
+
+ /// <summary>
+ /// Infrared
+ /// </summary>
+ Infrared = (1 << 0),
+
+ /// <summary>
+ /// Usb
+ /// </summary>
+ Usb = (1 << 1),
+
+ /// <summary>
+ /// Bluetooth
+ /// </summary>
+ Bt = (1 << 2),
+
+ /// <summary>
+ /// Zigbee
+ /// </summary>
+ Zigbee = (1 << 3),
+
+ /// <summary>
+ /// Wifi
+ /// </summary>
+ Wifi = (1 << 4),
+
+ /// <summary>
+ /// Nosp
+ /// </summary>
+ Nosp = (1 << 5),
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) capture mode for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ScreenMirroringCaptureMode
+ {
+ /// <summary>
+ /// Application
+ /// </summary>
+ Application,
+
+ /// <summary>
+ /// Raw interface
+ /// </summary>
+ RawInterface
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) mouse event type for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ScreenMirroringMouseEventType
+ {
+ /// <summary>
+ /// Left button is pressed
+ /// </summary>
+ LeftButtonPressed,
+
+ /// <summary>
+ /// Left button is released
+ /// </summary>
+ LeftButtonReleased,
+
+ /// <summary>
+ /// Mouse is moved
+ /// </summary>
+ Move
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) key event type for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum ScreenMirroringKeyEventType
+ {
+ /// <summary>
+ /// Key is pressed
+ /// </summary>
+ KeyPressed,
+
+ /// <summary>
+ /// Key is released
+ /// </summary>
+ KeyReleased
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) inputs for <see cref="ScreenMirroring"/>.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public readonly struct UibcInputs
+ {
+ internal UibcInputs(ScreenMirroringUibcInputType type, ScreenMirroringUibcInputPath path)
+ {
+ Type = type;
+ Path = path;
+ }
+
+ /// <summary>
+ /// Gets the type of UIBC input.
+ /// </summary>
+ /// <value>The UIBC input type</value>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ScreenMirroringUibcInputType Type { get; }
+
+ /// <summary>
+ /// Gets the path of UIBC input.
+ /// </summary>
+ /// <value>The UIBC input path</value>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ScreenMirroringUibcInputPath Path { get; }
+ }
+
+ /// <summary>
+ /// Specifies the UIBC(User Input Back Channel) mount event.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public struct UibcMouseInfo
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UibcMouseInfo"/> class.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public UibcMouseInfo(ushort id, ushort x, ushort y)
+ {
+ Id = id;
+ X = x;
+ Y = y;
+ }
+
+ /// <summary>
+ /// Gets the ID for pointer.
+ /// </summary>
+ /// <value>The UIBC input type</value>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ushort Id { get; set; }
+
+ /// <summary>
+ /// Gets the X coordinates of mouse.
+ /// </summary>
+ /// <value>The X coordinates</value>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ushort X { get; set; }
+
+ /// <summary>
+ /// Gets the Y coordinates of mouse.
+ /// </summary>
+ /// <value>The Y coordinates</value>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public ushort Y { get; set; }
+ }
}
return new InvalidOperationException($"Unknown error : {err.ToString()}.");
}
}
+
+ internal static ScreenMirroringError ToCsharp(this ScreenMirroringErrorCode err)
+ {
+ switch (err)
+ {
+ case ScreenMirroringErrorCode.InvalidOperation:
+ return ScreenMirroringError.InvalidOperation;
+
+ default:
+ throw new InvalidOperationException($"Unknown error : {err.ToString()}.");
+ }
+ }
}
}