Revert WebRTC library back to Microsoft MixedReality WebRTC.

This commit is contained in:
Jared Goodwin 2021-04-18 21:49:52 -07:00
parent 75006eae6c
commit c2d6dae83b
41 changed files with 378 additions and 182 deletions

View File

@ -46,8 +46,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="5.0.0" />
<PackageReference Include="SkiaSharp" Version="2.80.2" />
<PackageReference Include="SkiaSharp.Views.Desktop.Common" Version="2.80.2" />
<PackageReference Include="Microsoft.MixedReality.WebRTC" Version="2.0.2" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
</ItemGroup>

View File

@ -28,7 +28,7 @@ namespace Remotely.Desktop.Core.Services
Task SendCtrlAltDelToAgent();
Task SendDeviceInfo(string serviceID, string machineName, string deviceID);
Task SendDtoToViewer<T>(T baseDto, string viewerId);
Task SendIceCandidateToBrowser(string candidateJson, string viewerConnectionID);
Task SendIceCandidateToBrowser(string candidate, int sdpMlineIndex, string sdpMid, string viewerConnectionID);
Task SendMessageToViewer(string viewerID, string message);
Task SendRtcOfferToBrowser(string sdp, string viewerID, IceServerModel[] iceServers);
Task SendViewerConnected(string viewerConnectionId);
@ -164,9 +164,9 @@ namespace Remotely.Desktop.Core.Services
var serializedDto = MessagePack.MessagePackSerializer.Serialize(baseDto);
return Connection.SendAsync("SendDtoToBrowser", serializedDto, viewerId);
}
public async Task SendIceCandidateToBrowser(string candidateJson, string viewerConnectionID)
public async Task SendIceCandidateToBrowser(string candidate, int sdpMlineIndex, string sdpMid, string viewerConnectionID)
{
await Connection.SendAsync("SendIceCandidateToBrowser", candidateJson, viewerConnectionID);
await Connection.SendAsync("SendIceCandidateToBrowser", candidate, sdpMlineIndex, sdpMid, viewerConnectionID);
}
public async Task SendRtcOfferToBrowser(string sdp, string viewerID, IceServerModel[] iceServers)
@ -237,13 +237,13 @@ namespace Remotely.Desktop.Core.Services
});
Connection.On("ReceiveIceCandidate", (string candidateJson, string viewerID) =>
Connection.On("ReceiveIceCandidate", (string candidate, int sdpMlineIndex, string sdpMid, string viewerID) =>
{
try
{
if (conductor.Viewers.TryGetValue(viewerID, out var viewer))
{
viewer.RtcSession.AddIceCandidate(candidateJson);
viewer.RtcSession.AddIceCandidate(sdpMid, sdpMlineIndex, candidate);
}
}
catch (Exception ex)

View File

@ -97,6 +97,9 @@ namespace Remotely.Desktop.Core.Services
case BaseDtoType.ToggleBlockInput:
ToggleBlockInput(message);
break;
case BaseDtoType.ToggleWebRtcVideo:
ToggleWebRtcVideo(message, viewer);
break;
case BaseDtoType.ClipboardTransfer:
await ClipboardTransfer(message);
break;
@ -247,5 +250,11 @@ namespace Remotely.Desktop.Core.Services
var dto = MessagePackSerializer.Deserialize<ToggleBlockInputDto>(message);
KeyboardMouseInput.ToggleBlockInput(dto.ToggleOn);
}
private void ToggleWebRtcVideo(byte[] message, Viewer viewer)
{
var dto = MessagePackSerializer.Deserialize<ToggleWebRtcVideoDto>(message);
viewer.ToggleWebRtcVideo(dto.ToggleOn);
}
}
}

View File

