mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Created interfaces for services. Reworked dependencies.
This commit is contained in:
parent
d729300857
commit
107ff34fcd
@ -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);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -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);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
11
ScreenCast.Core/Interfaces/IAudioCapturer.cs
Normal file
11
ScreenCast.Core/Interfaces/IAudioCapturer.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
11
ScreenCast.Core/Interfaces/IClipboardService.cs
Normal file
11
ScreenCast.Core/Interfaces/IClipboardService.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
13
ScreenCast.Core/Interfaces/IScreenCaster.cs
Normal file
13
ScreenCast.Core/Interfaces/IScreenCaster.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using Remotely.ScreenCast.Core.Capture;
|
||||
using Remotely.ScreenCast.Core.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -43,4 +43,8 @@
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Input\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
15
ScreenCast.Linux/Services/LinuxAudioCapturer.cs
Normal file
15
ScreenCast.Linux/Services/LinuxAudioCapturer.cs
Normal 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.
|
||||
}
|
||||
}
|
||||
}
|
||||
37
ScreenCast.Linux/Services/LinuxClipboardService.cs
Normal file
37
ScreenCast.Linux/Services/LinuxClipboardService.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
ScreenCast.Linux/Services/LinuxScreenCaster.cs
Normal file
31
ScreenCast.Linux/Services/LinuxScreenCaster.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Remotely.ScreenCast.Core.Capture;
|
||||
using Remotely.ScreenCast.Core.Interfaces;
|
||||
using Remotely.ScreenCast.Core.Services;
|
||||
using SharpDX;
|
||||
using SharpDX.Direct3D11;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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.
|
||||
@ -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();
|
||||
24
ScreenCast.Win/Services/WinClipboardService.cs
Normal file
24
ScreenCast.Win/Services/WinClipboardService.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
49
ScreenCast.Win/Services/WinScreenCaster.cs
Normal file
49
ScreenCast.Win/Services/WinScreenCaster.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user