diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2020-03-03 18:56:58 +0200 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2020-03-03 18:56:58 +0200 |
| commit | c38f1c80f1fbdfdb758c5a0b93d045a9a5b526ad (patch) | |
| tree | 20cc57b06f4260b6f86fdaca04129e1a8ace53cd /Software | |
| parent | 1b0bdf6f8148e9cc4e7e07e41e9e2d75039c1349 (diff) | |
| download | Tango-c38f1c80f1fbdfdb758c5a0b93d045a9a5b526ad.tar.gz Tango-c38f1c80f1fbdfdb758c5a0b93d045a9a5b526ad.zip | |
Machine Studio v4.1.2
PPC v1.1.5
Added BYPASS_ROCKERS to SQLExaminer config.
Started integrating FSE Remote/Console To PPC.
Added support for generic continuous request.
Diffstat (limited to 'Software')
42 files changed, 848 insertions, 85 deletions
diff --git a/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Clipping/BitmapCliper.cs b/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Clipping/BitmapCliper.cs index 4f93eeb66..5bd8beaa3 100644 --- a/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Clipping/BitmapCliper.cs +++ b/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Clipping/BitmapCliper.cs @@ -30,8 +30,8 @@ namespace Tango.RemoteDesktop.Clipping //determine top for (int i = 0; i < rgbValues.Length; i++) { - int color = rgbValues[i] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[i] & 0xffffff; + if (color != 0x0) { int r = i / bd.Width; int c = i % bd.Width; @@ -53,8 +53,8 @@ namespace Tango.RemoteDesktop.Clipping //determine bottom for (int i = rgbValues.Length - 1; i >= 0; i--) { - int color = rgbValues[i] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[i] & 0xffffff; + if (color != 0x0) { int r = i / bd.Width; int c = i % bd.Width; @@ -79,8 +79,8 @@ namespace Tango.RemoteDesktop.Clipping //determine left for (int c = 0; c < left; c++) { - int color = rgbValues[r * bd.Width + c] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[r * bd.Width + c] & 0xffffff; + if (color != 0x0) { if (left > c) { @@ -93,8 +93,8 @@ namespace Tango.RemoteDesktop.Clipping //determine right for (int c = bd.Width - 1; c > right; c--) { - int color = rgbValues[r * bd.Width + c] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[r * bd.Width + c] & 0xffffff; + if (color != 0x0) { if (right < c) { @@ -128,9 +128,7 @@ namespace Tango.RemoteDesktop.Clipping //create new image Bitmap newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb); - BitmapData nbd - = newImage.LockBits(new Rectangle(0, 0, width, height), - ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + BitmapData nbd = newImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(imgData, 0, nbd.Scan0, imgData.Length); newImage.UnlockBits(nbd); @@ -140,5 +138,67 @@ namespace Tango.RemoteDesktop.Clipping Bounds = new Rectangle(left, top, width, height) }; } + + public static ClipResult ClipBitmap2(Bitmap bmp) + { + // Initialize variables + //var cropColor = Color.White; + + var bottom = 0; + var left = bmp.Width; // Set the left crop point to the width so that the logic below will set the left value to the first non crop color pixel it comes across. + var right = 0; + var top = bmp.Height; // Set the top crop point to the height so that the logic below will set the top value to the first non crop color pixel it comes across. + + var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); + + unsafe + { + var dataPtr = (byte*)bmpData.Scan0; + + for (var y = 0; y < bmp.Height; y++) + { + for (var x = 0; x < bmp.Width; x++) + { + var rgbPtr = dataPtr + (x * 4); + + //var b = rgbPtr[0]; + //var g = rgbPtr[1]; + //var r = rgbPtr[2]; + var a = rgbPtr[3]; + + // If any of the pixel RGBA values don't match and the crop color is not transparent, or if the crop color is transparent and the pixel A value is not transparent + if (a > 0) + { + if (x < left) + left = x; + + if (x >= right) + right = x + 1; + + if (y < top) + top = y; + + if (y >= bottom) + bottom = y + 1; + } + } + + dataPtr += bmpData.Stride; + } + } + + bmp.UnlockBits(bmpData); + + if (left < right && top < bottom) + { + return new ClipResult() + { + Bitmap = bmp.Clone(new Rectangle(left, top, right - left, bottom - top), bmp.PixelFormat), + Bounds = new Rectangle(left, top, right - left, bottom - top), + }; + } + + return null; // Entire image should be cropped, so just return null + } } } diff --git a/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj b/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj index f760b43dc..de790ca10 100644 --- a/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj +++ b/Software/Experiments/Tango.RemoteDesktop/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj @@ -35,16 +35,16 @@ <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> <Reference Include="SharpDX"> - <HintPath>..\..\..\..\..\..\DATA\Development\WpfVideoTools\WpfVideoTools\Resources\Referenced Assemblies\SharpDX.dll</HintPath> + <HintPath>..\..\..\Visual_Studio\Referenced Assemblies\SharpDX\SharpDX.dll</HintPath> </Reference> <Reference Include="SharpDX.Direct3D11"> - <HintPath>..\..\..\..\..\..\DATA\Development\WpfVideoTools\WpfVideoTools\Resources\Referenced Assemblies\SharpDX.Direct3D11.dll</HintPath> + <HintPath>..\..\..\Visual_Studio\Referenced Assemblies\SharpDX\SharpDX.Direct3D11.dll</HintPath> </Reference> <Reference Include="SharpDX.DXGI"> - <HintPath>..\..\..\..\..\..\DATA\Development\WpfVideoTools\WpfVideoTools\Resources\Referenced Assemblies\SharpDX.DXGI.dll</HintPath> + <HintPath>..\..\..\Visual_Studio\Referenced Assemblies\SharpDX\SharpDX.DXGI.dll</HintPath> </Reference> <Reference Include="SharpDX.Mathematics"> - <HintPath>..\..\..\..\..\..\DATA\Development\WpfVideoTools\WpfVideoTools\Resources\Referenced Assemblies\SharpDX.Mathematics.dll</HintPath> + <HintPath>..\..\..\Visual_Studio\Referenced Assemblies\SharpDX\SharpDX.Mathematics.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> diff --git a/Software/Experiments/Tango.RemoteDesktop/WpfApp1/MainWindow.xaml.cs b/Software/Experiments/Tango.RemoteDesktop/WpfApp1/MainWindow.xaml.cs index 6bd0b7a23..7953e9666 100644 --- a/Software/Experiments/Tango.RemoteDesktop/WpfApp1/MainWindow.xaml.cs +++ b/Software/Experiments/Tango.RemoteDesktop/WpfApp1/MainWindow.xaml.cs @@ -40,8 +40,9 @@ namespace WpfApp1 _engine = new RasterScreenCaptureEngine() { - CaptureRegion = new CaptureRegion(0, 0, 1280, 800) + CaptureRegion = new CaptureRegion(1920 + 1920, 0, 1280, 800) }; + _engine.CaptureMethod = new GdiScreenCapture(); _engine.FrameRate = 5; //Per second _engine.CaptureCursor = true; _engine.FrameReceived += _engine_FrameReceived; diff --git a/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip index 7a98315e6..a1d8353fe 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/Machine Studio Installer.aip @@ -16,10 +16,10 @@ <ROW Property="ARPCOMMENTS" Value="This installer database contains the logic and data required to install [|ProductName]." ValueLocId="*"/> <ROW Property="ARPNOREPAIR" MultiBuildValue="DefaultBuild:1"/> <ROW Property="Manufacturer" Value="Twine"/> - <ROW Property="ProductCode" Value="1033:{26780F4F-4EA2-42CF-BB23-D5E8D0B5D41A} " Type="16"/> + <ROW Property="ProductCode" Value="1033:{996DE894-BBBE-4C3F-B7B3-FA81F2D5C6A1} " Type="16"/> <ROW Property="ProductLanguage" Value="1033"/> <ROW Property="ProductName" Value="Machine Studio"/> - <ROW Property="ProductVersion" Value="4.1.1.0" Type="32"/> + <ROW Property="ProductVersion" Value="4.1.2.0" Type="32"/> <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/> <ROW Property="UpgradeCode" Value="{CBEE5CAE-7C5A-4280-98DE-AA98113764E4}"/> <ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/> @@ -810,7 +810,7 @@ <ROW Action="AI_DetectSoftware" Sequence="101"/> </COMPONENT> <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent"> - <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="..\Build\Installers\Machine Studio\Release" PackageFileName="Machine Studio Installer_v4.0.9" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="Machine Studio Installer_v4.1.1"/> + <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="..\Build\Installers\Machine Studio\Release" PackageFileName="Machine Studio Installer_v4.0.9" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="Machine Studio Installer_v4.1.2"/> </COMPONENT> <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent"> <ROW Path="<AI_DICTS>ui.ail"/> diff --git a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt Binary files differindex a603ff06b..993ced97e 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt +++ b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt diff --git a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip index bae639a22..e3bea2a1b 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip @@ -18,10 +18,10 @@ <ROW Property="ARPNOREPAIR" Value="1" MultiBuildValue="DefaultBuild:1"/> <ROW Property="ARPSYSTEMCOMPONENT" Value="1"/> <ROW Property="Manufacturer" Value="Twine"/> - <ROW Property="ProductCode" Value="1033:{594ACB06-E2BD-4948-96F6-0501BB029436} " Type="16"/> + <ROW Property="ProductCode" Value="1033:{FE1D7090-44C5-428B-A09C-787D47214B63} " Type="16"/> <ROW Property="ProductLanguage" Value="1033"/> <ROW Property="ProductName" Value="Tango"/> - <ROW Property="ProductVersion" Value="1.1.4.0" Type="32"/> + <ROW Property="ProductVersion" Value="1.1.5.0" Type="32"/> <ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/> <ROW Property="UpgradeCode" Value="{F8EAB8B4-FD57-45B7-8307-D52DF760273D}"/> <ROW Property="WindowsType9X" MultiBuildValue="DefaultBuild:Windows 9x/ME" ValueLocId="-"/> @@ -142,6 +142,7 @@ <ROW Component="Tango.ColorLib_v1.dll" ComponentId="{2144DE18-A79A-4811-ABBD-080FB91B0977}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.ColorLib_v1.dll"/> <ROW Component="Tango.ColorLib_v2.dll" ComponentId="{BF397BA6-85CE-4A7A-9C1B-76F8FD3210D8}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.ColorLib_v2.dll"/> <ROW Component="Tango.ColorLib_v3.dll" ComponentId="{3264F593-EBB0-4AAB-BC34-AF382E485620}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.ColorLib_v3.dll"/> + <ROW Component="Tango.Console.dll" ComponentId="{9F335170-14FF-472E-B3A5-1AAFA7C3067B}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Console.dll"/> <ROW Component="Tango.Core.dll" ComponentId="{4DF6644D-C4EC-419D-9622-2F79BBBC5A3F}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Core.dll"/> <ROW Component="Tango.Documents.dll" ComponentId="{1FFC36F6-BF53-47D7-A4DB-92ABBDCC127B}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Documents.dll"/> <ROW Component="Tango.DragAndDrop.dll" ComponentId="{E9081F1C-7A40-402F-83B4-62F4E3D5E4BE}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.DragAndDrop.dll"/> @@ -406,6 +407,8 @@ <ROW File="Tango.PPC.Browser.pdb" Component_="Tango.PPC.Browser.dll" FileName="TANGO~16.PDB|Tango.PPC.Browser.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\PPC\Release\Tango.PPC.Browser.pdb" SelfReg="false"/> <ROW File="Microsoft.AspNet.SignalR.Client.dll" Component_="Microsoft.AspNet.SignalR.Client.dll" FileName="MICRO~36.DLL|Microsoft.AspNet.SignalR.Client.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\PPC\Release\Microsoft.AspNet.SignalR.Client.dll" SelfReg="false"/> <ROW File="Microsoft.AspNet.SignalR.Client.pdb" Component_="Microsoft.AspNet.SignalR.Client.dll" FileName="MICROS~2.PDB|Microsoft.AspNet.SignalR.Client.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\PPC\Release\Microsoft.AspNet.SignalR.Client.pdb" SelfReg="false"/> + <ROW File="Tango.Console.dll" Component_="Tango.Console.dll" FileName="TANGOC~7.DLL|Tango.Console.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\PPC\Release\Tango.Console.dll" SelfReg="false"/> + <ROW File="Tango.Console.pdb" Component_="Tango.Console.dll" FileName="TANGOC~4.PDB|Tango.Console.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\PPC\Release\Tango.Console.pdb" SelfReg="false"/> <ATTRIBUTE name="DontAddFileAttributes" value="true"/> </COMPONENT> <COMPONENT cid="caphyon.advinst.msicomp.BootstrOptComponent"> @@ -415,7 +418,7 @@ <ROW Action="AI_DetectSoftware" Sequence="101"/> </COMPONENT> <COMPONENT cid="caphyon.advinst.msicomp.BuildComponent"> - <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="..\Build\Installers\PPC" PackageFileName="PPC Installer v1.0.3" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="PPC Installer_v1.1.4"/> + <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="..\Build\Installers\PPC" PackageFileName="PPC Installer v1.0.3" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="PPC Installer_v1.1.5"/> </COMPONENT> <COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent"> <ROW Path="<AI_DICTS>ui.ail"/> @@ -656,6 +659,7 @@ <ROW Feature_="MainFeature" Component_="vcruntime140d.dll"/> <ROW Feature_="MainFeature" Component_="APPDIR"/> <ROW Feature_="MainFeature" Component_="Microsoft.AspNet.SignalR.Client.dll"/> + <ROW Feature_="MainFeature" Component_="Tango.Console.dll"/> </COMPONENT> <COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent"> <ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1502"/> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj index bcb1242a3..75cae76a9 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj @@ -61,6 +61,23 @@ <Reference Include="System" /> <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Data" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Reactive.Core, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll</HintPath> + </Reference> + <Reference Include="System.Reactive.Interfaces, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll</HintPath> + </Reference> + <Reference Include="System.Reactive.Linq, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\System.Reactive.Linq.3.1.1\lib\net46\System.Reactive.Linq.dll</HintPath> + </Reference> + <Reference Include="System.Reactive.PlatformServices, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\System.Reactive.PlatformServices.3.1.1\lib\net46\System.Reactive.PlatformServices.dll</HintPath> + </Reference> + <Reference Include="System.Reactive.Windows.Threading, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll</HintPath> + </Reference> + <Reference Include="System.Windows" /> <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\..\..\packages\ControlzEx.3.0.2.4\lib\net45\System.Windows.Interactivity.dll</HintPath> </Reference> @@ -111,8 +128,12 @@ <Generator>ResXFileCodeGenerator</Generator> <LastGenOutput>Resources.Designer.cs</LastGenOutput> </EmbeddedResource> - <None Include="app.config" /> - <None Include="packages.config" /> + <None Include="app.config"> + <SubType>Designer</SubType> + </None> + <None Include="packages.config"> + <SubType>Designer</SubType> + </None> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.Designer.cs</LastGenOutput> @@ -147,6 +168,10 @@ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project> <Name>Tango.PMR</Name> </ProjectReference> + <ProjectReference Include="..\..\..\Tango.RemoteDesktop\Tango.RemoteDesktop.csproj"> + <Project>{a78068d4-2061-4376-8ede-583d8d880dec}</Project> + <Name>Tango.RemoteDesktop</Name> + </ProjectReference> <ProjectReference Include="..\..\..\Tango.Settings\Tango.Settings.csproj"> <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> <Name>Tango.Settings</Name> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/RemoteDesktopViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/RemoteDesktopViewVM.cs index 32a85ada6..eb5d57447 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/RemoteDesktopViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/RemoteDesktopViewVM.cs @@ -1,13 +1,109 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Tango.Core.Commands; +using Tango.Core.Threading; using Tango.FSE.Common; +using Tango.RemoteDesktop.Frames; +using Tango.RemoteDesktop.Network; namespace Tango.FSE.PPCConsole.ViewModels { public class RemoteDesktopViewVM : FSEViewModel { + private RasterFrame _currentFrame; + + private BitmapSource _source; + public BitmapSource Source + { + get { return _source; } + set { _source = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand StartCommand { get; set; } + public RelayCommand StopCommand { get; set; } + + public RemoteDesktopViewVM() + { + StartCommand = new RelayCommand(StartRemoteDesktop, () => MachineProvider.IsConnected); + StopCommand = new RelayCommand(StopRemoteDesktop); + } + + public override void OnApplicationStarted() + { + base.OnApplicationStarted(); + + MachineProvider.MachineConnected += (_, __) => InvalidateRelayCommands(); + MachineProvider.MachineDisconnected += (_, __) => InvalidateRelayCommands(); + } + + private void StartRemoteDesktop() + { + SequencerThread<StartRemoteDesktopSessionResponse> sequencer = null; + sequencer = new SequencerThread<StartRemoteDesktopSessionResponse>((response) => + { + if (response.Packet == null) + { + sequencer.FrameRate = 1000 / response.FrameRate; + return; //Returned just to notice that there was no timeout.. + } + + try + { + if (!response.Packet.IsPartial) + { + using (MemoryStream ms = new MemoryStream(response.Packet.Bitmap)) + { + if (_currentFrame != null) + { + _currentFrame.Dispose(); + } + + _currentFrame = new RasterFrame(new Bitmap(ms)); + } + } + else + { + using (MemoryStream ms = new MemoryStream(response.Packet.Bitmap)) + { + var diffFrame = new RasterFrame(new Bitmap(ms), response.Packet.PartialRegion.Left, response.Packet.PartialRegion.Top); + diffFrame.Apply(_currentFrame); + diffFrame.Dispose(); + } + } + + Source = _currentFrame.ToBitmapSource(); + } + catch (Exception ex) + { + Debug.WriteLine($"Error on remote desktop packet received: {ex.Message}"); + } + }); + + sequencer.Start(); + + MachineProvider.MachineOperator.SendGenericContinuousRequest<StartRemoteDesktopSessionRequest, StartRemoteDesktopSessionResponse>(new StartRemoteDesktopSessionRequest() { }, new Transport.TransportContinuousRequestConfig() + { + ContinuousTimeout = TimeSpan.FromSeconds(30), + }).Subscribe((response) => + { + sequencer.Push(response); + + }, (ex) => + { + Debug.WriteLine(ex); + }, () => { }); + } + + private void StopRemoteDesktop() + { + + } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml index 4e2afa884..9514db919 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml @@ -11,8 +11,8 @@ mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:ConsoleViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.ConsoleViewVM}"> <Grid> - <Border Background="Black" CornerRadius="10" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> - <console:ConsoleControl Margin="10" BorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsBackground="{StaticResource FSE_PrimaryBackgroundBrush}" SuggestionsBorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsForeground="Silver" DataContext="{Binding ConsoleVM}"> + <Border Background="#121212" CornerRadius="10" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> + <console:ConsoleControl Background="#121212" Margin="10" BorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsBackground="{StaticResource FSE_PrimaryBackgroundBrush}" SuggestionsBorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsForeground="Silver" DataContext="{Binding ConsoleVM}"> <console:ConsoleControl.BusyTemplate> <DataTemplate> <ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" IsIndeterminate="True" Width="16" Height="16" /> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml index 8d986a04a..b6a4eec62 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml @@ -11,27 +11,41 @@ mc:Ignorable="d" d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:RemoteDesktopViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.RemoteDesktopViewVM}"> <Grid> - <Border CornerRadius="15" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> - <Border CornerRadius="1" BorderThickness="30"> - <Border.BorderBrush> - <LinearGradientBrush> - <GradientStop Color="#101010" Offset="0" /> - <GradientStop Color="#202020" Offset="1" /> - </LinearGradientBrush> - </Border.BorderBrush> - <Border BorderThickness="1"> + <DockPanel> + + <Grid DockPanel.Dock="Bottom" Height="50" Margin="0 10 0 0"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1*" /> + <ColumnDefinition Width="50*" /> + <ColumnDefinition Width="50*" /> + </Grid.ColumnDefinitions> + <Button Command="{Binding StopCommand}" Grid.Column="1" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">STOP</Button> + <Button Command="{Binding StartCommand}" Grid.Column="2" Margin="10 0 0 0" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">START</Button> + </Grid> + + <Border CornerRadius="15" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> + <Border CornerRadius="1" BorderThickness="30"> <Border.BorderBrush> <LinearGradientBrush> - <GradientStop Color="#3E3E3E" Offset="0" /> - <GradientStop Color="#101010" Offset="0.5" /> - <GradientStop Color="#3E3E3E" Offset="1" /> + <GradientStop Color="#101010" Offset="0" /> + <GradientStop Color="#202020" Offset="1" /> </LinearGradientBrush> </Border.BorderBrush> - <Border.Background> - <ImageBrush ImageSource="{StaticResource FSE_PPC_Back}" /> - </Border.Background> + <Border BorderThickness="1"> + <Border.BorderBrush> + <LinearGradientBrush> + <GradientStop Color="#3E3E3E" Offset="0" /> + <GradientStop Color="#101010" Offset="0.5" /> + <GradientStop Color="#3E3E3E" Offset="1" /> + </LinearGradientBrush> + </Border.BorderBrush> + <Border.Background> + <ImageBrush ImageSource="{StaticResource FSE_PPC_Back}" /> + </Border.Background> + <Image Source="{Binding Source}" RenderOptions.BitmapScalingMode="Fant" Stretch="Fill"></Image> + </Border> </Border> </Border> - </Border> + </DockPanel> </Grid> </UserControl> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/app.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/app.config index 36bc04f85..5d8d17458 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/app.config +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/app.config @@ -74,6 +74,10 @@ <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" /> </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Z.EntityFramework.Extensions" publicKeyToken="59b66d028979105b" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.50.0" newVersion="4.0.50.0" /> + </dependentAssembly> </assemblyBinding> </runtime> <entityFramework> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config index dd8c723e4..d17a56d7d 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config @@ -7,4 +7,10 @@ <package id="MaterialDesignColors" version="1.2.2" targetFramework="net461" /> <package id="MaterialDesignThemes" version="3.0.1" targetFramework="net461" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" /> + <package id="System.Reactive" version="3.1.1" targetFramework="net461" /> + <package id="System.Reactive.Core" version="3.1.1" targetFramework="net461" /> + <package id="System.Reactive.Interfaces" version="3.1.1" targetFramework="net461" /> + <package id="System.Reactive.Linq" version="3.1.1" targetFramework="net461" /> + <package id="System.Reactive.PlatformServices" version="3.1.1" targetFramework="net461" /> + <package id="System.Reactive.Windows.Threading" version="3.1.1" targetFramework="net461" /> </packages>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs index c5886fb3c..be4748617 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs @@ -16,6 +16,16 @@ namespace Tango.FSE.Common.Connection public interface IMachineProvider { /// <summary> + /// Occurs when machine operator has connected. + /// </summary> + event EventHandler<MachineConnectedEventArgs> MachineConnected; + + /// <summary> + /// Occurs when the machine operator has disconnected. + /// </summary> + event EventHandler<MachineDisconnectedEventArgs> MachineDisconnected; + + /// <summary> /// Gets the database machine entity associated with the current machine. /// </summary> Machine Machine { get; } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectedEventArgs.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectedEventArgs.cs new file mode 100644 index 000000000..ae4d18538 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectedEventArgs.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.ExternalBridge; + +namespace Tango.FSE.Common.Connection +{ + public class MachineConnectedEventArgs : EventArgs + { + public IExternalBridgeClient MachineOperator { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineDisconnectedEventArgs.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineDisconnectedEventArgs.cs new file mode 100644 index 000000000..1a4534baf --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineDisconnectedEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.ExternalBridge; + +namespace Tango.FSE.Common.Connection +{ + public class MachineDisconnectedEventArgs : EventArgs + { + public IExternalBridgeClient MachineOperator { get; set; } + public Exception Exception { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj index 80e1dde40..664643f95 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj @@ -83,6 +83,8 @@ <Compile Include="Authentication\IAuthenticationProvider.cs" /> <Compile Include="AutoComplete\AutoCompleteSource.cs" /> <Compile Include="Connection\IMachineProvider.cs" /> + <Compile Include="Connection\MachineConnectedEventArgs.cs" /> + <Compile Include="Connection\MachineDisconnectedEventArgs.cs" /> <Compile Include="Controls\ConnectedMachineIcon.xaml.cs"> <DependentUpon>ConnectedMachineIcon.xaml</DependentUpon> </Compile> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config index 22e3d6062..27bce5f20 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.config @@ -80,6 +80,10 @@ <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" /> </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Z.EntityFramework.Extensions" publicKeyToken="59b66d028979105b" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.50.0" newVersion="4.0.50.0" /> + </dependentAssembly> </assemblyBinding> </runtime> <entityFramework> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs index 10ba9d957..9027d6a01 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs @@ -57,6 +57,16 @@ namespace Tango.FSE.UI.Connection } } + /// <summary> + /// Occurs when machine operator has connected. + /// </summary> + public event EventHandler<MachineConnectedEventArgs> MachineConnected; + + /// <summary> + /// Occurs when the machine operator has disconnected. + /// </summary> + public event EventHandler<MachineDisconnectedEventArgs> MachineDisconnected; + [TangoInject] private INotificationProvider NotificationProvider { get; set; } @@ -192,6 +202,7 @@ namespace Tango.FSE.UI.Connection await MachineOperator.Connect(); IsConnected = true; + OnMachineConnected(MachineOperator); return true; } } @@ -234,6 +245,7 @@ namespace Tango.FSE.UI.Connection { IsConnected = false; IsBusy = false; + OnMachineDisconnected(MachineOperator, null); } } } @@ -247,6 +259,8 @@ namespace Tango.FSE.UI.Connection { IsConnected = false; + OnMachineDisconnected(MachineOperator, MachineOperator.FailedStateException); + InvokeUI(async () => { var vm = await NotificationProvider.ShowDialog<MachineConnectionLostViewVM>(new MachineConnectionLostViewVM(MachineOperator, MachineOperator.FailedStateException.FlattenMessage(), 10)); @@ -280,6 +294,8 @@ namespace Tango.FSE.UI.Connection { IsConnected = false; + OnMachineDisconnected(MachineOperator, new Exception("The connection has been terminated by the remote machine.")); + InvokeUI(() => { NotificationProvider.ShowError("The connection has been terminated by the remote machine."); @@ -301,6 +317,23 @@ namespace Tango.FSE.UI.Connection MachineOperator.ContinuousRequestTimeout = TimeSpan.FromSeconds(5); } + protected virtual void OnMachineConnected(IExternalBridgeClient machineOperator) + { + MachineConnected?.Invoke(this, new MachineConnectedEventArgs() + { + MachineOperator = machineOperator, + }); + } + + protected virtual void OnMachineDisconnected(IExternalBridgeClient machineOperator, Exception exception) + { + MachineDisconnected?.Invoke(this, new MachineDisconnectedEventArgs() + { + MachineOperator = machineOperator, + Exception = exception + }); + } + /// <summary> /// Reassigns the event handlers from the previous connected machine to a new one. /// </summary> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml index 5d84b6b46..2a4db030b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml @@ -36,9 +36,9 @@ </Grid> <!--Right Panes--> - <Border x:Name="paneConnection" Padding="5" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1 0 0 0" Width="350" HorizontalAlignment="Right" Visibility="{Binding IsConnectionPaneOpened,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Border x:Name="paneConnection" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1 0 0 0" Width="350" HorizontalAlignment="Right" Visibility="{Binding IsConnectionPaneOpened,Converter={StaticResource BooleanToVisibilityConverter}}"> <Border.Background> - <ImageBrush ImageSource="/Images/abstracts/abstract1.png" Stretch="UniformToFill" Opacity="0.2" /> + <SolidColorBrush Color="{StaticResource FSE_PrimaryBackgroundDarkColor}" Opacity="0.8" /> </Border.Background> <Border.Style> <Style TargetType="Border"> @@ -71,14 +71,19 @@ <DropShadowEffect Direction="-180" Opacity="0.5" /> </Border.Effect> - <Grid> - <Grid Visibility="{Binding MachineProvider.IsConnected,Converter={StaticResource BooleanToVisibilityInverseConverter}}" > - <panes:MachineConnectionPane DataContext="{Binding ConnectionPaneVM}" /> - </Grid> - <Grid Visibility="{Binding MachineProvider.IsConnected,Converter={StaticResource BooleanToVisibilityConverter}}" > - <panes:ConnectedMachinePane DataContext="{Binding ConnectedMachinePaneVM}" /> + <Border Padding="5"> + <Border.Background> + <ImageBrush ImageSource="/Images/abstracts/abstract1.png" Stretch="UniformToFill" Opacity="0.2" /> + </Border.Background> + <Grid> + <Grid Visibility="{Binding MachineProvider.IsConnected,Converter={StaticResource BooleanToVisibilityInverseConverter}}" > + <panes:MachineConnectionPane DataContext="{Binding ConnectionPaneVM}" /> + </Grid> + <Grid Visibility="{Binding MachineProvider.IsConnected,Converter={StaticResource BooleanToVisibilityConverter}}" > + <panes:ConnectedMachinePane DataContext="{Binding ConnectedMachinePaneVM}" /> + </Grid> </Grid> - </Grid> + </Border> </Border> <!--Right Panes--> </Grid> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml index 70422a8ca..59ad6341d 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml @@ -1404,7 +1404,7 @@ <Grid Background="{StaticResource TransparentBackgroundBrush100}"> <Grid.Style> <Style TargetType="Grid"> - <Setter Property="Width" Value="740"></Setter> + <Setter Property="Width" Value="640"></Setter> <Setter Property="LayoutTransform"> <Setter.Value> <ScaleTransform ScaleY="1" ScaleX="0"></ScaleTransform> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs index 275db58c9..9f7d786bc 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Properties/AssemblyInfo.cs @@ -4,5 +4,5 @@ using System.Runtime.InteropServices; [assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)] [assembly: AssemblyTitle("Tango - Machine Studio")] -[assembly: AssemblyVersion("4.1.1.0")] +[assembly: AssemblyVersion("4.1.2.0")] [assembly: ComVisible(false)]
\ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs index 431545c33..42228614e 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs @@ -41,5 +41,10 @@ namespace Tango.PPC.Common.Console } } } + + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) + { + + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs index aacc40168..71a417190 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs @@ -251,6 +251,16 @@ namespace Tango.PPC.Common public String ExternalBridgeSignalRHub { get; set; } /// <summary> + /// Gets or sets a value indicating whether to enable the internal remote desktop service. + /// </summary> + public bool EnableRemoteDesktop { get; set; } + + /// <summary> + /// Gets or sets the internal remote desktop service frame rate (1-20). + /// </summary> + public int RemoteDesktopFrameRate { get; set; } + + /// <summary> /// Gets the machine service address. /// </summary> /// <returns></returns> @@ -299,6 +309,8 @@ namespace Tango.PPC.Common TcpTransportAdapterWriteMode = TcpTransportAdapterWriteMode.Interval; EnableExternalBridgeSignalR = true; ExternalBridgeSignalRHub = "ExternalBridgeHub"; + EnableRemoteDesktop = true; + RemoteDesktopFrameRate = 5; } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteDesktop/DefaultRemoteDesktopService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteDesktop/DefaultRemoteDesktopService.cs new file mode 100644 index 000000000..9099e6346 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteDesktop/DefaultRemoteDesktopService.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.Integration.ExternalBridge; +using Tango.PPC.Common.Application; +using Tango.PPC.Common.ExternalBridge; +using Tango.RemoteDesktop; +using Tango.RemoteDesktop.CaptureMethods; +using Tango.RemoteDesktop.Encoders; +using Tango.RemoteDesktop.Engines; +using Tango.RemoteDesktop.Frames; +using Tango.RemoteDesktop.Network; +using Tango.Settings; +using Tango.Transport; + +namespace Tango.PPC.Common.RemoteDesktop +{ + [TangoCreateWhenRegistered] + public class DefaultRemoteDesktopService : ExtendedObject, IRemoteDesktopService, IExternalBridgeRequestHandler + { + private class RemoteDesktopClient + { + public String Token { get; set; } + public ExternalBridgeReceiver Receiver { get; set; } + public bool InitialPacketSent { get; set; } + } + + private RemoteDesktopPacket _initialPacket; + private RasterScreenCaptureEngine _engine; + private PPCSettings _settings; + private List<RemoteDesktopClient> _clients; + + public DefaultRemoteDesktopService(IPPCApplicationManager applicationManager, IPPCExternalBridgeService externalBridge) + { + _settings = SettingsManager.Default.GetOrCreate<PPCSettings>(); + applicationManager.ApplicationReady += ApplicationManager_ApplicationReady; + + externalBridge.RegisterRequestHandler(this); + + _clients = new List<RemoteDesktopClient>(); + _engine = new RasterScreenCaptureEngine(); + + _engine.FrameRate = Math.Min(Math.Max(_settings.RemoteDesktopFrameRate, 1), 20); + _engine.FrameReceived += _engine_FrameReceived; + } + + private void ApplicationManager_ApplicationReady(object sender, EventArgs e) + { + +#if DEBUG + _engine.CaptureMethod.Dispose(); + + var mainWindow = System.Windows.Application.Current.MainWindow; + + _engine.CaptureRegion = new CaptureRegion() + { + Left = (int)mainWindow.Left, + Top = (int)mainWindow.Top, + Width = (int)mainWindow.Width, + Height = (int)mainWindow.Height + }; + _engine.CaptureMethod = new GdiScreenCapture(); +#endif + + if (_settings.EnableRemoteDesktop) + { + Start(); + } + } + + private bool _isStarted; + public bool IsStarted + { + get { return _isStarted; } + private set { _isStarted = value; RaisePropertyChangedAuto(); } + } + + public void Start() + { + if (!IsStarted) + { + _engine.Start(); + IsStarted = true; + } + } + + public void Stop() + { + if (IsStarted) + { + _engine.Stop(); + IsStarted = false; + } + } + + [ExternalBridgeRequestHandlerMethod(typeof(StartRemoteDesktopSessionRequest))] + public async void OnStartRemoteDesktopSessionRequestReceived(StartRemoteDesktopSessionRequest request, String token, ExternalBridgeReceiver receiver) + { + var client = _clients.SingleOrDefault(x => x.Receiver == receiver); + + if (client != null) + { + _clients.Remove(client); + } + + _clients.Add(new RemoteDesktopClient() + { + Receiver = receiver, + Token = token + }); + + await receiver.SendGenericResponse(new StartRemoteDesktopSessionResponse() + { + FrameRate = _engine.FrameRate + }, token, new TransportResponseConfig() + { + Immediate = true, + }); + } + + private async void _engine_FrameReceived(object sender, ScreenCaptureFrameReceivedEventArgs<RasterFrame> e) + { + _initialPacket = new RemoteDesktopPacket() + { + Bitmap = e.Frame.ToEncoder<PngEncoder>().ToArray(), + }; + + foreach (var client in _clients.ToList().Where(x => !x.InitialPacketSent)) + { + try + { + await client.Receiver.SendGenericResponse(new StartRemoteDesktopSessionResponse() + { + Packet = _initialPacket, + }, client.Token, new TransportResponseConfig() + { + Immediate = true, + }); + + client.InitialPacketSent = true; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + if (e.Frame.DifferenceAvailable && e.Frame.DifferenceCount > 0) + { + var diffFrame = e.Frame.ToDifference(); + diffFrame = diffFrame.OptimizeBounds(); + + RemoteDesktopPacket packet = new RemoteDesktopPacket() + { + Bitmap = diffFrame.ToEncoder<PngEncoder>().ToArray(), + IsPartial = true, + PartialRegion = new CaptureRegion(diffFrame.Left, diffFrame.Top, diffFrame.Width, diffFrame.Height), + }; + + diffFrame.Dispose(); + e.Frame.Dispose(); + + foreach (var client in _clients.ToList().Where(x => x.InitialPacketSent)) + { + try + { + await client.Receiver.SendGenericResponse(new StartRemoteDesktopSessionResponse() + { + Packet = packet + }, client.Token, new TransportResponseConfig() + { + Immediate = false, + }); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + } + } + + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) + { + var client = _clients.SingleOrDefault(x => x.Receiver == receiver); + + if (client != null) + { + _clients.Remove(client); + } + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteDesktop/IRemoteDesktopService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteDesktop/IRemoteDesktopService.cs new file mode 100644 index 000000000..bce1bf51e --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/RemoteDesktop/IRemoteDesktopService.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.RemoteDesktop +{ + public interface IRemoteDesktopService + { + bool IsStarted { get; } + void Start(); + void Stop(); + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index 382405705..80bcf6ef1 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -159,6 +159,8 @@ <Compile Include="MachineSetup\MachineSetupManager.cs" /> <Compile Include="MachineSetup\MachineSetupProgress.cs" /> <Compile Include="MachineSetup\MachineSetupResult.cs" /> + <Compile Include="RemoteDesktop\DefaultRemoteDesktopService.cs" /> + <Compile Include="RemoteDesktop\IRemoteDesktopService.cs" /> <Compile Include="Synchronization\DefaultMachineDataSynchronizer.cs" /> <Compile Include="Synchronization\IMachineDataSynchronizer.cs" /> <Compile Include="Synchronization\SynchronizationEndedEventArgs.cs" /> @@ -373,6 +375,10 @@ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project> <Name>Tango.PMR</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.RemoteDesktop\Tango.RemoteDesktop.csproj"> + <Project>{a78068d4-2061-4376-8ede-583d8d880dec}</Project> + <Name>Tango.RemoteDesktop</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Settings\Tango.Settings.csproj"> <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> <Name>Tango.Settings</Name> diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs index 18a34afb3..01ccc7654 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Properties/AssemblyInfo.cs @@ -8,4 +8,4 @@ using System.Windows; // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Tango PPC Application")] -[assembly: AssemblyVersion("1.1.4.0")] +[assembly: AssemblyVersion("1.1.5.0")] diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs index 3e4a91c73..a8cbcfe2d 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs @@ -22,6 +22,7 @@ using Tango.PPC.Common.Notifications; using Tango.PPC.Common.OS; using Tango.PPC.Common.Printing; using Tango.PPC.Common.RemoteAssistance; +using Tango.PPC.Common.RemoteDesktop; using Tango.PPC.Common.Storage; using Tango.PPC.Common.Synchronization; using Tango.PPC.Common.Threading; @@ -80,6 +81,7 @@ namespace Tango.PPC.UI TangoIOC.Default.Unregister<IPackageRunner>(); TangoIOC.Default.Unregister<IMachineDataSynchronizer>(); TangoIOC.Default.Unregister<IConsoleEngineService>(); + TangoIOC.Default.Unregister<IRemoteDesktopService>(); if (App.StartupArgs.Contains("-webDebug")) { @@ -103,6 +105,7 @@ namespace Tango.PPC.UI TangoIOC.Default.Register<IDiagnosticsFrameProvider, DefaultDiagnosticsFrameProvider>(); TangoIOC.Default.Register<IPPCExternalBridgeService, PPCExternalBridgeService>(); TangoIOC.Default.Register<IConsoleEngineService, DefaultConsoleEngineService>(); + TangoIOC.Default.Register<IRemoteDesktopService, DefaultRemoteDesktopService>(); TangoIOC.Default.Register<IRemoteAssistanceProvider, DefaultRemoteAssistanceProvider>(); TangoIOC.Default.Register<IPackageRunner, DefaultPackageRunner>(); TangoIOC.Default.Register<IMachineSetupManager, MachineSetupManager>(); diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj index 7c794c276..8014ac3f2 100644 --- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj +++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj @@ -98,6 +98,7 @@ <Compile Include="IO\KnownFolders.cs" /> <Compile Include="Json\ProtobufContractResolver.cs" /> <Compile Include="Threading\ActionTimer.cs" /> + <Compile Include="Threading\SequencerThread.cs" /> <Compile Include="Threading\TaskSequencer.cs" /> <Compile Include="Threading\ThreadFactory.cs" /> <Compile Include="Threading\TimeoutTask.cs" /> @@ -205,7 +206,7 @@ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <ProjectExtensions> <VisualStudio> - <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" /> + <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" /> </VisualStudio> </ProjectExtensions> <Import Project="..\packages\System.Data.SQLite.Core.1.0.108.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('..\packages\System.Data.SQLite.Core.1.0.108.0\build\net46\System.Data.SQLite.Core.targets')" /> diff --git a/Software/Visual_Studio/Tango.Core/Threading/SequencerThread.cs b/Software/Visual_Studio/Tango.Core/Threading/SequencerThread.cs new file mode 100644 index 000000000..603790466 --- /dev/null +++ b/Software/Visual_Studio/Tango.Core/Threading/SequencerThread.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Tango.Core.Threading +{ + public class SequencerThread<T> : IDisposable + { + private Thread _queueThread; + private ProducerConsumerQueue<T> _queue; + private Action<T> _onNext; + + public int FrameRate { get; set; } + + public bool IsStarted { get; private set; } + + public SequencerThread(Action<T> onNext) + { + _onNext = onNext; + _queue = new ProducerConsumerQueue<T>(); + } + + public void Start() + { + if (!IsStarted) + { + IsStarted = true; + _queueThread = new Thread(QueueThreadMethod); + _queueThread.Name = "Sequencer Thread"; + _queueThread.IsBackground = true; + _queueThread.Start(); + } + } + + public void Push(T item) + { + _queue.BlockEnqueue(item); + } + + private void QueueThreadMethod() + { + Stopwatch watch = new Stopwatch(); + watch.Start(); + + while (IsStarted) + { + watch.Restart(); + var item = _queue.BlockDequeue(); + + if (!IsStarted) break; + + try + { + _onNext?.Invoke(item); + } + catch { } + + Thread.Sleep(Math.Max(1, (int)(FrameRate - watch.ElapsedMilliseconds))); + } + } + + public void Dispose() + { + IsStarted = false; + } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs index ef98db11b..7ebe32927 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs @@ -338,6 +338,16 @@ namespace Tango.Integration.ExternalBridge HasSessions = _receivers.Count(x => x.IsLoggedIn) > 0; FullControlSessionReceiver = _receivers.SingleOrDefault(x => x.IsLoggedIn && x.LoginIntent == ExternalBridgeLoginIntent.FullControl); + + //Notify request handlers about this receiver disconnected. + foreach (var requestHandler in _requestHandlers.ToList().Select(x => x.Value.Handler)) + { + try + { + requestHandler.OnReceiverDisconnected(receiver); + } + catch { } //Ignore exceptions on handler. + } } private void Receiver_ColorProfileRequest(object sender, ColorProfileRequestEventArgs e) diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeRequestHandler.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeRequestHandler.cs index fe9e9caee..1161436d8 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeRequestHandler.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeRequestHandler.cs @@ -9,6 +9,6 @@ namespace Tango.Integration.ExternalBridge { public interface IExternalBridgeRequestHandler { - + void OnReceiverDisconnected(ExternalBridgeReceiver receiver); } } diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Clipping/BitmapCliper.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Clipping/BitmapCliper.cs index 4f93eeb66..8866f6d9a 100644 --- a/Software/Visual_Studio/Tango.RemoteDesktop/Clipping/BitmapCliper.cs +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Clipping/BitmapCliper.cs @@ -30,8 +30,8 @@ namespace Tango.RemoteDesktop.Clipping //determine top for (int i = 0; i < rgbValues.Length; i++) { - int color = rgbValues[i] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[i] & 0xffffff; + if (color != 0x0) { int r = i / bd.Width; int c = i % bd.Width; @@ -53,8 +53,8 @@ namespace Tango.RemoteDesktop.Clipping //determine bottom for (int i = rgbValues.Length - 1; i >= 0; i--) { - int color = rgbValues[i] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[i] & 0xffffff; + if (color != 0x0) { int r = i / bd.Width; int c = i % bd.Width; @@ -79,8 +79,8 @@ namespace Tango.RemoteDesktop.Clipping //determine left for (int c = 0; c < left; c++) { - int color = rgbValues[r * bd.Width + c] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[r * bd.Width + c] & 0xffffff; + if (color != 0x0) { if (left > c) { @@ -93,8 +93,8 @@ namespace Tango.RemoteDesktop.Clipping //determine right for (int c = bd.Width - 1; c > right; c--) { - int color = rgbValues[r * bd.Width + c] & 0x00ffffff; - if (color != 0x00ffffff) + int color = rgbValues[r * bd.Width + c] & 0xffffff; + if (color != 0x0) { if (right < c) { @@ -128,9 +128,7 @@ namespace Tango.RemoteDesktop.Clipping //create new image Bitmap newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb); - BitmapData nbd - = newImage.LockBits(new Rectangle(0, 0, width, height), - ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + BitmapData nbd = newImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(imgData, 0, nbd.Scan0, imgData.Length); newImage.UnlockBits(nbd); diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Frame.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Frame.cs index 93f38bac0..e871d5da2 100644 --- a/Software/Visual_Studio/Tango.RemoteDesktop/Frame.cs +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Frame.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media.Imaging; +using Tango.RemoteDesktop.Frames; namespace Tango.RemoteDesktop { @@ -45,6 +46,15 @@ namespace Tango.RemoteDesktop } /// <summary> + /// Applies this frame onto an existing raster frame. + /// </summary> + /// <param name="frame">The frame.</param> + public virtual void Apply(RasterFrame frame) + { + Apply(frame.ToBitmap()); + } + + /// <summary> /// Returns a WPF BitmapSource representing the frame. /// </summary> /// <returns></returns> diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Network/RemoteDesktopPacket.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Network/RemoteDesktopPacket.cs new file mode 100644 index 000000000..28f890a9a --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Network/RemoteDesktopPacket.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.RemoteDesktop.Network +{ + public class RemoteDesktopPacket + { + /// <summary> + /// Gets or sets the bitmap byte array. + /// </summary> + public byte[] Bitmap { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether the <see cref="Bitmap"/> is a partial bitmap that needs to be applied over the previous one. + /// </summary> + public bool IsPartial { get; set; } + + /// <summary> + /// Gets or sets the region on the previous bitmap that needs to be applied with this packet bitmap. + /// </summary> + public CaptureRegion PartialRegion { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Network/StartRemoteDesktopSessionRequest.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Network/StartRemoteDesktopSessionRequest.cs new file mode 100644 index 000000000..f6d572b83 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Network/StartRemoteDesktopSessionRequest.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.RemoteDesktop.Network +{ + /// <summary> + /// Represents a message for starting the remote desktop session. + /// </summary> + public class StartRemoteDesktopSessionRequest + { + + } +} diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Network/StartRemoteDesktopSessionResponse.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Network/StartRemoteDesktopSessionResponse.cs new file mode 100644 index 000000000..2c1d0e635 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Network/StartRemoteDesktopSessionResponse.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.RemoteDesktop.Network +{ + /// <summary> + /// Represents a continuous message for updating about remote desktop changes. + /// </summary> + public class StartRemoteDesktopSessionResponse + { + /// <summary> + /// Gets or sets the remote desktop packet. + /// </summary> + public RemoteDesktopPacket Packet { get; set; } + + /// <summary> + /// Capture frame rate reported by the host. + /// Will be sent only on the first response! + /// </summary> + public int FrameRate { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/ScreenCaptureEngine.cs b/Software/Visual_Studio/Tango.RemoteDesktop/ScreenCaptureEngine.cs index 1d7b4d7d4..17f54369c 100644 --- a/Software/Visual_Studio/Tango.RemoteDesktop/ScreenCaptureEngine.cs +++ b/Software/Visual_Studio/Tango.RemoteDesktop/ScreenCaptureEngine.cs @@ -136,37 +136,44 @@ namespace Tango.RemoteDesktop { watch.Restart(); - var bitmap = CaptureMethod.GetDesktopBitmap(CaptureRegion); - - if (CaptureCursor) + try { - using (Graphics g = Graphics.FromImage(bitmap)) + var bitmap = CaptureMethod.GetDesktopBitmap(CaptureRegion); + + if (CaptureCursor) { - CursorUtils.ApplyCursor(g, bitmap, CaptureRegion.Left, CaptureRegion.Top); + using (Graphics g = Graphics.FromImage(bitmap)) + { + CursorUtils.ApplyCursor(g, bitmap, CaptureRegion.Left, CaptureRegion.Top); + } } - } - if (EnableComparer && Comparer != null) - { - if (_previousBitmap == null) + if (EnableComparer && Comparer != null) { - _previousBitmap = bitmap.Clone() as Bitmap; - OnFrameReceived(bitmap, null, 0); + if (_previousBitmap == null) + { + _previousBitmap = bitmap.Clone() as Bitmap; + OnFrameReceived(bitmap, null, 0); + } + else + { + var result = Comparer.CreateDifference(_previousBitmap, bitmap); + _previousBitmap.Dispose(); + _previousBitmap = bitmap.Clone() as Bitmap; + OnFrameReceived(bitmap, result.Frame, result.DifferenceCount); + } } else { - var result = Comparer.CreateDifference(_previousBitmap, bitmap); - _previousBitmap.Dispose(); - _previousBitmap = bitmap.Clone() as Bitmap; - OnFrameReceived(bitmap, result.Frame, result.DifferenceCount); + OnFrameReceived(bitmap, null, 0); } } - else + catch (Exception ex) { - OnFrameReceived(bitmap, null, 0); + Debug.WriteLine($"Error in screen capture engine: {ex.Message}"); } - int delay = Math.Max(5, (FrameRate * 10) - (int)watch.ElapsedMilliseconds); + int delay = Math.Max(5, (1000 / FrameRate) - (int)watch.ElapsedMilliseconds); Thread.Sleep(delay); } } diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj b/Software/Visual_Studio/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj index 06abb0040..87674b42b 100644 --- a/Software/Visual_Studio/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Tango.RemoteDesktop.csproj @@ -79,6 +79,9 @@ <Compile Include="Engines\VectorScreenCaptureEngine.cs" /> <Compile Include="Frames\VectorFrameColor.cs" /> <Compile Include="IScreenCaptureEngine.cs" /> + <Compile Include="Network\RemoteDesktopPacket.cs" /> + <Compile Include="Network\StartRemoteDesktopSessionRequest.cs" /> + <Compile Include="Network\StartRemoteDesktopSessionResponse.cs" /> <Compile Include="Quantization\ColorBgra.cs" /> <Compile Include="Quantization\OctreeQuantizer.cs" /> <Compile Include="Quantization\PaletteTable.cs" /> diff --git a/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml b/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml Binary files differindex 0309fb66b..f9c59f188 100644 --- a/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml +++ b/Software/Visual_Studio/Tango.SQLExaminer/SQLExaminer/Configurations/OverrideData.xml diff --git a/Software/Visual_Studio/Tango.Transport/ITransporter.cs b/Software/Visual_Studio/Tango.Transport/ITransporter.cs index bffcb0444..78047c080 100644 --- a/Software/Visual_Studio/Tango.Transport/ITransporter.cs +++ b/Software/Visual_Studio/Tango.Transport/ITransporter.cs @@ -104,6 +104,15 @@ namespace Tango.Transport Task SendGenericResponse<Response>(Response response, String token, TransportResponseConfig config = null) where Response : class; /// <summary> + /// Sends a generic request and expecting multiple generic response messages. + /// </summary> + /// <typeparam name="Request">The type of the request.</typeparam> + /// <typeparam name="Response">The type of the response.</typeparam> + /// <param name="config">Request configuration.</param> + /// <returns></returns> + IObservable<Response> SendGenericContinuousRequest<Request, Response>(Request request, TransportContinuousRequestConfig config = null) where Request : class where Response : class; + + /// <summary> /// Sends the response. /// </summary> /// <param name="container">The container.</param> diff --git a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs index c9388678d..f61e29795 100644 --- a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs @@ -885,6 +885,61 @@ namespace Tango.Transport await SendResponse<GenericResponse>(genericResponse, token, config); } + /// <summary> + /// Sends a generic request and expecting multiple generic response messages. + /// </summary> + /// <typeparam name="Request">The type of the request.</typeparam> + /// <typeparam name="Response">The type of the response.</typeparam> + /// <param name="config">Request configuration.</param> + /// <returns></returns> + public IObservable<Response> SendGenericContinuousRequest<Request, Response>(Request request, TransportContinuousRequestConfig config = null) where Request : class where Response : class + { + GenericRequest genericRequest = new GenericRequest(); + genericRequest.Type = request.GetType().Name; + genericRequest.Data = ByteString.CopyFromUtf8(JsonConvert.SerializeObject(request, _genericMessageSettings)); + + Subject<Response> subject = new Subject<Response>(); + + SendContinuousRequest<GenericRequest, GenericResponse>(genericRequest, config).Subscribe((response) => + { + + try + { + var responseObject = JsonConvert.DeserializeObject<Response>(response.Message.Data.ToStringUtf8()); + subject.OnNext(responseObject); + } + catch + { + //Ignore exception at the client side. + } + + }, (ex) => + { + + try + { + subject.OnError(ex); + } + catch + { + //Ignore exception at the client side. + } + + }, () => + { + try + { + subject.OnCompleted(); + } + catch + { + //Ignore exception at the client side. + } + }); + + return subject.AsObservable(); + } + #endregion #region Public Response Methods |
