Created interfaces for services. Reworked dependencies.

This commit is contained in:
Jared Goodwin 2019-12-13 19:44:08 -08:00
parent d729300857
commit 107ff34fcd
27 changed files with 364 additions and 282 deletions

View File

@ -6,10 +6,11 @@ using Remotely.Desktop.Unix.Controls;
using Remotely.Desktop.Unix.Services;
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Models;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Linux.Capture;
using Remotely.ScreenCast.Linux.Input;
using Remotely.ScreenCast.Linux.Services;
using Remotely.Shared.Models;
using Remotely.Shared.Services;
using System;
@ -35,11 +36,15 @@ namespace Remotely.Desktop.Unix.ViewModels
public MainWindowViewModel()
{
Current = this;
Conductor = new Conductor();
Conductor = new Conductor(
new X11Input(),
new LinuxAudioCapturer(),
new LinuxClipboardService(),
new LinuxScreenCaster());
Conductor.SessionIDChanged += SessionIDChanged;
Conductor.ViewerRemoved += ViewerRemoved;
Conductor.ViewerAdded += ViewerAdded;
Conductor.ClipboardTransferred += Conductor_ClipboardTransferred;
Conductor.ScreenCastRequested += ScreenCastRequested;
}
@ -136,11 +141,6 @@ namespace Remotely.Desktop.Unix.ViewModels
return;
}
if (OSUtils.IsLinux)
{
Conductor.SetMessageHandlers(new X11Input());
}
if (OSUtils.IsWindows)
{
return;
@ -201,15 +201,15 @@ namespace Remotely.Desktop.Unix.ViewModels
{
_ = Task.Run(async () =>
{
ICapturer capturer = null;
ICapturer capturer = null;
if (OSUtils.IsLinux)
{
capturer = new X11Capture();
}
await Conductor.CasterSocket.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
if (OSUtils.IsLinux)
{
capturer = new X11Capture();
}
await Conductor.CasterSocket.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List<string>() { screenCastRequest.ViewerID });
_ = ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer);
});
}
});

View File

@ -5,25 +5,19 @@ using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Models;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Win;
using Remotely.ScreenCast.Win.Capture;
using Remotely.ScreenCast.Win.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Security.Principal;
using System.Security.Claims;
using System.Windows.Input;
using System.Windows.Controls;
using Remotely.ScreenCast.Win.Services;
using Remotely.ScreenCast.Core.Interfaces;
namespace Remotely.Desktop.Win.ViewModels
{
@ -34,22 +28,24 @@ namespace Remotely.Desktop.Win.ViewModels
public MainWindowViewModel()
{
Current = this;
Conductor = new Conductor();
CursorIconWatcher = new CursorIconWatcher(Conductor);
CursorIconWatcher.OnChange += CursorIconWatcher_OnChange;
Conductor = new Conductor(
new WinInput(),
new WinAudioCapturer(),
new WinClipboardService(),
new WinScreenCaster(CursorIconWatcher));
Conductor.SessionIDChanged += SessionIDChanged;
Conductor.ViewerRemoved += ViewerRemoved;
Conductor.ViewerAdded += ViewerAdded;
Conductor.ScreenCastRequested += ScreenCastRequested;
Conductor.AudioToggled += AudioToggled;
Conductor.ClipboardTransferred += Conductor_ClipboardTransferred;
CursorIconWatcher = new CursorIconWatcher(Conductor);
CursorIconWatcher.OnChange += CursorIconWatcher_OnChange;
AudioCapturer = new AudioCapturer(Conductor);
}
public static MainWindowViewModel Current { get; private set; }
public AudioCapturer AudioCapturer { get; private set; }
public ICommand ChangeServerCommand
{
get
@ -162,7 +158,6 @@ namespace Remotely.Desktop.Win.ViewModels
return;
}
Conductor.SetMessageHandlers(new WinInput());
await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID);
await Conductor.CasterSocket.GetSessionID();
}
@ -186,27 +181,9 @@ namespace Remotely.Desktop.Win.ViewModels
}
}
private void AudioToggled(object sender, bool toggleOn)
{
if (toggleOn)
{
AudioCapturer.Start();
}
else
{
AudioCapturer.Stop();
}
}
private void Conductor_ClipboardTransferred(object sender, string transferredText)
{
Application.Current.Dispatcher.Invoke(() => {
Clipboard.SetText(transferredText);
});
}
private async void CursorIconWatcher_OnChange(object sender, CursorInfo cursor)
{
if (Conductor?.CasterSocket != null)
if (Conductor?.CasterSocket != null && Conductor?.Viewers?.Count > 0)
{
await Conductor?.CasterSocket?.SendCursorChange(cursor, Conductor.Viewers.Keys.ToList());
}
@ -238,7 +215,7 @@ namespace Remotely.Desktop.Win.ViewModels
capturer = new BitBltCapture();
}
await Conductor.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
_ = ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer);
});
}
});