@ -106,7 +106,7 @@ namespace Remotely.Desktop.Core.Services
}
if (screenCastRequest.UseWebRtc)
if (EnvironmentHelper.IsWindows && screenCastRequest.UseWebRtc)
{
await viewer.InitializeWebRtc();
}
@ -118,6 +118,11 @@ namespace Remotely.Desktop.Core.Services
{
try
{
if (viewer.IsUsingWebRtcVideo)
{
Thread.Sleep(100);
continue;
}
if (viewer.IsStalled)
{
// Viewer isn't responding. Abort sending.

View File

@ -60,6 +60,14 @@ namespace Remotely.Desktop.Core.Services
}
}
public bool IsUsingWebRtcVideo
{
get
{
return RtcSession?.IsPeerConnected == true && RtcSession?.IsVideoTrackConnected == true;
}
}
public string Name { get; set; }
public double AverageBytesPerSecond { get; set; }
@ -102,17 +110,11 @@ namespace Remotely.Desktop.Core.Services
RtcSession.LocalSdpReady += async (sender, sdp) =>
{
await CasterSocket.SendRtcOfferToBrowser(sdp.sdp, ViewerConnectionID, iceServers);
await CasterSocket.SendRtcOfferToBrowser(sdp.Content, ViewerConnectionID, iceServers);
};
RtcSession.IceCandidateReady += async (sender, candidate) =>
{
if (candidate is null)
{
Logger.Write("Candidate is null. Aborting send.");
return;
}
await CasterSocket.SendIceCandidateToBrowser(candidate.toJSON(), ViewerConnectionID);
await CasterSocket.SendIceCandidateToBrowser(candidate.Content, candidate.SdpMlineIndex, candidate.SdpMid, ViewerConnectionID);
};
await RtcSession.Init(iceServers);
@ -305,6 +307,11 @@ namespace Remotely.Desktop.Core.Services
TimeSpan.FromSeconds(10));
}
public void ToggleWebRtcVideo(bool toggleOn)
{
RtcSession.ToggleWebRtcVideo(toggleOn);
}
private async void AudioCapturer_AudioSampleReady(object sender, byte[] sample)
{
await SendAudioSample(sample);

View File

@ -1,4 +1,5 @@
using MessagePack;
using Microsoft.MixedReality.WebRTC;
using Remotely.Shared.Utilities;
using Remotely.Shared.Models;
using Remotely.Shared.Models.RemoteControlDtos;
@ -6,59 +7,66 @@ using System;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using SIPSorcery.Net;
using System.Timers;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
namespace Remotely.Desktop.Core.Services
{
public class WebRtcSession : IDisposable
{
public WebRtcSession(Viewer viewer, IDtoMessageHandler rtcMessageHandler)
public WebRtcSession(Services.Viewer viewer, IDtoMessageHandler rtcMessageHandler)
{
Viewer = viewer;
RtcMessageHandler = rtcMessageHandler;
}
public event EventHandler<IceCandidate> IceCandidateReady;
public event EventHandler<SdpMessage> LocalSdpReady;
public event EventHandler<RTCIceCandidate> IceCandidateReady;
public event EventHandler<RTCSessionDescriptionInit> LocalSdpReady;
public bool IsDataChannelOpen => CaptureChannel?.readyState == RTCDataChannelState.open;
public bool IsPeerConnected => PeerSession?.connectionState == RTCPeerConnectionState.connected;
private RTCDataChannel CaptureChannel { get; set; }
private IceServerModel[] IceServers { get; set; }
private RTCPeerConnection PeerSession { get; set; }
private IDtoMessageHandler RtcMessageHandler { get; }
private Viewer Viewer { get; }
public void AddIceCandidate(string candidateJson)
public ulong CurrentBuffer { get; private set; }
public bool IsDataChannelOpen => CaptureChannel?.State == DataChannel.ChannelState.Open;
public bool IsPeerConnected => PeerSession?.IsConnected == true;
public bool IsVideoTrackConnected
{
if (RTCIceCandidateInit.TryParse(candidateJson, out var rtcCandidate))
get
{
PeerSession.addIceCandidate(rtcCandidate);
return Transceiver?.LocalVideoTrack?.Enabled == true;
}
else
}
private DataChannel CaptureChannel { get; set; }
private IceServerModel[] IceServers { get; set; }
private PeerConnection PeerSession { get; set; }
private IDtoMessageHandler RtcMessageHandler { get; }
private Transceiver Transceiver { get; set; }
private ExternalVideoTrackSource VideoSource { get; set; }
private Services.Viewer Viewer { get; }
public void AddIceCandidate(string sdpMid, int sdpMlineIndex, string candidate)
{
PeerSession.AddIceCandidate(new IceCandidate()
{
Logger.Write("End of ICE candidates. Adding null candidate.");
PeerSession.addIceCandidate(rtcCandidate);
}
Content = candidate,
SdpMid = sdpMid,
SdpMlineIndex = sdpMlineIndex
});
}
public void Dispose()
{
try
{
PeerSession?.DataChannels?.Clear();
CaptureChannel?.close();
// Unable to exit process until DataChannel is removed/disposed,
// and this throws internally (at least in 2.0 version).
PeerSession?.RemoveDataChannel(CaptureChannel);
}
catch { }
PeerSession?.Dispose();
PeerSession.Transceivers.RemoveAll(x => true);
Disposer.TryDisposeAll(new IDisposable[]
{
Transceiver?.LocalVideoTrack,
VideoSource,
PeerSession
});
GC.SuppressFinalize(this);
}
@ -68,111 +76,171 @@ namespace Remotely.Desktop.Core.Services
IceServers = iceServers;
var config = new RTCConfiguration()
{
iceServers = iceServers.Select(x => new RTCIceServer()
{
credential = x.Credential,
credentialType = RTCIceCredentialType.password,
urls = x.Urls,
username = x.Username
PeerSession = new PeerConnection();
}).ToList()
var iceList = IceServers.Select(x => new IceServer()
{
Urls = { x.Url },
TurnPassword = x.TurnPassword ?? string.Empty,
TurnUserName = x.TurnUsername ?? string.Empty
}).ToList();
var config = new PeerConnectionConfiguration()
{
IceServers = iceList
};
PeerSession = new RTCPeerConnection(config);
await PeerSession.InitializeAsync(config);
PeerSession.oniceconnectionstatechange += PeerSession_oniceconnectionstatechange;
PeerSession.onicecandidate += PeerSession_onicecandidate;
PeerSession.LocalSdpReadytoSend += PeerSession_LocalSdpReadytoSend;
PeerSession.Connected += PeerConnection_Connected;
PeerSession.IceStateChanged += PeerConnection_IceStateChanged;
PeerSession.IceCandidateReadytoSend += PeerSession_IceCandidateReadytoSend;
var dataChannelInit = new RTCDataChannelInit()
{
ordered = true
};
CaptureChannel = await PeerSession.createDataChannel("RemoteControl", dataChannelInit);
CaptureChannel = await PeerSession.AddDataChannelAsync("ScreenCapture", true, true);
CaptureChannel.BufferingChanged += DataChannel_BufferingChanged;
CaptureChannel.MessageReceived += CaptureChannel_MessageReceived;
CaptureChannel.StateChanged += CaptureChannel_StateChanged;
CaptureChannel.onmessage += CaptureChannel_onmessage; ;
CaptureChannel.onclose += CaptureChannel_onclose;
CaptureChannel.onopen += CaptureChannel_onopen;
CaptureChannel.onerror += CaptureChannel_onerror;
VideoSource = ExternalVideoTrackSource.CreateFromArgb32Callback(GetCaptureFrame);
Transceiver = PeerSession.AddTransceiver(MediaKind.Video);
var offer = PeerSession.createOffer(new RTCOfferOptions());
LocalSdpReady?.Invoke(this, offer);
PeerSession.CreateOffer();
}
public Task SendDto<T>(T dto) where T : BaseDto
{
CaptureChannel.send(MessagePackSerializer.Serialize(dto));
TaskHelper.DelayUntil(() => CaptureChannel.bufferedAmount < 64_000, TimeSpan.FromSeconds(5));
return Task.CompletedTask;
return Task.Run(() =>
{
CaptureChannel.SendMessage(MessagePackSerializer.Serialize(dto));
while (CurrentBuffer > 64_000)
{
Thread.Sleep(10);
}
});
}
public Task SetRemoteDescription(string type, string sdp)
public async Task SetRemoteDescription(string type, string sdp)
{
if (!Enum.TryParse<RTCSdpType>(type, true, out var sdpMessageType))
if (!Enum.TryParse<SdpMessageType>(type, true, out var sdpMessageType))
{
Logger.Write("Unable to parse remote WebRTC description type.");
return Task.CompletedTask;
return;
}
PeerSession.setRemoteDescription(new RTCSessionDescriptionInit()
await PeerSession.SetRemoteDescriptionAsync(new SdpMessage()
{
type = sdpMessageType,
sdp = sdp
Content = sdp,
Type = sdpMessageType
});
if (sdpMessageType == RTCSdpType.offer)
if (sdpMessageType == SdpMessageType.Offer)
{
PeerSession.createAnswer(new RTCAnswerOptions());
PeerSession.CreateAnswer();
}
}
public void ToggleWebRtcVideo(bool toggleOn)
{
if (Transceiver?.LocalVideoTrack != null)
{
Transceiver.LocalVideoTrack.Dispose();
Transceiver.LocalVideoTrack = null;
}
return Task.CompletedTask;
if (toggleOn)
{
Transceiver.LocalVideoTrack = LocalVideoTrack.CreateFromSource(VideoSource, new LocalVideoTrackInitConfig()
{
trackName = "ScreenCapture"
});
}
}
private async void CaptureChannel_onmessage(RTCDataChannel dc, DataChannelPayloadProtocols protocol, byte[] data)
private async void CaptureChannel_MessageReceived(byte[] obj)
{
await RtcMessageHandler.ParseMessage(Viewer, data);
await RtcMessageHandler.ParseMessage(Viewer, obj);
}
private async void CaptureChannel_onerror(string obj)
private async void CaptureChannel_StateChanged()
{
// Clear the queue when WebRTC state changes.
Viewer.PendingSentFrames.Clear();
Logger.Write($"DataChannel error: {obj}");
await Init(IceServers);
Logger.Write($"DataChannel state changed. New State: {CaptureChannel.State}");
if (CaptureChannel.State == DataChannel.ChannelState.Closed)
{
await Init(IceServers);
}
}
private void CaptureChannel_onopen()
private void DataChannel_BufferingChanged(ulong previous, ulong current, ulong limit)
{
// Clear the queue when WebRTC state changes.
Viewer.PendingSentFrames.Clear();
Logger.Write("DataChannel opened.");
CurrentBuffer = current;
}
private async void CaptureChannel_onclose()
private void GetCaptureFrame(in FrameRequest request)
{
// Clear the queue when WebRTC state changes.
Viewer.PendingSentFrames.Clear();
Logger.Write("DataChannel closed.");
await Init(IceServers);
try
{
if (!IsVideoTrackConnected)
{
return;
}
using var currentFrame = Viewer.Capturer.GetNextFrame();
if (currentFrame == null)
{
return;
}
var bitmapData = currentFrame.LockBits(
new Rectangle(Point.Empty, Viewer.Capturer.CurrentScreenBounds.Size),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
try
{
var frame = new Argb32VideoFrame()
{
data = bitmapData.Scan0,
height = (uint)currentFrame.Height,
width = (uint)currentFrame.Width,
stride = bitmapData.Stride
};
request.CompleteRequest(in frame);
}
finally
{
currentFrame.UnlockBits(bitmapData);
}
}
catch (Exception ex)
{
Logger.Write(ex);
}
}
private void PeerSession_oniceconnectionstatechange(RTCIceConnectionState newState)
private void PeerConnection_Connected()
{
Logger.Write("PeerConnection connected.");
}
private void PeerConnection_IceStateChanged(IceConnectionState newState)
{
// Clear the queue when WebRTC state changes.
Viewer.PendingSentFrames.Clear();
Logger.Write($"Ice state changed to {newState}.");
}
private void PeerSession_onicecandidate(RTCIceCandidate candidate)
private void PeerSession_IceCandidateReadytoSend(IceCandidate candidate)
{
Logger.Write("Ice candidate ready to send.");
IceCandidateReady?.Invoke(this, candidate);
}
private void PeerSession_LocalSdpReadytoSend(SdpMessage message)
{
Logger.Write($"Local SDP ready.");
LocalSdpReady?.Invoke(this, message);
}
}
}

View File

@ -34,6 +34,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.MixedReality.WebRTC" Version="2.0.2" />
<PackageReference Include="NAudio" Version="2.0.0" />
<PackageReference Include="SharpDX" Version="4.2.0" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />

View File

@ -168,11 +168,11 @@ namespace Remotely.Server.Hubs
return ViewerHubContext.Clients.Client(viewerId).SendAsync("SendDtoToBrowser", dto);
}
public Task SendIceCandidateToBrowser(string candidateJson, string viewerID)
public Task SendIceCandidateToBrowser(string candidate, int sdpMlineIndex, string sdpMid, string viewerID)
{
if (_appConfig.UseWebRtc)
{
return ViewerHubContext.Clients.Client(viewerID).SendAsync("ReceiveIceCandidate", candidateJson);
return ViewerHubContext.Clients.Client(viewerID).SendAsync("ReceiveIceCandidate", candidate, sdpMlineIndex, sdpMid);
}
return Task.CompletedTask;

View File

@ -122,9 +122,9 @@ namespace Remotely.Server.Hubs
return base.OnDisconnectedAsync(exception);
}
public Task SendIceCandidateToAgent(string candidateJson)
public Task SendIceCandidateToAgent(string candidate, int sdpMlineIndex, string sdpMid)
{
return CasterHubContext.Clients.Client(ScreenCasterID).SendAsync("ReceiveIceCandidate", candidateJson, Context.ConnectionId);
return CasterHubContext.Clients.Client(ScreenCasterID).SendAsync("ReceiveIceCandidate", candidate, sdpMlineIndex, sdpMid, Context.ConnectionId);
}
public Task SendRtcAnswerToAgent(string sdp)

View File

@ -134,6 +134,10 @@
</div>
<div>
<button id="streamVideoButton" class="option-button" hidden title="Reduce bandwidth and increase FPS, but increase input delay.">
Stream Mode <i class="fas fa-video"></i>
</button>
<button id="changeScreenButton" class="option-button" title="Switch monitors on remote multi-monitor setups.">
Monitors <i class="fas fa-desktop"></i>
</button>

View File

@ -40,8 +40,8 @@ namespace Remotely.Server.Services
{
private readonly IceServerModel[] fallbackIceServers = new IceServerModel[]
{
new IceServerModel() { Urls = "stun:stun.l.google.com:19302"},
new IceServerModel() { Urls = "stun:stun4.l.google.com:19302"}
new IceServerModel() { Url = "stun:stun.l.google.com:19302"},
new IceServerModel() { Url = "stun:stun4.l.google.com:19302"}
};
public ApplicationConfig(IConfiguration config)

View File

@ -18,14 +18,14 @@
"EnforceAttendedAccess": false,
"IceServers": [
{
"Urls": "stun:stun.l.google.com:19302",
"Credential": null,
"Username": null
"Url": "stun:stun.l.google.com:19302",
"TurnPassword": "",
"TurnUsername": ""
},
{
"Urls": "stun:stun4.l.google.com:19302",
"Credential": null,
"Username": null
"Url": "stun:stun4.l.google.com:19302",
"TurnPassword": "",
"TurnUsername": ""
}
],
"KnownProxies": [],

View File

@ -24,6 +24,7 @@ export var BaseDtoType;
BaseDtoType[BaseDtoType["WindowsSessions"] = 23] = "WindowsSessions";
BaseDtoType[BaseDtoType["SetKeyStatesUp"] = 24] = "SetKeyStatesUp";
BaseDtoType[BaseDtoType["FrameReceived"] = 25] = "FrameReceived";
BaseDtoType[BaseDtoType["ToggleWebRtcVideo"] = 26] = "ToggleWebRtcVideo";
BaseDtoType[BaseDtoType["OpenFileTransferWindow"] = 27] = "OpenFileTransferWindow";
})(BaseDtoType || (BaseDtoType = {}));
//# sourceMappingURL=BaseDtoType.js.map

View File

@ -1 +1 @@
{"version":3,"file":"BaseDtoType.js","sourceRoot":"","sources":["BaseDtoType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,WA0BX;AA1BD,WAAY,WAAW;IACnB,6DAAgB,CAAA;IAChB,yDAAc,CAAA;IACd,yDAAc,CAAA;IACd,2DAAe,CAAA;IACf,+DAAiB,CAAA;IACjB,2DAAe,CAAA;IACf,6DAAgB,CAAA;IAChB,6DAAgB,CAAA;IAChB,uDAAa,CAAA;IACb,uDAAa,CAAA;IACb,oDAAY,CAAA;IACZ,4CAAQ,CAAA;IACR,0DAAe,CAAA;IACf,oDAAY,CAAA;IACZ,gDAAU,CAAA;IACV,0DAAe,CAAA;IACf,4DAAgB,CAAA;IAChB,sEAAqB,CAAA;IACrB,wEAAsB,CAAA;IACtB,sDAAa,CAAA;IACb,8CAAS,CAAA;IACT,oEAAoB,CAAA;IACpB,kEAAmB,CAAA;IACnB,gEAAkB,CAAA;IAClB,kFAA2B,CAAA;AAC/B,CAAC,EA1BW,WAAW,KAAX,WAAW,QA0BtB"}
{"version":3,"file":"BaseDtoType.js","sourceRoot":"","sources":["BaseDtoType.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,WA2BX;AA3BD,WAAY,WAAW;IACnB,6DAAgB,CAAA;IAChB,yDAAc,CAAA;IACd,yDAAc,CAAA;IACd,2DAAe,CAAA;IACf,+DAAiB,CAAA;IACjB,2DAAe,CAAA;IACf,6DAAgB,CAAA;IAChB,6DAAgB,CAAA;IAChB,uDAAa,CAAA;IACb,uDAAa,CAAA;IACb,oDAAY,CAAA;IACZ,4CAAQ,CAAA;IACR,0DAAe,CAAA;IACf,oDAAY,CAAA;IACZ,gDAAU,CAAA;IACV,0DAAe,CAAA;IACf,4DAAgB,CAAA;IAChB,sEAAqB,CAAA;IACrB,wEAAsB,CAAA;IACtB,sDAAa,CAAA;IACb,8CAAS,CAAA;IACT,oEAAoB,CAAA;IACpB,kEAAmB,CAAA;IACnB,gEAAkB,CAAA;IAClB,wEAAsB,CAAA;IACtB,kFAA2B,CAAA;AAC/B,CAAC,EA3BW,WAAW,KAAX,WAAW,QA2BtB"}

View File

@ -23,5 +23,6 @@
WindowsSessions = 23,
SetKeyStatesUp = 24,
FrameReceived = 25,
ToggleWebRtcVideo = 26,
OpenFileTransferWindow = 27
}

View File

@ -1,10 +1,11 @@
import { AudioButton, ChangeScreenButton, HorizontalBars, ScreenSelectBar, ClipboardTransferButton, ClipboardTransferBar, TypeClipboardButton, ConnectButton, CtrlAltDelButton, DisconnectButton, FileTransferButton, FileTransferInput, FitToScreenButton, ScreenViewer, BlockInputButton, InviteButton, KeyboardButton, TouchKeyboardTextArea, MenuFrame, MenuButton, ScreenViewerWrapper, WindowsSessionSelect, RecordSessionButton, DownloadRecordingButton, VideoScreenViewer, FileTransferBar, FileUploadButtton, FileDownloadButton, ViewOnlyButton, FullScreenButton } from "./UI.js";
import { AudioButton, ChangeScreenButton, HorizontalBars, ScreenSelectBar, ClipboardTransferButton, ClipboardTransferBar, TypeClipboardButton, ConnectButton, CtrlAltDelButton, DisconnectButton, FileTransferButton, FileTransferInput, FitToScreenButton, ScreenViewer, BlockInputButton, InviteButton, KeyboardButton, TouchKeyboardTextArea, MenuFrame, MenuButton, ScreenViewerWrapper, WindowsSessionSelect, RecordSessionButton, DownloadRecordingButton, VideoScreenViewer, StreamVideoButton, FileTransferBar, FileUploadButtton, FileDownloadButton, UpdateStreamingToggled, ViewOnlyButton, FullScreenButton } from "./UI.js";
import { Sound } from "./Sound.js";
import { ViewerApp } from "./App.js";
import { UploadFiles } from "./FileTransferService.js";
import { RemoteControlMode } from "./Enums/RemoteControlMode.js";
import { GetDistanceBetween } from "./Utilities.js";
import { ShowMessage } from "./UI.js";
import { SetSettings } from "./SettingsService.js";
var lastPointerMove = Date.now();
var isDragging;
var currentPointerDevice;
@ -173,6 +174,13 @@ export function ApplyInputHandlers() {
ev.stopPropagation();
MenuButton.style.top = `${ev.touches[0].clientY}px`;
});
StreamVideoButton.addEventListener("click", (ev) => {
var toggleOn = !StreamVideoButton.classList.contains("toggled");
ViewerApp.Settings.streamModeEnabled = toggleOn;
SetSettings(ViewerApp.Settings);
UpdateStreamingToggled(toggleOn);
ViewerApp.MessageSender.SendToggleWebRtcVideo(toggleOn);
});
[ScreenViewer, VideoScreenViewer].forEach(viewer => {
viewer.addEventListener("pointermove", function (e) {
currentPointerDevice = e.pointerType;

File diff suppressed because one or more lines are too long

View File

@ -24,9 +24,11 @@
RecordSessionButton,
DownloadRecordingButton,
VideoScreenViewer,
StreamVideoButton,
FileTransferBar,
FileUploadButtton,
FileDownloadButton,
UpdateStreamingToggled,
ViewOnlyButton,
FullScreenButton
} from "./UI.js";
@ -213,6 +215,15 @@ export function ApplyInputHandlers() {
ev.stopPropagation();
MenuButton.style.top = `${ev.touches[0].clientY}px`;
});
StreamVideoButton.addEventListener("click", (ev) => {
var toggleOn = !StreamVideoButton.classList.contains("toggled");
ViewerApp.Settings.streamModeEnabled = toggleOn;
SetSettings(ViewerApp.Settings);
UpdateStreamingToggled(toggleOn);
ViewerApp.MessageSender.SendToggleWebRtcVideo(toggleOn);
});
[ ScreenViewer, VideoScreenViewer ].forEach(viewer => {
viewer.addEventListener("pointermove", function (e: PointerEvent) {

View File

@ -99,6 +99,12 @@ export class ToggleBlockInputDto {
this.ToggleOn = toggleOn;
}
}
export class ToggleWebRtcVideoDto {
constructor(toggleOn) {
this.DtoType = BaseDtoType.ToggleWebRtcVideo;
this.ToggleOn = toggleOn;
}
}
export class WindowsSessionsDto {
constructor() {
this.DtoType = BaseDtoType.WindowsSessions;

View File

@ -1 +1 @@
{"version":3,"file":"Dtos.js","sourceRoot":"","sources":["Dtos.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"Dtos.js","sourceRoot":"","sources":["Dtos.ts"],"names":[],"mappings":"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"}

View File

@ -201,6 +201,16 @@ export class ToggleBlockInputDto implements BaseDto {
DtoType: BaseDtoType = BaseDtoType.ToggleBlockInput;
}
export class ToggleWebRtcVideoDto implements BaseDto {
constructor(toggleOn: boolean) {
this.ToggleOn = toggleOn;
}
ToggleOn: boolean;
DtoType: BaseDtoType = BaseDtoType.ToggleWebRtcVideo;
}
export class WindowsSessionsDto implements BaseDto {
WindowsSessions: Array<WindowsSession>;

View File

@ -1,3 +1,4 @@
export interface Settings {
displayName: string;
streamModeEnabled: boolean;
}

View File

@ -1,5 +1,5 @@
import { ViewerApp } from "./App.js";
import { CtrlAltDelDto, KeyDownDto, KeyPressDto, KeyUpDto, MouseDownDto, MouseMoveDto, MouseUpDto, MouseWheelDto, SelectScreenDto, TapDto, ToggleAudioDto, ToggleBlockInputDto, ClipboardTransferDto, FileDto, WindowsSessionsDto, GenericDto } from "./Interfaces/Dtos.js";
import { CtrlAltDelDto, KeyDownDto, KeyPressDto, KeyUpDto, MouseDownDto, MouseMoveDto, MouseUpDto, MouseWheelDto, SelectScreenDto, TapDto, ToggleAudioDto, ToggleBlockInputDto, ClipboardTransferDto, FileDto, WindowsSessionsDto, GenericDto, ToggleWebRtcVideoDto } from "./Interfaces/Dtos.js";
import { CreateGUID, When } from "./Utilities.js";
import { FileTransferProgress } from "./UI.js";
import { BaseDtoType } from "./Enums/BaseDtoType.js";
@ -94,6 +94,10 @@ export class MessageSender {
var dto = new ToggleBlockInputDto(toggleOn);
this.SendToAgent(() => ViewerApp.RtcSession.SendDto(dto), () => ViewerApp.ViewerHubConnection.SendDtoToClient(dto));
}
SendToggleWebRtcVideo(toggleOn) {
var dto = new ToggleWebRtcVideoDto(toggleOn);
this.SendToAgent(() => ViewerApp.RtcSession.SendDto(dto), () => ViewerApp.ViewerHubConnection.SendDtoToClient(dto));
}
SendClipboardTransfer(text, typeText) {
var dto = new ClipboardTransferDto(text, typeText);
this.SendToAgent(() => ViewerApp.RtcSession.SendDto(dto), () => ViewerApp.ViewerHubConnection.SendDtoToClient(dto));

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,8 @@ import {
ClipboardTransferDto,
FileDto,
WindowsSessionsDto,
GenericDto
GenericDto,
ToggleWebRtcVideoDto
} from "./Interfaces/Dtos.js";
import { CreateGUID, When } from "./Utilities.js";
import { FileTransferProgress } from "./UI.js";
@ -138,6 +139,11 @@ export class MessageSender {
this.SendToAgent(() => ViewerApp.RtcSession.SendDto(dto),
() => ViewerApp.ViewerHubConnection.SendDtoToClient(dto));
}
SendToggleWebRtcVideo(toggleOn: boolean) {
var dto = new ToggleWebRtcVideoDto(toggleOn);
this.SendToAgent(() => ViewerApp.RtcSession.SendDto(dto),
() => ViewerApp.ViewerHubConnection.SendDtoToClient(dto));
}
SendClipboardTransfer(text: string, typeText: boolean) {
var dto = new ClipboardTransferDto(text, typeText);
this.SendToAgent(() => ViewerApp.RtcSession.SendDto(dto),

View File

@ -1,5 +1,5 @@
export class IceServerModel {
Urls: string;
Credential: string;
Username: string;
Url: string;
TurnPassword: string;
TurnUsername: string;
}

View File

@ -1,21 +1,19 @@
import * as UI from "./UI.js";
import { ViewerApp } from "./App.js";
import { When } from "./Utilities.js";
export class RtcSession {
constructor() {
this.MessagePack = window['MessagePack'];
}
Init(iceServers) {
var servers = iceServers.map(x => {
return {
urls: x.Urls,
username: x.Username,
credential: x.Credential,
credentialType: "password"
};
});
this.PeerConnection = new RTCPeerConnection({
iceServers: servers
iceServers: iceServers.map(x => {
return {
urls: x.Url,
username: x.TurnUsername,
credential: x.TurnPassword,
credentialType: "password"
};
})
});
this.PeerConnection.ondatachannel = (ev) => {
console.log("Data channel received.");
@ -25,6 +23,7 @@ export class RtcSession {
console.log("Data channel closed.");
UI.ConnectionP2PIcon.style.display = "none";
UI.ConnectionRelayedIcon.style.display = "unset";
UI.StreamVideoButton.setAttribute("hidden", "hidden");
UI.ScreenViewer.removeAttribute("hidden");
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
};
@ -32,6 +31,7 @@ export class RtcSession {
console.log("Data channel error.", ev.error);
UI.ConnectionP2PIcon.style.display = "none";
UI.ConnectionRelayedIcon.style.display = "unset";
UI.StreamVideoButton.setAttribute("hidden", "hidden");
UI.ScreenViewer.removeAttribute("hidden");
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
};
@ -43,6 +43,11 @@ export class RtcSession {
console.log("Data channel opened.");
UI.ConnectionP2PIcon.style.display = "unset";
UI.ConnectionRelayedIcon.style.display = "none";
UI.StreamVideoButton.removeAttribute("hidden");
if (ViewerApp.Settings.streamModeEnabled) {
UI.UpdateStreamingToggled(true);
ViewerApp.MessageSender.SendToggleWebRtcVideo(true);
}
};
};
this.PeerConnection.onconnectionstatechange = function (ev) {
@ -73,12 +78,9 @@ export class RtcSession {
await ViewerApp.ViewerHubConnection.SendRtcAnswer(this.PeerConnection.localDescription);
console.log("Set RTC offer.");
}
async ReceiveCandidate(candidateJson) {
When(() => !!this.PeerConnection).then(async () => {
var rtcCandidate = JSON.parse(candidateJson);
await this.PeerConnection.addIceCandidate(rtcCandidate);
console.log("Set ICE candidate.", rtcCandidate);
});
async ReceiveCandidate(candidate) {
await this.PeerConnection.addIceCandidate(candidate);
console.log("Set ICE candidate.");
}
SendDto(dto) {
this.DataChannel.send(this.MessagePack.encode(dto));

View File

@ -1 +1 @@
{"version":3,"file":"RtcSession.js","sourceRoot":"","sources":["RtcSession.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"RtcSession.js","sourceRoot":"","sources":["RtcSession.ts"],"names":[],"mappings":"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"}

View File

@ -1,26 +1,23 @@
import * as UI from "./UI.js";
import * as Utilities from "./Utilities.js";
import { ViewerApp } from "./App.js";
import { IceServerModel } from "./Models/IceServerModel.js";
import { When } from "./Utilities.js";
export class RtcSession {
PeerConnection: RTCPeerConnection;
DataChannel: RTCDataChannel;
MessagePack: any = window['MessagePack'];
Init(iceServers: IceServerModel[]) {
var servers = iceServers.map(x => {
return {
urls: x.Urls,
username: x.Username,
credential: x.Credential,
credentialType: "password"
} as RTCIceServer
});
this.PeerConnection = new RTCPeerConnection({
iceServers: servers
iceServers: iceServers.map(x => {
return {
urls: x.Url,
username: x.TurnUsername,
credential: x.TurnPassword,
credentialType: "password"
}
})
});
this.PeerConnection.ondatachannel = (ev) => {
@ -32,6 +29,7 @@ export class RtcSession {
UI.ConnectionP2PIcon.style.display = "none";
UI.ConnectionRelayedIcon.style.display = "unset";
UI.StreamVideoButton.setAttribute("hidden", "hidden");
UI.ScreenViewer.removeAttribute("hidden");
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
};
@ -40,6 +38,7 @@ export class RtcSession {
UI.ConnectionP2PIcon.style.display = "none";
UI.ConnectionRelayedIcon.style.display = "unset";
UI.StreamVideoButton.setAttribute("hidden", "hidden");
UI.ScreenViewer.removeAttribute("hidden");
UI.VideoScreenViewer.setAttribute("hidden", "hidden");
};
@ -52,6 +51,13 @@ export class RtcSession {
console.log("Data channel opened.");
UI.ConnectionP2PIcon.style.display = "unset";
UI.ConnectionRelayedIcon.style.display = "none";
UI.StreamVideoButton.removeAttribute("hidden");
if (ViewerApp.Settings.streamModeEnabled) {
UI.UpdateStreamingToggled(true);
ViewerApp.MessageSender.SendToggleWebRtcVideo(true);
}
};
};
this.PeerConnection.onconnectionstatechange = function (ev) {
@ -85,14 +91,9 @@ export class RtcSession {
await ViewerApp.ViewerHubConnection.SendRtcAnswer(this.PeerConnection.localDescription);
console.log("Set RTC offer.");
}
async ReceiveCandidate(candidateJson: string) {
When(() => !!this.PeerConnection).then(async () => {
var rtcCandidate = JSON.parse(candidateJson) as RTCIceCandidate;
await this.PeerConnection.addIceCandidate(rtcCandidate);
console.log("Set ICE candidate.", rtcCandidate);
});
async ReceiveCandidate(candidate: RTCIceCandidate) {
await this.PeerConnection.addIceCandidate(candidate);
console.log("Set ICE candidate.");
}
SendDto(dto: any) {

View File

@ -1,4 +1,5 @@
const defaultSettings = {
streamModeEnabled: false,
displayName: ""
};
export function GetSettings() {

View File

@ -1 +1 @@
{"version":3,"file":"SettingsService.js","sourceRoot":"","sources":["SettingsService.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG;IACpB,WAAW,EAAE,EAAE;CAClB,CAAC;AAGF,MAAM,UAAU,WAAW;IACvB,IAAI;QACA,IAAI,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACvD,IAAI,QAAQ,EAAE;YACV,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;SAC/B;KACJ;IACD,OAAO,EAAE,EAAE;QACP,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACrB;IAED,WAAW,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,eAAe,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAkB;IAC1C,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC"}
{"version":3,"file":"SettingsService.js","sourceRoot":"","sources":["SettingsService.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG;IACpB,iBAAiB,EAAE,KAAK;IACxB,WAAW,EAAE,EAAE;CAClB,CAAC;AAGF,MAAM,UAAU,WAAW;IACvB,IAAI;QACA,IAAI,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACvD,IAAI,QAAQ,EAAE;YACV,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;SAC/B;KACJ;IACD,OAAO,EAAE,EAAE;QACP,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACrB;IAED,WAAW,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,eAAe,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAkB;IAC1C,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtE,CAAC"}

View File

@ -1,6 +1,7 @@
import { Settings } from "./Interfaces/Settings.js";
const defaultSettings = {
streamModeEnabled: false,
displayName: ""
};

View File

@ -20,6 +20,7 @@ export var ScreenSelectBar = document.getElementById("screenSelectBar");
export var ActionsBar = document.getElementById("actionsBar");
export var ViewBar = document.getElementById("viewBar");
export var ChangeScreenButton = document.getElementById("changeScreenButton");
export var StreamVideoButton = document.getElementById("streamVideoButton");
export var FitToScreenButton = document.getElementById("fitToScreenButton");
export var BlockInputButton = document.getElementById("blockInputButton");
export var DisconnectButton = document.getElementById("disconnectButton");
@ -105,6 +106,7 @@ export function ToggleConnectUI(shown) {
else {
DisconnectedBox.style.removeProperty("display");
}
StreamVideoButton.classList.remove("toggled");
BlockInputButton.classList.remove("toggled");
AudioButton.classList.remove("toggled");
}
@ -148,6 +150,18 @@ export function UpdateDisplays(selectedDisplay, displayNames) {
};
}
}
export function UpdateStreamingToggled(toggleOn) {
if (toggleOn) {
StreamVideoButton.classList.add("toggled");
VideoScreenViewer.removeAttribute("hidden");
ScreenViewer.setAttribute("hidden", "hidden");
}
else {
StreamVideoButton.classList.remove("toggled");
ScreenViewer.removeAttribute("hidden");
VideoScreenViewer.setAttribute("hidden", "hidden");
}
}
export function UpdateWindowsSessions(windowsSessions) {
while (WindowsSessionSelect.options.length > 0) {
WindowsSessionSelect.options.remove(0);

File diff suppressed because one or more lines are too long

View File

@ -22,6 +22,7 @@ export var ScreenSelectBar = document.getElementById("screenSelectBar") as HTMLD
export var ActionsBar = document.getElementById("actionsBar") as HTMLDivElement;
export var ViewBar = document.getElementById("viewBar") as HTMLDivElement;
export var ChangeScreenButton = document.getElementById("changeScreenButton") as HTMLButtonElement;
export var StreamVideoButton = document.getElementById("streamVideoButton") as HTMLButtonElement;
export var FitToScreenButton = document.getElementById("fitToScreenButton") as HTMLButtonElement;
export var BlockInputButton = document.getElementById("blockInputButton") as HTMLButtonElement;
export var DisconnectButton = document.getElementById("disconnectButton") as HTMLButtonElement;
@ -123,6 +124,7 @@ export function ToggleConnectUI(shown: boolean) {
else {
DisconnectedBox.style.removeProperty("display");
}
StreamVideoButton.classList.remove("toggled");
BlockInputButton.classList.remove("toggled");
AudioButton.classList.remove("toggled");
}
@ -170,6 +172,19 @@ export function UpdateDisplays(selectedDisplay: string, displayNames: string[])
}
}
export function UpdateStreamingToggled(toggleOn: boolean) {
if (toggleOn) {
StreamVideoButton.classList.add("toggled");
VideoScreenViewer.removeAttribute("hidden");
ScreenViewer.setAttribute("hidden", "hidden");
}
else {
StreamVideoButton.classList.remove("toggled");
ScreenViewer.removeAttribute("hidden");
VideoScreenViewer.setAttribute("hidden", "hidden");
}
}
export function UpdateWindowsSessions(windowsSessions: Array<WindowsSession>) {
while (WindowsSessionSelect.options.length > 0) {
WindowsSessionSelect.options.remove(0);

View File

@ -39,12 +39,10 @@ export class ViewerHubConnection {
}
SendIceCandidate(candidate) {
if (candidate) {
console.log(candidate.toJSON);
this.Connection.invoke("SendIceCandidateToAgent", JSON.stringify(candidate.toJSON()));
this.Connection.invoke("SendIceCandidateToAgent", candidate.candidate, candidate.sdpMLineIndex, candidate.sdpMid);
}
else {
console.log("Sending null candidate.");
this.Connection.invoke("SendIceCandidateToAgent", "{}");
this.Connection.invoke("SendIceCandidateToAgent", "", 0, "");
}
}
SendRtcAnswer(sessionDescription) {
@ -121,9 +119,13 @@ export class ViewerHubConnection {
ViewerApp.RtcSession.Init(iceServers);
await ViewerApp.RtcSession.ReceiveRtcOffer(sdp);
});
hubConnection.on("ReceiveIceCandidate", async (candidateJson) => {
console.log("Ice candidate received.", candidateJson);
await ViewerApp.RtcSession.ReceiveCandidate(candidateJson);
hubConnection.on("ReceiveIceCandidate", (candidate, sdpMlineIndex, sdpMid) => {
console.log("Ice candidate received.");
ViewerApp.RtcSession.ReceiveCandidate({
candidate: candidate,
sdpMLineIndex: sdpMlineIndex,
sdpMid: sdpMid
});
});
hubConnection.on("ShowMessage", (message) => {
ShowMessage(message);

File diff suppressed because one or more lines are too long

View File

@ -55,12 +55,10 @@ export class ViewerHubConnection {
SendIceCandidate(candidate: RTCIceCandidate) {
if (candidate) {
console.log(candidate.toJSON);
this.Connection.invoke("SendIceCandidateToAgent", JSON.stringify(candidate.toJSON()));
this.Connection.invoke("SendIceCandidateToAgent", candidate.candidate, candidate.sdpMLineIndex, candidate.sdpMid);
}
else {
console.log("Sending null candidate.");
this.Connection.invoke("SendIceCandidateToAgent", "{}");
this.Connection.invoke("SendIceCandidateToAgent", "", 0, "");
}
}
SendRtcAnswer(sessionDescription: RTCSessionDescription) {
@ -149,9 +147,13 @@ export class ViewerHubConnection {
await ViewerApp.RtcSession.ReceiveRtcOffer(sdp);
});
hubConnection.on("ReceiveIceCandidate", async (candidateJson: string) => {
console.log("Ice candidate received.", candidateJson);
await ViewerApp.RtcSession.ReceiveCandidate(candidateJson);
hubConnection.on("ReceiveIceCandidate", (candidate: string, sdpMlineIndex: number, sdpMid: string) => {
console.log("Ice candidate received.");
ViewerApp.RtcSession.ReceiveCandidate({
candidate: candidate,
sdpMLineIndex: sdpMlineIndex,
sdpMid: sdpMid
} as any);
});
hubConnection.on("ShowMessage", (message: string) => {
ShowMessage(message);

View File

@ -53,6 +53,8 @@ namespace Remotely.Shared.Enums
SetKeyStatesUp = 24,
[EnumMember(Value = "FrameReceived")]
FrameReceived = 25,
[EnumMember(Value = "ToggleWebRtcVideo")]
ToggleWebRtcVideo = 26,
[EnumMember(Value = "OpenFileTransferWindow")]
OpenFileTransferWindow = 27
}

View File

@ -2,8 +2,8 @@
{
public class IceServerModel
{
public string Urls { get; set; }
public string Credential { get; set; }
public string Username { get; set; }
public string Url { get; set; }
public string TurnPassword { get; set; }
public string TurnUsername { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using Remotely.Shared.Enums;
using System.Runtime.Serialization;
namespace Remotely.Shared.Models.RemoteControlDtos
{
[DataContract]
public class ToggleWebRtcVideoDto : BaseDto
{
[DataMember(Name = "ToggleOn")]
public bool ToggleOn { get; set; }
[DataMember(Name = "DtoType")]
public new BaseDtoType DtoType { get; } = BaseDtoType.ToggleWebRtcVideo;
}
}