View File

@ -12,16 +12,17 @@ using System.Text;
using System.Threading.Tasks;
using Remotely.Shared.Services;
using Remotely.Shared.Win32;
using Remotely.ScreenCast.Core.Interfaces;
namespace Remotely.ScreenCast.Core.Capture
{
public class ScreenCaster
{
public static async void BeginScreenCasting(string viewerID,
public static async Task BeginScreenCasting(string viewerID,
string requesterName,
ICapturer capturer,
Conductor conductor)
ICapturer capturer)
{
var conductor = Conductor.Current;
Viewer viewer;
byte[] encodedImageBytes;
@ -129,9 +130,9 @@ namespace Remotely.ScreenCast.Core.Capture
// Close if no one is viewing.
if (conductor.Viewers.Count == 0 && conductor.Mode == Enums.AppMode.Unattended)
{
await conductor.CasterSocket.Disconnect();
Environment.Exit(0);
}
}
}
}

View File

@ -12,18 +12,22 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Remotely.ScreenCast.Core.Interfaces;
namespace Remotely.ScreenCast.Core
{
public class Conductor
{
public static Conductor Current { get; private set; }
public event EventHandler<bool> AudioToggled;
public event EventHandler<string> ClipboardTransferred;
public event EventHandler<ScreenCastRequest> ScreenCastInitiated;
public Conductor(IKeyboardMouseInput keyboardMouse,
IAudioCapturer audioService,
IClipboardService clipboardService,
IScreenCaster screenCastService)
{
Current = this;
CasterSocket = new CasterSocket(this, keyboardMouse, screenCastService, audioService, clipboardService);
}
public event EventHandler<ScreenCastRequest> ScreenCastRequested;
public event EventHandler<string> SessionIDChanged;
@ -44,12 +48,7 @@ namespace Remotely.ScreenCast.Core
public ConcurrentDictionary<string, Viewer> Viewers { get; } = new ConcurrentDictionary<string, Viewer>();
public async Task Connect()
{
Connection = new HubConnectionBuilder()
.WithUrl($"{Host}/RCDeviceHub")
.AddMessagePackProtocol()
.Build();
await Connection.StartAsync();
await CasterSocket.Connect(Host);
}
public void ProcessArgs(string[] args)
@ -83,39 +82,20 @@ namespace Remotely.ScreenCast.Core
}
}
public void SetMessageHandlers(IKeyboardMouseInput keyboardMouse)
{
CasterSocket = new CasterSocket(Connection, this, keyboardMouse);
}
internal void InvokeAudioToggled(bool toggleOn)
{
AudioToggled?.Invoke(null, toggleOn);
}
internal void InvokeClipboardTransfer(string transferText)
{
ClipboardTransferred?.Invoke(null, transferText);
}
internal void InvokeScreenCastInitiated(ScreenCastRequest viewerIdAndRequesterName)
{
ScreenCastInitiated?.Invoke(null, viewerIdAndRequesterName);
}
internal void InvokeScreenCastRequested(ScreenCastRequest viewerIdAndRequesterName)
public void InvokeScreenCastRequested(ScreenCastRequest viewerIdAndRequesterName)
{
ScreenCastRequested?.Invoke(null, viewerIdAndRequesterName);
}
internal void InvokeSessionIDChanged(string sessionID)
public void InvokeSessionIDChanged(string sessionID)
{
SessionIDChanged?.Invoke(null, sessionID);
}
internal void InvokeViewerAdded(Viewer viewer)
public void InvokeViewerAdded(Viewer viewer)
{
ViewerAdded?.Invoke(null, viewer);
}
internal void InvokeViewerRemoved(string viewerID)
public void InvokeViewerRemoved(string viewerID)
{
ViewerRemoved?.Invoke(null, viewerID);
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Remotely.ScreenCast.Core.Interfaces
{
public interface IAudioCapturer
{
void ToggleAudio(bool toggleOn);
}
}

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Remotely.ScreenCast.Core.Capture
namespace Remotely.ScreenCast.Core.Interfaces
{
public interface ICapturer : IDisposable
{

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Remotely.ScreenCast.Core.Interfaces
{
public interface IClipboardService
{
void SetText(string clipboardText);
}
}

View File

@ -0,0 +1,13 @@
using Remotely.Shared.Models;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Remotely.ScreenCast.Core.Interfaces
{
public interface IScreenCaster
{
Task BeginScreenCasting(ScreenCastRequest screenCastRequest);
}
}

View File

@ -1,4 +1,5 @@
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Drawing;

View File

@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

View File

@ -14,22 +14,51 @@ using System.Net;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Core.Input;
using Remotely.Shared.Win32;
using Remotely.ScreenCast.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
namespace Remotely.ScreenCast.Core.Sockets
{
public class CasterSocket
{
public CasterSocket(HubConnection hubConnection, Conductor conductor, IKeyboardMouseInput keyboardMouseInput)
public CasterSocket(
Conductor conductor,
IKeyboardMouseInput keyboardMouseInput,
IScreenCaster screenCastService,
IAudioCapturer audioService,
IClipboardService clipboardService)
{
Connection = hubConnection;
Conductor = conductor;
KeyboardMouseInput = keyboardMouseInput;
ApplyConnectionHandlers();
ClipboardService = clipboardService;
AudioService = audioService;
ScreenCastService = screenCastService;
}
public IScreenCaster ScreenCastService { get; }
private IAudioCapturer AudioService { get; }
private IClipboardService ClipboardService { get; }
private Conductor Conductor { get; }
private HubConnection Connection { get; set; }
private IKeyboardMouseInput KeyboardMouseInput { get; }
public async Task Connect(string host)
{
Connection = new HubConnectionBuilder()
.WithUrl($"{host}/RCDeviceHub")
.AddMessagePackProtocol()
.Build();
ApplyConnectionHandlers();
await Connection.StartAsync();
}
public async Task Disconnect()
{
await Connection.StopAsync();
await Connection.DisposeAsync();
}
public Conductor Conductor { get; }
public IKeyboardMouseInput KeyboardMouseInput { get; }
private HubConnection Connection { get; }
public async Task GetSessionID()
{
await Connection.SendAsync("GetSessionID");
@ -44,7 +73,6 @@ namespace Remotely.ScreenCast.Core.Sockets
{
await Connection.SendAsync("NotifyViewersRelaunchedScreenCasterReady", viewerIDs);
}
public async Task SendAudioSample(byte[] buffer, List<string> viewerIDs)
{
await Connection.SendAsync("SendAudioSample", buffer, viewerIDs);
@ -104,7 +132,7 @@ namespace Remotely.ScreenCast.Core.Sockets
{
if (Conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl)
{
Conductor.InvokeClipboardTransfer(transferText);
ClipboardService.SetText(transferText);
}
}
catch (Exception ex)
@ -125,7 +153,7 @@ namespace Remotely.ScreenCast.Core.Sockets
{
try
{
Conductor.InvokeScreenCastInitiated(new ScreenCastRequest() { ViewerID = viewerID, RequesterName = requesterName });
ScreenCastService.BeginScreenCasting(new ScreenCastRequest() { ViewerID = viewerID, RequesterName = requesterName });
}
catch (Exception ex)
{
@ -249,7 +277,7 @@ namespace Remotely.ScreenCast.Core.Sockets
{
if (Conductor.Viewers.TryGetValue(viewerID, out var viewer) && viewer.HasControl)
{
Conductor.InvokeAudioToggled(toggleOn);
AudioService.ToggleAudio(toggleOn);
}
});

View File

@ -1,4 +1,5 @@
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Linux.X11Interop;
using System;

View File

@ -1,17 +1,8 @@
using Remotely.Shared.Models;
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Linux.Capture;
using Remotely.ScreenCast.Linux.Input;
using Remotely.ScreenCast.Linux.X11Interop;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using Remotely.ScreenCast.Linux.Services;
namespace Remotely.ScreenCast.Linux
{
@ -23,13 +14,15 @@ namespace Remotely.ScreenCast.Linux
try
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Conductor = new Conductor();
Conductor = new Conductor(
new X11Input(),
new LinuxAudioCapturer(),
new LinuxClipboardService(),
new LinuxScreenCaster());
Conductor.ProcessArgs(args);
Conductor.Connect().ContinueWith(async (task) =>
{
Conductor.SetMessageHandlers(new X11Input());
Conductor.ScreenCastInitiated += ScreenCastInitiated;
Conductor.ClipboardTransferred += Conductor_ClipboardTransferred;
await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID);
await Conductor.CasterSocket.NotifyRequesterUnattendedReady(Conductor.RequesterID);
Conductor.IdleTimer = new IdleTimer(Conductor.Viewers);
@ -45,43 +38,6 @@ namespace Remotely.ScreenCast.Linux
}
}
private static void Conductor_ClipboardTransferred(object sender, string transferredText)
{
var tempPath = Path.GetTempFileName();
File.WriteAllText(tempPath, transferredText);
try
{
var psi = new ProcessStartInfo("bash", $"-c \"cat {tempPath} | xclip -i -selection clipboard\"")
{
WindowStyle = ProcessWindowStyle.Hidden
};
var proc = Process.Start(psi);
proc.WaitForExit();
}
catch (Exception ex)
{
Logger.Write(ex);
}
finally
{
File.Delete(tempPath);
}
}
private static async void ScreenCastInitiated(object sender, ScreenCastRequest screenCastRequest)
{
try
{
var capturer = new X11Capture();
await Conductor.CasterSocket.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
}
catch (Exception ex)
{
Logger.Write(ex);
}
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{

View File

@ -43,4 +43,8 @@
<ProjectReference Include="..\Shared\Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Input\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
using Remotely.ScreenCast.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;
namespace Remotely.ScreenCast.Linux.Services
{
public class LinuxAudioCapturer : IAudioCapturer
{
public void ToggleAudio(bool toggleOn)
{
// Not implemented.
}
}
}

View File

@ -0,0 +1,37 @@
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace Remotely.ScreenCast.Linux.Services
{
public class LinuxClipboardService : IClipboardService
{
public void SetText(string clipboardText)
{
var tempPath = Path.GetTempFileName();
File.WriteAllText(tempPath, clipboardText);
try
{
var psi = new ProcessStartInfo("bash", $"-c \"cat {tempPath} | xclip -i -selection clipboard\"")
{
WindowStyle = ProcessWindowStyle.Hidden
};
var proc = Process.Start(psi);
proc.WaitForExit();
}
catch (Exception ex)
{
Logger.Write(ex);
}
finally
{
File.Delete(tempPath);
}
}
}
}

View File

@ -0,0 +1,31 @@
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Linux.Capture;
using Remotely.Shared.Models;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
namespace Remotely.ScreenCast.Linux.Services
{
public class LinuxScreenCaster : IScreenCaster
{
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)
{
try
{
var capturer = new X11Capture();
await Conductor.Current.CasterSocket.SendCursorChange(new CursorInfo(null, Point.Empty, "default"), new List<string>() { screenCastRequest.ViewerID });
_ = ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer);
}
catch (Exception ex)
{
Logger.Write(ex);
}
}
}
}

View File

@ -9,7 +9,7 @@ using System.Linq;
using Remotely.ScreenCast.Linux.Capture;
using Remotely.ScreenCast.Core.Models;
namespace Remotely.ScreenCast.Linux.Input
namespace Remotely.ScreenCast.Linux.Services
{
public class X11Input : IKeyboardMouseInput
{

View File

@ -8,12 +8,9 @@ using System.Windows.Forms;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using Remotely.ScreenCast.Core.Services;
using System.Threading;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
namespace Remotely.ScreenCast.Win.Capture
{

View File

@ -1,4 +1,4 @@
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
using Remotely.ScreenCast.Core.Services;
using SharpDX;
using SharpDX.Direct3D11;

View File

@ -1,37 +1,18 @@
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
using Remotely.Shared.Models;
using Remotely.Shared.Models;
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Enums;
using Remotely.ScreenCast.Core.Models;
using Remotely.ScreenCast.Core.Sockets;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Win.Capture;
using Remotely.ScreenCast.Win.Input;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Remotely.Shared.Win32;
using NAudio.Wave;
using Remotely.Shared.Services;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;
using Remotely.ScreenCast.Win.Services;
namespace Remotely.ScreenCast.Win
{
public class Program
public class Program
{
public static AudioCapturer AudioCapturer { get; private set; }
public static Conductor Conductor { get; private set; }
public static CursorIconWatcher CursorIconWatcher { get; private set; }
public static async void CursorIconWatcher_OnChange(object sender, CursorInfo cursor)
@ -47,18 +28,16 @@ namespace Remotely.ScreenCast.Win
try
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Conductor = new Conductor();
CursorIconWatcher = new CursorIconWatcher(Conductor);
Conductor = new Conductor(
new WinInput(),
new WinAudioCapturer(),
new WinClipboardService(),
new WinScreenCaster(CursorIconWatcher));
Conductor.ProcessArgs(args);
Conductor.ScreenCastInitiated += ScreenCastInitiated;
Conductor.AudioToggled += AudioToggled;
Conductor.ClipboardTransferred += Conductor_ClipboardTransferred;
Conductor.Connect().ContinueWith(async (task) =>
{
Conductor.SetMessageHandlers(new WinInput());
AudioCapturer = new AudioCapturer(Conductor);
CursorIconWatcher = new CursorIconWatcher(Conductor);
CursorIconWatcher.OnChange += CursorIconWatcher_OnChange;
await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID);
CheckInitialDesktop();
@ -78,17 +57,7 @@ namespace Remotely.ScreenCast.Win
}
}
private static void AudioToggled(object sender, bool toggledOn)
{
if (toggledOn)
{
AudioCapturer.Start();
}
else
{
AudioCapturer.Stop();
}
}
private static async Task CheckForRelaunch()
{
@ -128,16 +97,6 @@ namespace Remotely.ScreenCast.Win
}
}
private static void Conductor_ClipboardTransferred(object sender, string transferredText)
{
var thread = new Thread(() =>
{
Clipboard.SetText(transferredText);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Logger.Write((Exception)e.ExceptionObject);
@ -157,27 +116,5 @@ namespace Remotely.ScreenCast.Win
await Task.Delay(1000);
}
}
private static async void ScreenCastInitiated(object sender, ScreenCastRequest screenCastRequest)
{
ICapturer capturer;
try
{
if (Conductor.Viewers.Count == 0)
{
capturer = new DXCapture();
}
else
{
capturer = new BitBltCapture();
}
}
catch (Exception ex)
{
Logger.Write(ex);
capturer = new BitBltCapture();
}
await Conductor.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { screenCastRequest.ViewerID });
ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer, Conductor);
}
}
}

View File

@ -234,11 +234,13 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Capture\AudioCapturer.cs" />
<Compile Include="Services\WinAudioCapturer.cs" />
<Compile Include="Capture\BitBltCapture.cs" />
<Compile Include="Capture\CursorIconWatcher.cs" />
<Compile Include="Services\WinClipboardService.cs" />
<Compile Include="Services\CursorIconWatcher.cs" />
<Compile Include="Capture\DXCapture.cs" />
<Compile Include="Input\WinInput.cs" />
<Compile Include="Services\WinScreenCaster.cs" />
<Compile Include="Services\WinInput.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

View File

@ -14,7 +14,7 @@ using System.Windows.Forms;
using Remotely.Shared.Win32;
using Remotely.Shared.Models;
namespace Remotely.ScreenCast.Win.Capture
namespace Remotely.ScreenCast.Win.Services
{
/// <summary>
/// A class that can be used to watch for cursor icon changes.

View File

@ -8,23 +8,58 @@ using System.Threading.Tasks;
using System.Timers;
using NAudio.Wave;
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Interfaces;
namespace Remotely.ScreenCast.Win.Capture
namespace Remotely.ScreenCast.Win.Services
{
public class AudioCapturer
public class WinAudioCapturer : IAudioCapturer
{
public AudioCapturer(Conductor conductor)
{
Conductor = conductor;
}
private WasapiLoopbackCapture Capturer { get; set; }
private WaveFormat TargetFormat { get; set; }
private Conductor Conductor { get; set; }
private List<byte> TempBuffer { get; set; } = new List<byte>();
private Stopwatch SendTimer { get; set; }
private WaveFormat TargetFormat { get; set; }
private List<byte> TempBuffer { get; set; } = new List<byte>();
public void ToggleAudio(bool toggleOn)
{
if (toggleOn)
{
Start();
}
else
{
Stop();
}
}
public void Start()
private async void SendTempBuffer()
{
if (TempBuffer.Count == 0)
{
return;
}
using (var ms1 = new MemoryStream())
{
using (var wfw = new WaveFileWriter(ms1, Capturer.WaveFormat))
{
wfw.Write(TempBuffer.ToArray(), 0, TempBuffer.Count);
}
TempBuffer.Clear();
// Resample to 16-bit so Firefox will play it.
using (var ms2 = new MemoryStream(ms1.ToArray()))
using (var wfr = new WaveFileReader(ms2))
using (var ms3 = new MemoryStream())
{
using (var resampler = new MediaFoundationResampler(wfr, TargetFormat))
{
WaveFileWriter.WriteWavFileToStream(ms3, resampler);
}
await Conductor.Current.CasterSocket.SendAudioSample(ms3.ToArray(), Program.Conductor.Viewers.Keys.ToList());
}
}
}
private void Start()
{
try
{
@ -63,37 +98,7 @@ namespace Remotely.ScreenCast.Win.Capture
}
catch { }
}
private async void SendTempBuffer()
{
if (TempBuffer.Count == 0)
{
return;
}
using (var ms1 = new MemoryStream())
{
using (var wfw = new WaveFileWriter(ms1, Capturer.WaveFormat))
{
wfw.Write(TempBuffer.ToArray(), 0, TempBuffer.Count);
}
TempBuffer.Clear();
// Resample to 16-bit so Firefox will play it.
using (var ms2 = new MemoryStream(ms1.ToArray()))
using (var wfr = new WaveFileReader(ms2))
using (var ms3 = new MemoryStream())
{
using (var resampler = new MediaFoundationResampler(wfr, TargetFormat))
{
WaveFileWriter.WriteWavFileToStream(ms3, resampler);
}
await Conductor.CasterSocket.SendAudioSample(ms3.ToArray(), Conductor.Viewers.Keys.ToList());
}
}
}
public void Stop()
private void Stop()
{
Capturer.StopRecording();
SendTimer.Reset();

View File

@ -0,0 +1,24 @@
using Remotely.ScreenCast.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Remotely.ScreenCast.Win.Services
{
public class WinClipboardService : IClipboardService
{
public void SetText(string clipboardText)
{
var thread = new Thread(() =>
{
Clipboard.SetText(clipboardText);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
}
}

View File

@ -4,8 +4,9 @@ using System;
using Remotely.Shared.Win32;
using static Remotely.Shared.Win32.User32;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core.Interfaces;
namespace Remotely.ScreenCast.Win.Input
namespace Remotely.ScreenCast.Win.Services
{
public class WinInput : IKeyboardMouseInput
{

View File

@ -0,0 +1,49 @@
using Remotely.ScreenCast.Core.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Remotely.ScreenCast.Core.Enums;
using Remotely.ScreenCast.Core.Services;
using Remotely.ScreenCast.Core.Capture;
using Remotely.ScreenCast.Core;
using Remotely.ScreenCast.Core.Models;
using Remotely.Shared.Models;
using Remotely.ScreenCast.Win.Capture;
namespace Remotely.ScreenCast.Win.Services
{
public class WinScreenCaster : IScreenCaster
{
public WinScreenCaster(CursorIconWatcher cursorIconWatcher)
{
CursorIconWatcher = cursorIconWatcher;
}
public CursorIconWatcher CursorIconWatcher { get; }
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)
{
ICapturer capturer;
try
{
if (Conductor.Current.Viewers.Count == 0)
{
capturer = new DXCapture();
}
else
{
capturer = new BitBltCapture();
}
}
catch (Exception ex)
{
Logger.Write(ex);
capturer = new BitBltCapture();
}
await Conductor.Current.CasterSocket.SendCursorChange(CursorIconWatcher.GetCurrentCursor(), new List<string>() { screenCastRequest.ViewerID });
_ = ScreenCaster.BeginScreenCasting(screenCastRequest.ViewerID, screenCastRequest.RequesterName, capturer);
}
}
}