From 88f609c6244121f07b45e8101174fdc293bbcb2d Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 27 Oct 2019 13:19:32 +0200 Subject: Removed rollback version in machine studio. Omitted remove old dll files from machine studio updater. Removed ColorCapture module from MS update to reduce package size. Added ColorCapture module only to MS installer. Added ExternalBridge default timeout to machine studio settings file. --- .../MachineStudio/Tango.MachineStudio.UI/Views/UpdateView.xaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/UpdateView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/UpdateView.xaml index a35928e12..924db7f8b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/UpdateView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/UpdateView.xaml @@ -109,12 +109,12 @@ - diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif new file mode 100644 index 000000000..11cef3b10 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/Ready_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png new file mode 100644 index 000000000..fbace4fa5 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif new file mode 100644 index 000000000..058d9a34d Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/dyeing_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif new file mode 100644 index 000000000..9bf0d84f3 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/error_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif new file mode 100644 index 000000000..79256816a Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/getting_ready_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png new file mode 100644 index 000000000..6dc569e35 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine-off.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif new file mode 100644 index 000000000..9ca81da39 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/machine_off_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png new file mode 100644 index 000000000..7edf624be Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/ready-to-dye.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif new file mode 100644 index 000000000..f5962c36c Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/service_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif new file mode 100644 index 000000000..d936476b6 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/shutdown_icon_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png new file mode 100644 index 000000000..6b46c22c0 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif new file mode 100644 index 000000000..89491179d Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/Statuses/standby_Anim.gif differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index b542821d7..3379ef4ae 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -359,6 +359,18 @@ TCC\template.bmp Always + + + + + + + + + + + + SettingsSingleFileGenerator @@ -384,6 +396,10 @@ {bb2abb74-ba58-4812-83aa-ec8171f42df4} Tango.AutoComplete + + {d129789c-3096-4d0b-8dd7-fe24a4df4b21} + Tango.AnimatedGif + {f441feee-322a-4943-b566-110e12fd3b72} Tango.BL @@ -641,7 +657,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)ProtoCompilers\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 5513b65ac..d427be9e5 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -11,6 +11,8 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:common="clr-namespace:Tango.MachineStudio.Common;assembly=Tango.MachineStudio.Common" xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL" + xmlns:operations="clr-namespace:Tango.Integration.Operation;assembly=Tango.Integration" + xmlns:gif="clr-namespace:Tango.AnimatedGif;assembly=Tango.AnimatedGif" xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" @@ -26,6 +28,7 @@ + @@ -274,6 +277,63 @@ + + + + + + + + + + + + + + + + + + + + -- cgit v1.3.1 From 5cb75f4b026a7842171369f58f5aba1c9678f60f Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Fri, 20 Dec 2019 17:47:51 +0200 Subject: Added error message for when external bridge failed due to udp port is already used. Implemented flexo font on mahcine studio. Added module title/image on MS. Updated some machine icons on MS. --- Software/Graphics/machine_new.png | Bin 0 -> 43275 bytes .../Fonts/Flexo-Black.otf | Bin 0 -> 112924 bytes .../Fonts/Flexo-BlackIt.otf | Bin 0 -> 121948 bytes .../Fonts/Flexo-Bold.otf | Bin 0 -> 112436 bytes .../Fonts/Flexo-BoldIt.otf | Bin 0 -> 121352 bytes .../Fonts/Flexo-Demi.otf | Bin 0 -> 112936 bytes .../Fonts/Flexo-DemiIt.otf | Bin 0 -> 122096 bytes .../Fonts/Flexo-Heavy.otf | Bin 0 -> 112632 bytes .../Fonts/Flexo-HeavyIt.otf | Bin 0 -> 122220 bytes .../Tango.MachineStudio.Common/Fonts/Flexo-It.otf | Bin 0 -> 120816 bytes .../Fonts/Flexo-Light.otf | Bin 0 -> 112116 bytes .../Fonts/Flexo-LightIt.otf | Bin 0 -> 120472 bytes .../Fonts/Flexo-Medium.otf | Bin 0 -> 112016 bytes .../Fonts/Flexo-MediumIt.otf | Bin 0 -> 121092 bytes .../Fonts/Flexo-Regular.otf | Bin 0 -> 111924 bytes .../Fonts/Flexo-Thin.otf | Bin 0 -> 112040 bytes .../Fonts/Flexo-ThinIt.otf | Bin 0 -> 120108 bytes .../Images/machine_new.png | Bin 0 -> 43275 bytes .../Images/machine_new_small.png | Bin 0 -> 16963 bytes .../Resources/MaterialDesign.xaml | 13 +++- .../Tango.MachineStudio.Common.csproj | 25 +++++++- .../Tango.MachineStudio.UI/MainWindow.xaml | 2 +- .../Notifications/DialogWindow.xaml | 2 +- .../Notifications/MessageBoxWindow.xaml | 2 +- .../Notifications/TextInputBoxWindow.xaml | 2 +- .../Tango.MachineStudio.UI.csproj | 5 +- .../ViewModels/MachineConnectionViewVM.cs | 3 + .../ViewModels/MainViewVM.cs | 14 +++-- .../Tango.MachineStudio.UI/Views/AboutView.xaml | 2 +- .../Views/ConnectionLostView.xaml | 2 +- .../Tango.MachineStudio.UI/Views/LoadingView.xaml | 2 +- .../Tango.MachineStudio.UI/Views/LoginView.xaml | 2 +- .../Views/MachineConnectionView.xaml | 2 +- .../Views/MachineLoginView.xaml | 2 +- .../Views/MachineSerialView.xaml | 2 +- .../Tango.MachineStudio.UI/Views/MainView.xaml | 69 +++++++++++++++++++-- .../Tango.MachineStudio.UI/Views/ShutdownView.xaml | 2 +- .../Windows/ExceptionWindow.xaml | 2 +- .../Windows/ModuleWindow.xaml | 14 ++++- .../Windows/ModuleWindow.xaml.cs | 9 +++ .../Tango.MachineStudio.UI/machine_new_small.ico | Bin 0 -> 132825 bytes .../ExternalBridge/ExternalBridgeScanner.cs | 6 +- 42 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 Software/Graphics/machine_new.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/Graphics/machine_new.png b/Software/Graphics/machine_new.png new file mode 100644 index 000000000..116e1e9c7 Binary files /dev/null and b/Software/Graphics/machine_new.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf new file mode 100644 index 000000000..0341d05db Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Black.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf new file mode 100644 index 000000000..e0823abdf Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BlackIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf new file mode 100644 index 000000000..2b9144e5c Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Bold.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf new file mode 100644 index 000000000..f21ed044d Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-BoldIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf new file mode 100644 index 000000000..ada716012 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Demi.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf new file mode 100644 index 000000000..ab9a133a5 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-DemiIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf new file mode 100644 index 000000000..b3630c982 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Heavy.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf new file mode 100644 index 000000000..e47f75546 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-HeavyIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf new file mode 100644 index 000000000..6f9b5fa49 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-It.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf new file mode 100644 index 000000000..27af39094 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Light.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf new file mode 100644 index 000000000..89085eeca Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-LightIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf new file mode 100644 index 000000000..04b2a8853 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Medium.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf new file mode 100644 index 000000000..91996979e Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-MediumIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf new file mode 100644 index 000000000..2703ba3f3 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Regular.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf new file mode 100644 index 000000000..666c69931 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-Thin.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf new file mode 100644 index 000000000..b039daffe Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/Flexo-ThinIt.otf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png new file mode 100644 index 000000000..116e1e9c7 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png new file mode 100644 index 000000000..378879ce1 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Images/machine_new_small.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml index 177a4fe75..37e35b1ab 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml @@ -63,6 +63,13 @@ ../Fonts/#digital-7 + ../Fonts/#flexo + + + + + + @@ -526,7 +533,7 @@ - + @@ -774,6 +781,10 @@ + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 3ce667afe..5e874add1 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -127,6 +127,22 @@ + + + + + + + + + + + + + + + + @@ -401,11 +417,16 @@ - + + + + + + - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml index a76749b05..054d7b9d8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml @@ -8,7 +8,7 @@ xmlns:views="clr-namespace:Tango.MachineStudio.UI.Views" xmlns:sharedControls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Tango" Height="800" Width="1280" Foreground="{StaticResource MainWindow.Foreground}" + Title="Tango" Height="800" Width="1280" Foreground="{StaticResource MainWindow.Foreground}" FontFamily="{StaticResource flexo}" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}" Background="{DynamicResource MainWindow.Background}" WindowTitleBrush="{StaticResource MainWindow.WindowTitleColorBrush}"> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml index 41405f7fb..939adf5d5 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml @@ -7,7 +7,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Windows" mc:Ignorable="d" - Title="Machine Studio" MinHeight="220" SizeToContent="WidthAndHeight" MinWidth="600" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False"> + Title="Machine Studio" MinHeight="220" SizeToContent="WidthAndHeight" MinWidth="600" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml index 988e3c21f..888f49d3f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/MessageBoxWindow.xaml @@ -8,7 +8,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False"> + Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml index a43fafb46..7d888d784 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml @@ -8,7 +8,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False"> + Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent" ShowInTaskbar="False" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index d5084d051..1762205ad 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -36,7 +36,7 @@ 4 - machine.ico + machine_new_small.ico @@ -363,6 +363,7 @@ TCC\template.bmp Always + @@ -674,7 +675,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs index d1f3cc69e..0ea47c24a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; +using Tango.Core.DI; using Tango.Emulations.ExternalBridge; using Tango.Integration.ExternalBridge; using Tango.MachineStudio.Common; @@ -108,6 +109,8 @@ namespace Tango.MachineStudio.UI.ViewModels catch (Exception ex) { LogManager.Log(ex, "Error starting external bridge scanner."); + Cancel(); + TangoIOC.Default.GetInstance().ShowError($"There is a problem with machine scanning.\n{ex.FlattenMessage()}"); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs index c7fd7a525..a7397835b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs @@ -668,7 +668,7 @@ namespace Tango.MachineStudio.UI.ViewModels /// Starts the specified module. /// /// The module. - internal void StartModule(IStudioModule module) + internal async void StartModule(IStudioModule module) { IsMenuOpened = false; @@ -693,10 +693,9 @@ namespace Tango.MachineStudio.UI.ViewModels m.IsLoaded = false; } - CurrentModule = module; - if (module != null) { + CurrentModule = module; CurrentModule.IsLoaded = true; IsModuleLoaded = true; @@ -707,7 +706,10 @@ namespace Tango.MachineStudio.UI.ViewModels { IsModuleLoaded = false; LogManager.Log(String.Format("Navigating to Home...")); - (MainView.Self as MainView).NavigationControl.NavigateTo("Home"); + (MainView.Self as MainView).NavigationControl.NavigateTo("Home",() => + { + CurrentModule = module; + }); } } @@ -715,7 +717,7 @@ namespace Tango.MachineStudio.UI.ViewModels /// Opens the module in a new window. /// /// The module. - private void OpenModuleInWindow(IStudioModule module, Rect? bounds = null, WindowState? state = null) + private async void OpenModuleInWindow(IStudioModule module, Rect? bounds = null, WindowState? state = null) { if (module == null) return; @@ -725,6 +727,8 @@ namespace Tango.MachineStudio.UI.ViewModels StartModule(null); + await Task.Delay(1000); + LogManager.Log(String.Format("Starting module '{0}' in new window...", module.Name)); if (!(MainView.Self as MainView).NavigationControl.Elements.ToList().Exists(x => x.GetType() == module.MainViewType)) diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml index f7e90d4f5..82d628785 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/AboutView.xaml @@ -28,7 +28,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml index b2fa2b3e3..28937a438 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectionLostView.xaml @@ -18,7 +18,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml index df1c1b831..14fcc3a37 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml @@ -16,7 +16,7 @@ - + Machine Studio diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index ec6091988..d93dbc127 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -42,7 +42,7 @@ - + Machine Studio diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml index 69ce4c855..581e87ed6 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml @@ -27,7 +27,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml index 7d0b2e25c..5be9ba089 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineLoginView.xaml @@ -29,7 +29,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml index eea90c7b9..2393ab6e7 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineSerialView.xaml @@ -23,7 +23,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index d427be9e5..3f1164526 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -231,10 +231,71 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml index cc1060b2a..6bda3fe2d 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml @@ -10,7 +10,7 @@ - + Machine Studio diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml index 25fe4af5d..6b80fad43 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Windows" mc:Ignorable="d" - WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Width="800" Height="600" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}"> + WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Width="800" Height="600" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}" FontFamily="{StaticResource flexo}" > diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml index 47b36070a..5db0277cc 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml @@ -10,7 +10,7 @@ xmlns:views="clr-namespace:Tango.MachineStudio.UI.Views" xmlns:sharedControls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="{Binding RelativeSource={RelativeSource Self},Path=ModuleContext.Module.Name}" Height="800" Width="1280" WindowStartupLocation="CenterOwner" WindowState="Maximized" Foreground="#494949" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}"> + Title="Machine Studio" Height="800" Width="1280" WindowStartupLocation="CenterOwner" WindowState="Maximized" Foreground="#494949" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}" FontFamily="{StaticResource flexo}"> @@ -29,8 +29,16 @@ - - + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs index 7ca062645..cfea78964 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ModuleWindow.xaml.cs @@ -12,6 +12,8 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Tango.Core.DI; +using Tango.MachineStudio.Common.StudioApplication; using Tango.MachineStudio.UI.ViewModels; namespace Tango.MachineStudio.UI.Windows @@ -32,6 +34,13 @@ namespace Tango.MachineStudio.UI.Windows public ModuleWindow() { InitializeComponent(); + + ContentRendered += ModuleWindow_ContentRendered; + } + + private void ModuleWindow_ContentRendered(object sender, EventArgs e) + { + Title = "MACHINE STUDIO " + TangoIOC.Default.GetInstance().Version.ToString(3); } public ModuleWindow(MainViewVM mainViewVM, ModuleWindowVM moduleVM, FrameworkElement view) : this() diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico new file mode 100644 index 000000000..dd159c221 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/machine_new_small.ico differ diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs index b84942643..e20b12d1a 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs @@ -60,7 +60,6 @@ namespace Tango.Integration.ExternalBridge public ExternalBridgeScanner() { _settings = SettingsManager.Default.GetOrCreate(); - _server = new UdpClient(_settings.ExternalBridgeServiceDiscoveryPort); AvailableMachines = new SynchronizedObservableCollection(); } @@ -73,6 +72,11 @@ namespace Tango.Integration.ExternalBridge { LogManager.Log("External bridge scanner started..."); + if (_server == null) + { + _server = new UdpClient(_settings.ExternalBridgeServiceDiscoveryPort); + } + IsStarted = true; foreach (var machine in AvailableMachines.OfType().ToList()) -- cgit v1.3.1 From c6ca09b04ceb4024311b86aab409ca658fbee37e Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 22 Dec 2019 14:51:17 +0200 Subject: Improved CanPrint and IsPrinting detection on PPC. Added support for PowerUp and StandBy states. Made sync jobs false by default. --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../PMR/Messages/MachineStatus/MachineState.proto | 2 +- .../PPC Installer-cache/cacheIndex.txt | Bin 52 -> 52 bytes .../Advanced Installer Projects/PPC Installer.aip | 18 +++--------------- .../Views/MainView.xaml | 2 -- .../Tango.MachineStudio.UI/Views/MainView.xaml | 3 +++ .../AppButtons/StartPrintingButton.cs | 4 ++-- .../Tango.PPC.Packages.CefInstaller.csproj | 1 + .../PPC/Tango.PPC.Common/PPCSettings.cs | 2 +- .../Controls/MachineStatusControl.xaml | 3 +++ .../PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml | 2 +- .../Tango.PPC.UI/Dialogs/ThreadLoadingView.xaml | 4 ++-- .../PPC/Tango.PPC.UI/Tango.PPC.UI.csproj | 3 ++- .../PPC/Tango.PPC.UI/Views/MainView.xaml | 3 +++ .../ExternalBridge/ExternalBridgeService.cs | 2 +- .../Tango.Integration/Operation/MachineOperator.cs | 15 +++++++-------- .../Tango.Integration/Operation/MachineStatuses.cs | 2 ++ .../Tango.PMR/MachineStatus/MachineState.cs | 10 +++++----- 21 files changed, 37 insertions(+), 39 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index 5badddf75..850314148 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 970fecb23..8d5be3eab 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 502353550..3c21d39f4 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index be848ac71..760a829e1 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/PMR/Messages/MachineStatus/MachineState.proto b/Software/PMR/Messages/MachineStatus/MachineState.proto index 0e84b8aaf..14d71ee48 100644 --- a/Software/PMR/Messages/MachineStatus/MachineState.proto +++ b/Software/PMR/Messages/MachineStatus/MachineState.proto @@ -5,7 +5,7 @@ option java_package = "com.twine.tango.pmr.machinestatus"; enum MachineState { - Initializing = 0; + PowerUp = 0; Ready = 1; Sleep = 2; Error = 3; 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 index ee0744fc9..a603ff06b 100644 Binary files a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt and b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer-cache/cacheIndex.txt differ diff --git a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip index 17bdd452f..6000cea68 100644 --- a/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip +++ b/Software/Visual_Studio/Advanced Installer Projects/PPC Installer.aip @@ -42,7 +42,6 @@ - @@ -178,21 +177,16 @@ - - - - - - + @@ -351,9 +345,9 @@ - + - + @@ -395,10 +389,7 @@ - - - @@ -408,9 +399,6 @@ - - - diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml index 53db8c11d..b580bd237 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml @@ -9,13 +9,11 @@ xmlns:vm="clr-namespace:Tango.MachineStudio.ActionLogs.ViewModels" xmlns:global="clr-namespace:Tango.MachineStudio.ActionLogs" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" - xmlns:localConverters="clr-namespace:Tango.MachineStudio.ActionLogs.Converters" mc:Ignorable="d" d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> - diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 3f1164526..020343ba0 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -368,6 +368,9 @@ + + + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/AppButtons/StartPrintingButton.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/AppButtons/StartPrintingButton.cs index 001888c92..4d6050639 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/AppButtons/StartPrintingButton.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/AppButtons/StartPrintingButton.cs @@ -15,12 +15,12 @@ namespace Tango.PPC.Jobs.AppButtons { op.StatusChanged += Op_StatusChanged; - Op_StatusChanged(this, op.Status); + Op_StatusChanged(op, op.Status); } private void Op_StatusChanged(object sender, MachineStatuses status) { - IsEnabled = status == MachineStatuses.ReadyToDye; + IsEnabled = (sender as IMachineOperator).CanPrint; } } } diff --git a/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj index 4cab8bab9..9ade464ea 100644 --- a/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj +++ b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj @@ -60,6 +60,7 @@ {74e700b0-1156-4126-be40-ee450d3c3026} Tango.Transport + False {0be74eee-22cb-4dba-b896-793b9e1a3ac0} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs index 96fe39a9b..3f11aaa13 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs @@ -264,7 +264,7 @@ namespace Tango.PPC.Common SupportedColorSpaces = new List(); SupportedJobTypes = new List(); PreviousApplicationVersion = "1.0.0.0"; - SynchronizeJobs = true; + SynchronizeJobs = false; SynchronizeDiagnostics = true; SynchronizationInterval = TimeSpan.FromMinutes(60); FirmwareVersion = "1.0.0.0"; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml index d6114576d..3404c032a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/MachineStatusControl.xaml @@ -17,6 +17,9 @@ + + + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml index 28f922898..081778434 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml @@ -13,7 +13,7 @@ Continue getting ready for: - + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/ThreadLoadingView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/ThreadLoadingView.xaml index 98f2e1381..f6fc7704a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/ThreadLoadingView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/ThreadLoadingView.xaml @@ -16,9 +16,9 @@ - The machine is ready for loading the thread. Please load the selected thread below and press 'continue'. + The machine is ready for thread loading. Please load the thread as instructed and press 'continue'. - + CONTINUE diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj index 0dbabbf56..bac736d98 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj @@ -659,6 +659,7 @@ RD /S /Q "$(TargetDir)pt-BR\" RD /S /Q "$(TargetDir)roslyn\" RD /S /Q "$(TargetDir)ProtoCompilers\" +RD /S /Q "$(TargetDir)Packages\ProtoCompilers\" if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)x86\" if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)x64\" @@ -681,7 +682,7 @@ if $(ConfigurationName) == Debug copy /Y "$(TargetDir)Packages" "$(TargetDir)" - + \ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml index 5be95ded4..185a5b7ce 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MainView.xaml @@ -83,6 +83,9 @@ + + + diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs index dfc8eb671..fef212316 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs @@ -722,7 +722,7 @@ namespace Tango.Integration.ExternalBridge { throw new InvalidOperationException($"Job execution is disabled while session intent is '{SessionIntent}'."); } - if (MachineOperator.Status != MachineStatuses.ReadyToDye) + if (MachineOperator.IsPrinting) { throw new InvalidOperationException($"Could not execute job while machine operator status is '{MachineOperator.Status}'."); } diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index 74c64930b..6d9a987cb 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -335,7 +335,7 @@ namespace Tango.Integration.Operation { get { - return Status == MachineStatuses.ReadyToDye; + return Status == MachineStatuses.ReadyToDye || Status == MachineStatuses.PowerUp || Status == MachineStatuses.Standby; } } @@ -921,8 +921,8 @@ namespace Tango.Integration.Operation switch (MachineStatus.State) { - case MachineState.Initializing: - //Status = MachineStatuses.Service; + case MachineState.PowerUp: + Status = MachineStatuses.PowerUp; break; //case MachineState.PreparingJob: // Status = MachineStatuses.GettingReady; @@ -1270,7 +1270,7 @@ namespace Tango.Integration.Operation ResumingJobEventArgs args = new ResumingJobEventArgs((job) => { - if (Status != MachineStatuses.ReadyToDye) + if (!CanPrint) { throw new InvalidOperationException("Could not print while status = " + Status); } @@ -1971,7 +1971,7 @@ namespace Tango.Integration.Operation { return Task.Factory.StartNew(() => { - if (Status != MachineStatuses.ReadyToDye) + if (!CanPrint) { throw new InvalidOperationException("Could not print while status = " + Status); } @@ -2418,7 +2418,7 @@ namespace Tango.Integration.Operation } } - if (Status != MachineStatuses.ReadyToDye) + if (!CanPrint) { throw new InvalidOperationException("Could not print while status = " + Status); } @@ -3093,7 +3093,7 @@ namespace Tango.Integration.Operation LogManager.Log("Starting firmware upgrade..."); LogManager.Log($"Firmware upgrade flags: {String.Join(", ", FirmwareUpgradeMode.GetFlags().Select(x => x.ToString()))}"); - if (Status != MachineStatuses.ReadyToDye) + if (!CanPrint) { throw LogManager.Log(new InvalidOperationException($"Could not perform firmware upgrade while operator status is '{Status}'.")); } @@ -3396,7 +3396,6 @@ namespace Tango.Integration.Operation { Thread.Sleep(2000); var r = SendRequest(new AbortPowerDownRequest()).Result; - throw new InvalidOperationException(); })); Task.Factory.StartNew(() => diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineStatuses.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineStatuses.cs index 14774f73a..d9a5d9f3f 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineStatuses.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineStatuses.cs @@ -11,6 +11,8 @@ namespace Tango.Integration.Operation { [Description("Disconnected")] Disconnected, + [Description("Getting Ready")] + PowerUp, [Description("Standby")] Standby, [Description("Ready To Dye")] diff --git a/Software/Visual_Studio/Tango.PMR/MachineStatus/MachineState.cs b/Software/Visual_Studio/Tango.PMR/MachineStatus/MachineState.cs index 9e3725f20..8f421e04d 100644 --- a/Software/Visual_Studio/Tango.PMR/MachineStatus/MachineState.cs +++ b/Software/Visual_Studio/Tango.PMR/MachineStatus/MachineState.cs @@ -23,10 +23,10 @@ namespace Tango.PMR.MachineStatus { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "ChJNYWNoaW5lU3RhdGUucHJvdG8SF1RhbmdvLlBNUi5NYWNoaW5lU3RhdHVz", - "KnEKDE1hY2hpbmVTdGF0ZRIQCgxJbml0aWFsaXppbmcQABIJCgVSZWFkeRAB", - "EgkKBVNsZWVwEAISCQoFRXJyb3IQAxIMCghQb3dlck9mZhAEEhAKDFByZXBh", - "cmluZ0pvYhAFEg4KClJ1bm5pbmdKb2IQBkIjCiFjb20udHdpbmUudGFuZ28u", - "cG1yLm1hY2hpbmVzdGF0dXNiBnByb3RvMw==")); + "KmwKDE1hY2hpbmVTdGF0ZRILCgdQb3dlclVwEAASCQoFUmVhZHkQARIJCgVT", + "bGVlcBACEgkKBUVycm9yEAMSDAoIUG93ZXJPZmYQBBIQCgxQcmVwYXJpbmdK", + "b2IQBRIOCgpSdW5uaW5nSm9iEAZCIwohY29tLnR3aW5lLnRhbmdvLnBtci5t", + "YWNoaW5lc3RhdHVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Tango.PMR.MachineStatus.MachineState), }, null)); @@ -36,7 +36,7 @@ namespace Tango.PMR.MachineStatus { } #region Enums public enum MachineState { - [pbr::OriginalName("Initializing")] Initializing = 0, + [pbr::OriginalName("PowerUp")] PowerUp = 0, [pbr::OriginalName("Ready")] Ready = 1, [pbr::OriginalName("Sleep")] Sleep = 2, [pbr::OriginalName("Error")] Error = 3, -- cgit v1.3.1 From 6a0ff2744f0f13a2070b53e9eff20ea9379ee350 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 15 Jan 2020 01:14:27 +0200 Subject: Working on SignalR ExternalBridge... --- .../MachineStudioSettings.cs | 12 + .../ViewModels/MachineConnectionViewVM.cs | 11 + .../Views/MachineConnectionView.xaml | 18 + .../ExternalBridge/PPCExternalBridgeService.cs | 10 + .../ExternalBridge/ExternalBridgeReceiver.cs | 5 + .../ExternalBridge/ExternalBridgeScanner.cs | 66 +- .../ExternalBridge/ExternalBridgeService.cs | 60 +- .../ExternalBridge/ExternalBridgeSignalRClient.cs | 75 + .../ExternalBridgeSignalRConfiguration.cs | 15 + .../ExternalBridge/ExternalBridgeTcpClient.cs | 6 +- .../ExternalBridge/IExternalBridgeService.cs | 5 + .../ExternalBridge/SignalRExternalBridgeClient.cs | 20 - .../Tango.Integration/Tango.Integration.csproj | 9 +- .../Tango.Integration/packages.config | 1 + .../Adapters/SignalRTransportAdapter.cs | 124 +- .../Tango.Transport/Compression/Common/CRC.cs | 55 + .../Compression/Common/CommandLineParser.cs | 274 ++++ .../Tango.Transport/Compression/Common/InBuffer.cs | 72 + .../Compression/Common/OutBuffer.cs | 47 + .../Tango.Transport/Compression/Compress/.DS_Store | Bin 0 -> 6148 bytes .../Compression/Compress/LZ/IMatchFinder.cs | 24 + .../Compression/Compress/LZ/LzBinTree.cs | 367 +++++ .../Compression/Compress/LZ/LzInWindow.cs | 132 ++ .../Compression/Compress/LZ/LzOutWindow.cs | 110 ++ .../Compression/Compress/LZMA/LzmaBase.cs | 76 + .../Compression/Compress/LZMA/LzmaDecoder.cs | 398 ++++++ .../Compression/Compress/LZMA/LzmaEncoder.cs | 1480 ++++++++++++++++++++ .../Compression/Compress/RangeCoder/RangeCoder.cs | 234 ++++ .../Compress/RangeCoder/RangeCoderBit.cs | 117 ++ .../Compress/RangeCoder/RangeCoderBitTree.cs | 157 +++ .../Tango.Transport/Compression/ICoder.cs | 145 ++ .../Tango.Transport/Compression/SevenZipHelper.cs | 105 ++ .../Tango.Transport/Tango.Transport.csproj | 19 +- .../Tango.Transport/TransporterBase.cs | 5 + .../Tango.MachineService/Hubs/ExternalBridgeHub.cs | 91 +- 35 files changed, 4277 insertions(+), 68 deletions(-) create mode 100644 Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRClient.cs create mode 100644 Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRConfiguration.cs delete mode 100644 Software/Visual_Studio/Tango.Integration/ExternalBridge/SignalRExternalBridgeClient.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Common/CRC.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Common/CommandLineParser.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Common/InBuffer.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Common/OutBuffer.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/.DS_Store create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/IMatchFinder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzBinTree.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzInWindow.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzOutWindow.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaBase.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaDecoder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaEncoder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBit.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBitTree.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/ICoder.cs create mode 100644 Software/Visual_Studio/Tango.Transport/Compression/SevenZipHelper.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs index 1831d5aa3..6ab26028f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/MachineStudioSettings.cs @@ -139,6 +139,16 @@ namespace Tango.MachineStudio.Common /// public TimeSpan ExternalBridgeContinuousRequestTimeout { get; set; } + /// + /// Gets or sets the external bridge SignalR hub. + /// + public String ExternalBridgeSignalRHub { get; set; } + + /// + /// Gets or sets a value indicating whether to enable external bridge scanning via SignalR. + /// + public bool EnableExternalBridgeSignalR { get; set; } + /// /// Gets the machine service address. /// @@ -179,6 +189,8 @@ namespace Tango.MachineStudio.Common JobUnitsMethod = JobUnitsMethods.Operator; ExternalBridgeRequestTimeout = TimeSpan.FromSeconds(5); ExternalBridgeContinuousRequestTimeout = TimeSpan.FromSeconds(5); + ExternalBridgeSignalRHub = "ExternalBridgeHub"; + EnableExternalBridgeSignalR = true; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs index 0ea47c24a..5e44bf43d 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs @@ -53,7 +53,18 @@ namespace Tango.MachineStudio.UI.ViewModels { if (_scanner == null) { + var settings = SettingsManager.Default.GetOrCreate(); _scanner = new ExternalBridgeScanner(); + _scanner.SignalRConfiguration.Enabled = settings.EnableExternalBridgeSignalR; + if (App.StartupArgs.Contains("-webDebug")) + { + _scanner.SignalRConfiguration.Address = "http://localhost:1111/"; //settings.DeploymentSlot.ToAddress(); + } + else + { + _scanner.SignalRConfiguration.Address = settings.DeploymentSlot.ToAddress(); + } + _scanner.SignalRConfiguration.Hub = settings.ExternalBridgeSignalRHub; } EnableDiagnostics = true; diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml index 581e87ed6..0ef498420 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml @@ -55,6 +55,24 @@ + + + + + + + S/N: + + + IP Address: + + + Organization: + + + + + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs index c50202e86..ae4f7432e 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExternalBridge/PPCExternalBridgeService.cs @@ -33,6 +33,16 @@ namespace Tango.PPC.Common.ExternalBridge var settings = SettingsManager.Default.GetOrCreate(); MachineOperator = machineProvider.MachineOperator; Machine = machineProvider.Machine; + SignalRConfiguration.Enabled = true; + if (Environment.CommandLine.Contains("-webDebug")) + { + SignalRConfiguration.Address = "http://localhost:1111/"; //settings.DeploymentSlot.ToAddress(); + } + else + { + SignalRConfiguration.Address = settings.DeploymentSlot.ToAddress(); + } + SignalRConfiguration.Hub = "ExternalBridgeHub"; Enabled = settings.EnableExternalBridge; }; } diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs index c43598746..366f1bbdb 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs @@ -124,6 +124,11 @@ namespace Tango.Integration.ExternalBridge Adapter = new TcpTransportAdapter(tcpClient); } + public ExternalBridgeReceiver(SignalRTransportAdapter signalRAdapter, IMachineOperator machineOperator) : this(machineOperator) + { + Adapter = signalRAdapter; + } + #endregion #region Override Methods diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs index d365de5c6..97f15f6b4 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeScanner.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.AspNet.SignalR.Client; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -14,6 +15,7 @@ using System.Threading; using System.Threading.Tasks; using Tango.Core; using Tango.Core.Helpers; +using Tango.Integration.ExternalBridge.Web; using Tango.Logging; using Tango.PMR; using Tango.PMR.Common; @@ -31,8 +33,11 @@ namespace Tango.Integration.ExternalBridge { private Thread _tcpDiscoveryThread; private Thread _usbDiscoveryThread; + private Thread _signalRDiscoveryThread; private UdpClient _server; private IntegrationSettings _settings; + private HubConnection _connection; + private IHubProxy _proxy; private SynchronizedObservableCollection _availableMachines; /// @@ -44,6 +49,11 @@ namespace Tango.Integration.ExternalBridge private set { _availableMachines = value; RaisePropertyChangedAuto(); } } + /// + /// Gets or sets the SignalR configuration. + /// + public ExternalBridgeSignalRConfiguration SignalRConfiguration { get; set; } + private bool _isStarted; /// /// Gets or sets a value indicating whether this instance is started. @@ -61,6 +71,7 @@ namespace Tango.Integration.ExternalBridge { _settings = SettingsManager.Default.GetOrCreate(); AvailableMachines = new SynchronizedObservableCollection(); + SignalRConfiguration = new ExternalBridgeSignalRConfiguration(); } /// @@ -93,6 +104,24 @@ namespace Tango.Integration.ExternalBridge _usbDiscoveryThread = new Thread(UsbDiscoveryThreadMethod); _usbDiscoveryThread.IsBackground = true; _usbDiscoveryThread.Start(); + + if (SignalRConfiguration.Enabled) + { + try + { + _connection = new HubConnection(SignalRConfiguration.Address); + _proxy = _connection.CreateHubProxy(SignalRConfiguration.Hub); + _connection.Start(); + + _signalRDiscoveryThread = new Thread(SignalRDiscoveryThreadMethod); + _signalRDiscoveryThread.IsBackground = true; + _signalRDiscoveryThread.Start(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } } } @@ -191,6 +220,41 @@ namespace Tango.Integration.ExternalBridge } } + private void SignalRDiscoveryThreadMethod() + { + while (IsStarted && SignalRConfiguration.Enabled) + { + if (_connection.State == ConnectionState.Connected) + { + try + { + var machines = _proxy.Invoke>("GetAvailableMachines").Result; + + foreach (var machine in AvailableMachines.OfType().ToList().Where(x => !machines.Exists(y => y.SerialNumber == x.SerialNumber))) + { + AvailableMachines.Remove(machine); + } + + foreach (var machine in machines.Where(x => !AvailableMachines.OfType().ToList().Exists(y => y.SerialNumber == x.SerialNumber))) + { + ExternalBridgeSignalRClient newMachine = new ExternalBridgeSignalRClient(SignalRConfiguration.Address, SignalRConfiguration.Hub, machine.SerialNumber); + + ThreadsHelper.InvokeUINow(() => + { + AvailableMachines.Insert(1, newMachine); + }); + } + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + Thread.Sleep(5000); + } + } + private DateTime ParseDateTime(String dateTime) { try diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs index a0f81c835..b4d2e4df4 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs @@ -23,6 +23,8 @@ using Tango.Core.ExtensionMethods; using Tango.PMR.MachineStatus; using Tango.PMR.Power; using Tango.Core; +using Microsoft.AspNet.SignalR.Client; +using Tango.Integration.ExternalBridge.Web; namespace Tango.Integration.ExternalBridge { @@ -33,6 +35,8 @@ namespace Tango.Integration.ExternalBridge private TcpServer _tcpServer; private int _discovery_port = 8888; //Will be overridden by settings in constructor.. private int _external_bridge_port = 1984; //Will be overridden by settings in constructor.. + private HubConnection _connection; + private IHubProxy _proxy; #region Events @@ -55,6 +59,11 @@ namespace Tango.Integration.ExternalBridge #region Properties + /// + /// Gets or sets the SignalR configuration. + /// + public ExternalBridgeSignalRConfiguration SignalRConfiguration { get; set; } + private IMachineOperator _machineOperator; /// /// Gets or sets the machine operator. @@ -128,6 +137,8 @@ namespace Tango.Integration.ExternalBridge /// public ExternalBridgeService() { + SignalRConfiguration = new ExternalBridgeSignalRConfiguration(); + _receivers = new List(); var settings = SettingsManager.Default.GetOrCreate(); @@ -205,7 +216,7 @@ namespace Tango.Integration.ExternalBridge /// The instance containing the event data. private async void _tcpServer_ClientConnected(object sender, ClientConnectedEventArgs e) { - LogManager.Log("External bridge client connected from: " + e.Socket.GetIPAddress()); + LogManager.Log("External bridge TCP client connected from: " + e.Socket.GetIPAddress()); ExternalBridgeReceiver receiver = new ExternalBridgeReceiver(e.Socket, MachineOperator); receiver.LoginRequest += Receiver_LoginRequest; receiver.ColorProfileRequest += Receiver_ColorProfileRequest; @@ -214,6 +225,21 @@ namespace Tango.Integration.ExternalBridge await receiver.Connect(); } + private async void OnSignalRSessionCreated(String sessionID) + { + LogManager.Log("External bridge SignalR client connected."); + + var adapter = new SignalRTransportAdapter(SignalRConfiguration.Address, SignalRConfiguration.Hub, SignalRTransportAdapter.SignalRTransportAdapterMode.JoinSession, Machine.SerialNumber, sessionID); ; + + ExternalBridgeReceiver receiver = new ExternalBridgeReceiver(adapter, MachineOperator); + receiver.LoginRequest += Receiver_LoginRequest; + receiver.ColorProfileRequest += Receiver_ColorProfileRequest; + receiver.Disconnected += Receiver_Disconnected; + _receivers.Add(receiver); + await receiver.Connect(); + //await _proxy.Invoke("NotifySessionCreated"); + } + private void MachineOperator_StatusChanged(object sender, MachineStatuses status) { try @@ -255,7 +281,13 @@ namespace Tango.Integration.ExternalBridge private void Receiver_Disconnected(object sender, EventArgs e) { var receiver = sender as ExternalBridgeReceiver; + + receiver.LoginRequest -= Receiver_LoginRequest; + receiver.ColorProfileRequest -= Receiver_ColorProfileRequest; + receiver.Disconnected -= Receiver_Disconnected; + _receivers.Remove(receiver); + if (receiver.LoginIntent == ExternalBridgeLoginIntent.FullControl) { ClientDisconnected?.Invoke(this, new EventArgs()); @@ -317,6 +349,25 @@ namespace Tango.Integration.ExternalBridge _tcpServer.Start(); _discoveryService.Start(); + if (SignalRConfiguration.Enabled) + { + _connection = new HubConnection(SignalRConfiguration.Address); + _proxy = _connection.CreateHubProxy(SignalRConfiguration.Hub); + _proxy.On("OnSessionCreated", OnSignalRSessionCreated); + _connection.Start(); + _connection.StateChanged += (x) => + { + if (x.NewState == ConnectionState.Connected) + { + _proxy.Invoke("RegisterMachine", new MachineInfo() + { + SerialNumber = Machine.SerialNumber, + Organization = Machine.Organization.Name, + }); + } + }; + } + IsStarted = true; _enabled = true; RaisePropertyChanged(nameof(Enabled)); @@ -338,6 +389,13 @@ namespace Tango.Integration.ExternalBridge await receiver.Disconnect(); } + if (SignalRConfiguration.Enabled) + { + await _proxy.Invoke("UnregisterMachine"); + _connection.Stop(); + _connection.Dispose(); + } + IsStarted = false; IsInSession = false; _enabled = false; diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRClient.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRClient.cs new file mode 100644 index 000000000..3a26e6a25 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRClient.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Authentication; +using System.Text; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.Integration.Operation; +using Tango.PMR.Integration; +using Tango.Settings; +using Tango.Transport; +using Tango.Transport.Adapters; + +namespace Tango.Integration.ExternalBridge +{ + public class ExternalBridgeSignalRClient : ExternalBridgeTcpClient + { + public ExternalBridgeSignalRClient(String url, String hub, String serialNumber) + { + SerialNumber = serialNumber; + Machine = ObservablesStaticCollections.Instance.Machines.SingleOrDefault(x => x.SerialNumber == serialNumber); + Adapter = new SignalRTransportAdapter(url, hub, SignalRTransportAdapter.SignalRTransportAdapterMode.CreateSession, serialNumber); + } + + public override async Task Connect(ExternalBridgeLoginRequest login) + { + if (State != TransportComponentState.Connected) + { + try + { + await Adapter.Connect(); + + State = TransportComponentState.Connected; + StartThreads(); + + LogManager.Log("External Bridge TCP Client Connected..."); + + + LogRequestSent(login); + + var response = await SendRequest(login); + + SessionLogger.CreateSession(); + + DeviceInformation = response.Message.DeviceInformation; + if (!response.Message.Authenticated) + { + await Adapter.Disconnect(); + throw new AuthenticationException(response.Container.ErrorMessage); + } + } + catch (Exception ex) + { + LogRequestFailed(login, ex); + try + { + await Adapter.Disconnect(); + } + catch { } + + throw ex; + } + + OnEnableDiagnosticsChanged(EnableDiagnostics); + OnEnableEmbeddedDebuggingChanged(EnableEmbeddedDebugging); + OnEnableEventsNotification(EnableEventsNotification); + OnEnableApplicationLogsChanged(EnableApplicationLogs); + OnEnableMachineStatusUpdatesChanged(EnableMachineStatusUpdates); + //TODO: Uncomment this only when Machine Studio enables automatic thread loading (ExternalBridgeTCPClient). + //OnEnableAutomaticThreadLoadingChanged(EnableAutomaticThreadLoading); + } + } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRConfiguration.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRConfiguration.cs new file mode 100644 index 000000000..cd511aa9b --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeSignalRConfiguration.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.ExternalBridge +{ + public class ExternalBridgeSignalRConfiguration + { + public bool Enabled { get; set; } + public String Address { get; set; } + public String Hub { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs index e7190ae0f..064b673bc 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs @@ -90,7 +90,7 @@ namespace Tango.Integration.ExternalBridge /// The login. /// /// The machine password is invalid. - public async Task Connect(ExternalBridgeLoginRequest login) + public virtual async Task Connect(ExternalBridgeLoginRequest login) { if (State != TransportComponentState.Connected) { @@ -140,7 +140,7 @@ namespace Tango.Integration.ExternalBridge } } - private async void OnEnableApplicationLogsChanged(bool value) + protected async void OnEnableApplicationLogsChanged(bool value) { if (value && State == TransportComponentState.Connected && !_logs_sent) { @@ -323,7 +323,7 @@ namespace Tango.Integration.ExternalBridge /// /// Gets the database machine associated with this client. /// - public Machine Machine { get; private set; } + public Machine Machine { get; protected set; } /// /// Sets the database machine. diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs index 966c8d569..39b2f4e07 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs @@ -72,5 +72,10 @@ namespace Tango.Integration.ExternalBridge /// Gets the current session login intent. /// ExternalBridgeLoginIntent SessionIntent { get; } + + /// + /// Gets or sets the SignalR configuration. + /// + ExternalBridgeSignalRConfiguration SignalRConfiguration { get; set; } } } diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/SignalRExternalBridgeClient.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/SignalRExternalBridgeClient.cs deleted file mode 100644 index df5076598..000000000 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/SignalRExternalBridgeClient.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.BL.Entities; -using Tango.Integration.Operation; -using Tango.PMR.Integration; -using Tango.Transport.Adapters; - -namespace Tango.Integration.ExternalBridge -{ - public class SignalRExternalBridgeClient : ExternalBridgeTcpClient - { - public SignalRExternalBridgeClient(String url, String hub, String serialNumber) - { - Adapter = new SignalRTransportAdapter(url, hub); - } - } -} diff --git a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj index e9a888a37..e4c27a7a5 100644 --- a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj +++ b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj @@ -42,6 +42,9 @@ ..\packages\Ionic.Zip.1.9.1.8\lib\Ionic.Zip.dll + + ..\packages\Microsoft.AspNet.SignalR.Client.2.4.1\lib\net45\Microsoft.AspNet.SignalR.Client.dll + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll @@ -51,6 +54,7 @@ + ..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll @@ -97,7 +101,8 @@ - + + @@ -203,7 +208,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Integration/packages.config b/Software/Visual_Studio/Tango.Integration/packages.config index 56f5092b2..542b7a059 100644 --- a/Software/Visual_Studio/Tango.Integration/packages.config +++ b/Software/Visual_Studio/Tango.Integration/packages.config @@ -3,6 +3,7 @@ + diff --git a/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs index 77d5abe41..6e1f60232 100644 --- a/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs @@ -1,41 +1,152 @@ using Microsoft.AspNet.SignalR.Client; using System; +using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; +using Tango.Core; namespace Tango.Transport.Adapters { public class SignalRTransportAdapter : TransportAdapterBase { + public enum SignalRTransportAdapterMode + { + CreateSession, + JoinSession + } + private IHubProxy _proxy; private HubConnection _connection; + private Thread _pushThread; + private ProducerConsumerQueue _pushQueue; public String Hub { get; set; } + public String SerialNumber { get; set; } + + public String SessionID { get; set; } + + public SignalRTransportAdapterMode Mode { get; set; } + public SignalRTransportAdapter() : base() { - + ComponentName = $"SignalR Adapter {_component_counter++}"; + _pushThread = new Thread(PushThreadMethod); + _pushThread.IsBackground = true; + _pushThread.Name = $"{ComponentName} Push Thread"; + _pushQueue = new ProducerConsumerQueue(); } - public SignalRTransportAdapter(String url, String hub) : this() + public SignalRTransportAdapter(String url, String hub, SignalRTransportAdapterMode mode, String serialNumber = null, String sessionID = null) : this() { Address = url; Hub = hub; + Mode = mode; + SerialNumber = serialNumber; + SessionID = sessionID; } public override void Write(byte[] data) { - _proxy.Invoke("Write", data).GetAwaiter().GetResult(); + _pushQueue.BlockEnqueue(data); + } + + private void PushThreadMethod() + { + while (State == TransportComponentState.Connected) + { + List dataCollection = new List(); + + var data = _pushQueue.BlockDequeue(); + var first = true; + + while (_pushQueue.Count > 0 || first) + { + if (!first) + { + data = _pushQueue.BlockDequeue(); + } + else + { + first = false; + } + + var compressed = Compression.SevenZipHelper.Compress(data); + dataCollection.Add(compressed); + } + + if (dataCollection.Count > 0) + { + try + { + _proxy.Invoke("Write", dataCollection).GetAwaiter().GetResult(); + } + catch (Exception ex) + { + OnFailed(ex); + return; + } + } + + Thread.Sleep(1000); + } } public override Task Connect() { - return Task.Factory.StartNew(() => + if (State != TransportComponentState.Connected) { + TaskCompletionSource completionSource = new TaskCompletionSource(); + _connection = new HubConnection(Address); _proxy = _connection.CreateHubProxy(Hub); - _proxy.On("DataAvailable", (data) => { OnDataAvailable(data); }); + + if (Mode == SignalRTransportAdapterMode.CreateSession) + { + _proxy.On("SessionCreated", () => + { + State = TransportComponentState.Connected; + _pushThread.Start(); + completionSource.SetResult(true); + }); + } + + _connection.StateChanged += async (x) => + { + if (x.NewState == ConnectionState.Connected) + { + if (Mode == SignalRTransportAdapterMode.CreateSession) + { + SessionID = await _proxy.Invoke("CreateSession", SerialNumber); + } + else + { + await _proxy.Invoke("JoinSession", SessionID); + } + + if (Mode == SignalRTransportAdapterMode.JoinSession) + { + State = TransportComponentState.Connected; + _pushThread.Start(); + completionSource.SetResult(true); + } + } + }; + _proxy.On>("DataAvailable", (dataCollection) => { OnDataAvailable(dataCollection); }); _connection.Start(); - }); + + return completionSource.Task; + } + + return Task.FromResult(true); + } + + private void OnDataAvailable(List dataCollection) + { + foreach (var data in dataCollection) + { + OnDataAvailable(Compression.SevenZipHelper.Decompress(data)); + } } public override Task Disconnect() @@ -44,6 +155,7 @@ namespace Tango.Transport.Adapters { _connection.Stop(); _connection.Dispose(); + State = TransportComponentState.Disconnected; }); } } diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Common/CRC.cs b/Software/Visual_Studio/Tango.Transport/Compression/Common/CRC.cs new file mode 100644 index 000000000..59fd06bde --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Common/CRC.cs @@ -0,0 +1,55 @@ +// Common/CRC.cs + +namespace Tango.Transport.Compression +{ + class CRC + { + public static readonly uint[] Table; + + static CRC() + { + Table = new uint[256]; + const uint kPoly = 0xEDB88320; + for (uint i = 0; i < 256; i++) + { + uint r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >> 1) ^ kPoly; + else + r >>= 1; + Table[i] = r; + } + } + + uint _value = 0xFFFFFFFF; + + public void Init() { _value = 0xFFFFFFFF; } + + public void UpdateByte(byte b) + { + _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); + } + + public void Update(byte[] data, uint offset, uint size) + { + for (uint i = 0; i < size; i++) + _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); + } + + public uint GetDigest() { return _value ^ 0xFFFFFFFF; } + + static uint CalculateDigest(byte[] data, uint offset, uint size) + { + CRC crc = new CRC(); + // crc.Init(); + crc.Update(data, offset, size); + return crc.GetDigest(); + } + + static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) + { + return (CalculateDigest(data, offset, size) == digest); + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Common/CommandLineParser.cs b/Software/Visual_Studio/Tango.Transport/Compression/Common/CommandLineParser.cs new file mode 100644 index 000000000..dd0cb45d1 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Common/CommandLineParser.cs @@ -0,0 +1,274 @@ +// CommandLineParser.cs + +using System; +using System.Collections; + +namespace Tango.Transport.Compression.CommandLineParser +{ + public enum SwitchType + { + Simple, + PostMinus, + LimitedPostString, + UnLimitedPostString, + PostChar + } + + public class SwitchForm + { + public string IDString; + public SwitchType Type; + public bool Multi; + public int MinLen; + public int MaxLen; + public string PostCharSet; + + public SwitchForm(string idString, SwitchType type, bool multi, + int minLen, int maxLen, string postCharSet) + { + IDString = idString; + Type = type; + Multi = multi; + MinLen = minLen; + MaxLen = maxLen; + PostCharSet = postCharSet; + } + public SwitchForm(string idString, SwitchType type, bool multi, int minLen): + this(idString, type, multi, minLen, 0, "") + { + } + public SwitchForm(string idString, SwitchType type, bool multi): + this(idString, type, multi, 0) + { + } + } + + public class SwitchResult + { + public bool ThereIs; + public bool WithMinus; + public ArrayList PostStrings = new ArrayList(); + public int PostCharIndex; + public SwitchResult() + { + ThereIs = false; + } + } + + public class Parser + { + public ArrayList NonSwitchStrings = new ArrayList(); + SwitchResult[] _switches; + + public Parser(int numSwitches) + { + _switches = new SwitchResult[numSwitches]; + for (int i = 0; i < numSwitches; i++) + _switches[i] = new SwitchResult(); + } + + bool ParseString(string srcString, SwitchForm[] switchForms) + { + int len = srcString.Length; + if (len == 0) + return false; + int pos = 0; + if (!IsItSwitchChar(srcString[pos])) + return false; + while (pos < len) + { + if (IsItSwitchChar(srcString[pos])) + pos++; + const int kNoLen = -1; + int matchedSwitchIndex = 0; + int maxLen = kNoLen; + for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) + { + int switchLen = switchForms[switchIndex].IDString.Length; + if (switchLen <= maxLen || pos + switchLen > len) + continue; + if (String.Compare(switchForms[switchIndex].IDString, 0, + srcString, pos, switchLen, true) == 0) + { + matchedSwitchIndex = switchIndex; + maxLen = switchLen; + } + } + if (maxLen == kNoLen) + throw new Exception("maxLen == kNoLen"); + SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; + SwitchForm switchForm = switchForms[matchedSwitchIndex]; + if ((!switchForm.Multi) && matchedSwitch.ThereIs) + throw new Exception("switch must be single"); + matchedSwitch.ThereIs = true; + pos += maxLen; + int tailSize = len - pos; + SwitchType type = switchForm.Type; + switch (type) + { + case SwitchType.PostMinus: + { + if (tailSize == 0) + matchedSwitch.WithMinus = false; + else + { + matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); + if (matchedSwitch.WithMinus) + pos++; + } + break; + } + case SwitchType.PostChar: + { + if (tailSize < switchForm.MinLen) + throw new Exception("switch is not full"); + string charSet = switchForm.PostCharSet; + const int kEmptyCharValue = -1; + if (tailSize == 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + int index = charSet.IndexOf(srcString[pos]); + if (index < 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + matchedSwitch.PostCharIndex = index; + pos++; + } + } + break; + } + case SwitchType.LimitedPostString: + case SwitchType.UnLimitedPostString: + { + int minLen = switchForm.MinLen; + if (tailSize < minLen) + throw new Exception("switch is not full"); + if (type == SwitchType.UnLimitedPostString) + { + matchedSwitch.PostStrings.Add(srcString.Substring(pos)); + return true; + } + String stringSwitch = srcString.Substring(pos, minLen); + pos += minLen; + for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) + { + char c = srcString[pos]; + if (IsItSwitchChar(c)) + break; + stringSwitch += c; + } + matchedSwitch.PostStrings.Add(stringSwitch); + break; + } + } + } + return true; + + } + + public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) + { + int numCommandStrings = commandStrings.Length; + bool stopSwitch = false; + for (int i = 0; i < numCommandStrings; i++) + { + string s = commandStrings[i]; + if (stopSwitch) + NonSwitchStrings.Add(s); + else + if (s == kStopSwitchParsing) + stopSwitch = true; + else + if (!ParseString(s, switchForms)) + NonSwitchStrings.Add(s); + } + } + + public SwitchResult this[int index] { get { return _switches[index]; } } + + public static int ParseCommand(CommandForm[] commandForms, string commandString, + out string postString) + { + for (int i = 0; i < commandForms.Length; i++) + { + string id = commandForms[i].IDString; + if (commandForms[i].PostStringMode) + { + if (commandString.IndexOf(id) == 0) + { + postString = commandString.Substring(id.Length); + return i; + } + } + else + if (commandString == id) + { + postString = ""; + return i; + } + } + postString = ""; + return -1; + } + + static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, + string commandString, ArrayList indices) + { + indices.Clear(); + int numUsedChars = 0; + for (int i = 0; i < numForms; i++) + { + CommandSubCharsSet charsSet = forms[i]; + int currentIndex = -1; + int len = charsSet.Chars.Length; + for (int j = 0; j < len; j++) + { + char c = charsSet.Chars[j]; + int newIndex = commandString.IndexOf(c); + if (newIndex >= 0) + { + if (currentIndex >= 0) + return false; + if (commandString.IndexOf(c, newIndex + 1) >= 0) + return false; + currentIndex = j; + numUsedChars++; + } + } + if (currentIndex == -1 && !charsSet.EmptyAllowed) + return false; + indices.Add(currentIndex); + } + return (numUsedChars == commandString.Length); + } + const char kSwitchID1 = '-'; + const char kSwitchID2 = '/'; + + const char kSwitchMinus = '-'; + const string kStopSwitchParsing = "--"; + + static bool IsItSwitchChar(char c) + { + return (c == kSwitchID1 || c == kSwitchID2); + } + } + + public class CommandForm + { + public string IDString = ""; + public bool PostStringMode = false; + public CommandForm(string idString, bool postStringMode) + { + IDString = idString; + PostStringMode = postStringMode; + } + } + + class CommandSubCharsSet + { + public string Chars = ""; + public bool EmptyAllowed = false; + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Common/InBuffer.cs b/Software/Visual_Studio/Tango.Transport/Compression/Common/InBuffer.cs new file mode 100644 index 000000000..012954dfa --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Common/InBuffer.cs @@ -0,0 +1,72 @@ +// InBuffer.cs + +namespace Tango.Transport.Compression +{ + public class InBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_Limit; + uint m_BufferSize; + System.IO.Stream m_Stream; + bool m_StreamWasExhausted; + ulong m_ProcessedSize; + + public InBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void Init(System.IO.Stream stream) + { + m_Stream = stream; + m_ProcessedSize = 0; + m_Limit = 0; + m_Pos = 0; + m_StreamWasExhausted = false; + } + + public bool ReadBlock() + { + if (m_StreamWasExhausted) + return false; + m_ProcessedSize += m_Pos; + int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); + m_Pos = 0; + m_Limit = (uint)aNumProcessedBytes; + m_StreamWasExhausted = (aNumProcessedBytes == 0); + return (!m_StreamWasExhausted); + } + + + public void ReleaseStream() + { + // m_Stream.Close(); + m_Stream = null; + } + + public bool ReadByte(byte b) // check it + { + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return false; + b = m_Buffer[m_Pos++]; + return true; + } + + public byte ReadByte() + { + // return (byte)m_Stream.ReadByte(); + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return 0xFF; + return m_Buffer[m_Pos++]; + } + + public ulong GetProcessedSize() + { + return m_ProcessedSize + m_Pos; + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Common/OutBuffer.cs b/Software/Visual_Studio/Tango.Transport/Compression/Common/OutBuffer.cs new file mode 100644 index 000000000..624ecf937 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Common/OutBuffer.cs @@ -0,0 +1,47 @@ +// OutBuffer.cs + +namespace Tango.Transport.Compression +{ + public class OutBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_BufferSize; + System.IO.Stream m_Stream; + ulong m_ProcessedSize; + + public OutBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void SetStream(System.IO.Stream stream) { m_Stream = stream; } + public void FlushStream() { m_Stream.Flush(); } + public void CloseStream() { m_Stream.Close(); } + public void ReleaseStream() { m_Stream = null; } + + public void Init() + { + m_ProcessedSize = 0; + m_Pos = 0; + } + + public void WriteByte(byte b) + { + m_Buffer[m_Pos++] = b; + if (m_Pos >= m_BufferSize) + FlushData(); + } + + public void FlushData() + { + if (m_Pos == 0) + return; + m_Stream.Write(m_Buffer, 0, (int)m_Pos); + m_Pos = 0; + } + + public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/.DS_Store b/Software/Visual_Studio/Tango.Transport/Compression/Compress/.DS_Store new file mode 100644 index 000000000..c6fa379b8 Binary files /dev/null and b/Software/Visual_Studio/Tango.Transport/Compression/Compress/.DS_Store differ diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/IMatchFinder.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/IMatchFinder.cs new file mode 100644 index 000000000..6f68bee3a --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/IMatchFinder.cs @@ -0,0 +1,24 @@ +// IMatchFinder.cs + +using System; + +namespace Tango.Transport.Compression.LZ +{ + interface IInWindowStream + { + void SetStream(System.IO.Stream inStream); + void Init(); + void ReleaseStream(); + Byte GetIndexByte(Int32 index); + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); + UInt32 GetNumAvailableBytes(); + } + + interface IMatchFinder : IInWindowStream + { + void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + UInt32 GetMatches(UInt32[] distances); + void Skip(UInt32 num); + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzBinTree.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzBinTree.cs new file mode 100644 index 000000000..b09701788 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzBinTree.cs @@ -0,0 +1,367 @@ +// LzBinTree.cs + +using System; + +namespace Tango.Transport.Compression.LZ +{ + public class BinTree : InWindow, IMatchFinder + { + UInt32 _cyclicBufferPos; + UInt32 _cyclicBufferSize = 0; + UInt32 _matchMaxLen; + + UInt32[] _son; + UInt32[] _hash; + + UInt32 _cutValue = 0xFF; + UInt32 _hashMask; + UInt32 _hashSizeSum = 0; + + bool HASH_ARRAY = true; + + const UInt32 kHash2Size = 1 << 10; + const UInt32 kHash3Size = 1 << 16; + const UInt32 kBT2HashSize = 1 << 16; + const UInt32 kStartMaxLen = 1; + const UInt32 kHash3Offset = kHash2Size; + const UInt32 kEmptyHashValue = 0; + const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; + + UInt32 kNumHashDirectBytes = 0; + UInt32 kMinMatchCheck = 4; + UInt32 kFixHashSize = kHash2Size + kHash3Size; + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } + public new void ReleaseStream() { base.ReleaseStream(); } + + public new void Init() + { + base.Init(); + for (UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public new void MovePos() + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + base.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } + + public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { return base.GetMatchLen(index, distance, limit); } + + public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } + + public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) + { + if (historySize > kMaxValForNormalize - 256) + throw new Exception(); + _cutValue = 16 + (matchMaxLen >> 1); + + UInt32 windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + + base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + UInt32 cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; + + UInt32 hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new UInt32[_hashSizeSum = hs]; + } + + public UInt32 GetMatches(UInt32[] distances) + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + UInt32 offset = 0; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + UInt32 hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + hash2Value = temp & (kHash2Size - 1); + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + hash3Value = temp & (kHash3Size - 1); + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + UInt32 curMatch2 = _hash[hash2Value]; + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + UInt32 count = _cutValue; + + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while(++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(UInt32 num) + { + do + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + + UInt32 hashValue; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + UInt32 hash2Value = temp & (kHash2Size - 1); + _hash[hash2Value] = _pos; + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + UInt32 hash3Value = temp & (kHash3Size - 1); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + UInt32 count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } + while (--num != 0); + } + + void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) + { + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + void Normalize() + { + UInt32 subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets((Int32)subValue); + } + + public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzInWindow.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzInWindow.cs new file mode 100644 index 000000000..fd8f6fc9a --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzInWindow.cs @@ -0,0 +1,132 @@ +// LzInWindow.cs + +using System; + +namespace Tango.Transport.Compression.LZ +{ + public class InWindow + { + public Byte[] _bufferBase = null; // pointer to buffer with data + System.IO.Stream _stream; + UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + UInt32 _pointerToLastSafePosition; + + public UInt32 _bufferOffset; + + public UInt32 _blockSize; // Size of Allocated memory block + public UInt32 _pos; // offset (from _buffer) of curent byte + UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + public void MoveBlock() + { + UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; + + // check negative offset ???? + for (UInt32 i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public virtual void ReadBlock() + { + if (_streamEndWasReached) + return; + while (true) + { + int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); + if (size == 0) + return; + int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); + if (numReadBytes == 0) + { + _posLimit = _streamPos; + UInt32 pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); + + _streamEndWasReached = true; + return; + } + _streamPos += (UInt32)numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + void Free() { _bufferBase = null; } + + public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new Byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(System.IO.Stream stream) { _stream = stream; } + public void ReleaseStream() { _stream = null; } + + public void Init() + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() + { + _pos++; + if (_pos > _posLimit) + { + UInt32 pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (UInt32)(_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + UInt32 pby = _bufferOffset + _pos + (UInt32)index; + + UInt32 i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); + return i; + } + + public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } + + public void ReduceOffsets(Int32 subValue) + { + _bufferOffset += (UInt32)subValue; + _posLimit -= (UInt32)subValue; + _pos -= (UInt32)subValue; + _streamPos -= (UInt32)subValue; + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzOutWindow.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzOutWindow.cs new file mode 100644 index 000000000..611e6b35e --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZ/LzOutWindow.cs @@ -0,0 +1,110 @@ +// LzOutWindow.cs + +namespace Tango.Transport.Compression.LZ +{ + public class OutWindow + { + byte[] _buffer = null; + uint _pos; + uint _windowSize = 0; + uint _streamPos; + System.IO.Stream _stream; + + public uint TrainSize = 0; + + public void Create(uint windowSize) + { + if (_windowSize != windowSize) + { + // System.GC.Collect(); + _buffer = new byte[windowSize]; + } + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void Init(System.IO.Stream stream, bool solid) + { + ReleaseStream(); + _stream = stream; + if (!solid) + { + _streamPos = 0; + _pos = 0; + TrainSize = 0; + } + } + + public bool Train(System.IO.Stream stream) + { + long len = stream.Length; + uint size = (len < _windowSize) ? (uint)len : _windowSize; + TrainSize = size; + stream.Position = len - size; + _streamPos = _pos = 0; + while (size > 0) + { + uint curSize = _windowSize - _pos; + if (size < curSize) + curSize = size; + int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); + if (numReadBytes == 0) + return false; + size -= (uint)numReadBytes; + _pos += (uint)numReadBytes; + _streamPos += (uint)numReadBytes; + if (_pos == _windowSize) + _streamPos = _pos = 0; + } + return true; + } + + public void ReleaseStream() + { + Flush(); + _stream = null; + } + + public void Flush() + { + uint size = _pos - _streamPos; + if (size == 0) + return; + _stream.Write(_buffer, (int)_streamPos, (int)size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(uint distance, uint len) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + for (; len > 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(uint distance) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaBase.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaBase.cs new file mode 100644 index 000000000..b2b898673 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaBase.cs @@ -0,0 +1,76 @@ +// LzmaBase.cs + +namespace Tango.Transport.Compression.LZMA +{ + internal abstract class Base + { + public const uint kNumRepDistances = 4; + public const uint kNumStates = 12; + + // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; + // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; + // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; + // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + + public struct State + { + public uint Index; + public void Init() { Index = 0; } + public void UpdateChar() + { + if (Index < 4) Index = 0; + else if (Index < 10) Index -= 3; + else Index -= 6; + } + public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } + public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } + public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } + public bool IsCharState() { return Index < 7; } + } + + public const int kNumPosSlotBits = 6; + public const int kDicLogSizeMin = 0; + // public const int kDicLogSizeMax = 30; + // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; + + public const int kNumLenToPosStatesBits = 2; // it's for speed optimization + public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + + public const uint kMatchMinLen = 2; + + public static uint GetLenToPosState(uint len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (uint)(kNumLenToPosStates - 1); + } + + public const int kNumAlignBits = 4; + public const uint kAlignTableSize = 1 << kNumAlignBits; + public const uint kAlignMask = (kAlignTableSize - 1); + + public const uint kStartPosModelIndex = 4; + public const uint kEndPosModelIndex = 14; + public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + + public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); + + public const uint kNumLitPosStatesBitsEncodingMax = 4; + public const uint kNumLitContextBitsMax = 8; + + public const int kNumPosStatesBitsMax = 4; + public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public const int kNumPosStatesBitsEncodingMax = 4; + public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + public const int kNumLowLenBits = 3; + public const int kNumMidLenBits = 3; + public const int kNumHighLenBits = 8; + public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; + public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; + public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaDecoder.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaDecoder.cs new file mode 100644 index 000000000..d6314be7b --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaDecoder.cs @@ -0,0 +1,398 @@ +// LzmaDecoder.cs + +using System; + +namespace Tango.Transport.Compression.LZMA +{ + using RangeCoder; + + public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream + { + class LenDecoder + { + BitDecoder m_Choice = new BitDecoder(); + BitDecoder m_Choice2 = new BitDecoder(); + BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + uint m_NumPosStates = 0; + + public void Create(uint numPosStates) + { + for (uint posState = m_NumPosStates; posState < numPosStates; posState++) + { + m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); + } + m_NumPosStates = numPosStates; + } + + public void Init() + { + m_Choice.Init(); + for (uint posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_Choice2.Init(); + m_HighCoder.Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) + { + if (m_Choice.Decode(rangeDecoder) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + else + { + uint symbol = Base.kNumLowLenSymbols; + if (m_Choice2.Decode(rangeDecoder) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + { + symbol += Base.kNumMidLenSymbols; + symbol += m_HighCoder.Decode(rangeDecoder); + } + return symbol; + } + } + } + + class LiteralDecoder + { + struct Decoder2 + { + BitDecoder[] m_Decoders; + public void Create() { m_Decoders = new BitDecoder[0x300]; } + public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) + { + uint symbol = 1; + do + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + while (symbol < 0x100); + return (byte)symbol; + } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) + { + uint symbol = 1; + do + { + uint matchBit = (uint)(matchByte >> 7) & 1; + matchByte <<= 1; + uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + break; + } + } + while (symbol < 0x100); + return (byte)symbol; + } + } + + Decoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && + m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + uint GetState(uint pos, byte prevByte) + { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) + { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) + { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } + }; + + LZ.OutWindow m_OutWindow = new LZ.OutWindow(); + RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); + + BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + + BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + LenDecoder m_LenDecoder = new LenDecoder(); + LenDecoder m_RepLenDecoder = new LenDecoder(); + + LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + + uint m_DictionarySize; + uint m_DictionarySizeCheck; + + uint m_PosStateMask; + + public Decoder() + { + m_DictionarySize = 0xFFFFFFFF; + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + void SetDictionarySize(uint dictionarySize) + { + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); + uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); + m_OutWindow.Create(blockSize); + } + } + + void SetLiteralProperties(int lp, int lc) + { + if (lp > 8) + throw new InvalidParamException(); + if (lc > 8) + throw new InvalidParamException(); + m_LiteralDecoder.Create(lp, lc); + } + + void SetPosBitsProperties(int pb) + { + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + uint numPosStates = (uint)1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + } + + bool _solid = false; + void Init(System.IO.Stream inStream, System.IO.Stream outStream) + { + m_RangeDecoder.Init(inStream); + m_OutWindow.Init(outStream, _solid); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= m_PosStateMask; j++) + { + uint index = (i << Base.kNumPosStatesBitsMax) + j; + m_IsMatchDecoders[index].Init(); + m_IsRep0LongDecoders[index].Init(); + } + m_IsRepDecoders[i].Init(); + m_IsRepG0Decoders[i].Init(); + m_IsRepG1Decoders[i].Init(); + m_IsRepG2Decoders[i].Init(); + } + + m_LiteralDecoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + // m_PosSpecDecoder.Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + m_PosDecoders[i].Init(); + + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + } + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + Init(inStream, outStream); + + Base.State state = new Base.State(); + state.Init(); + uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + UInt64 nowPos64 = 0; + UInt64 outSize64 = (UInt64)outSize; + if (nowPos64 < outSize64) + { + if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) + throw new DataErrorException(); + state.UpdateChar(); + byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); + m_OutWindow.PutByte(b); + nowPos64++; + } + while (nowPos64 < outSize64) + { + // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); + // while(nowPos64 < next) + { + uint posState = (uint)nowPos64 & m_PosStateMask; + if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + byte b; + byte prevByte = m_OutWindow.GetByte(0); + if (!state.IsCharState()) + b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, + (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); + else + b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); + m_OutWindow.PutByte(b); + state.UpdateChar(); + nowPos64++; + } + else + { + uint len; + if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) + { + if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + state.UpdateShortRep(); + m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); + nowPos64++; + continue; + } + } + else + { + UInt32 distance; + if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + distance = rep1; + } + else + { + if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state.UpdateRep(); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state.UpdateMatch(); + uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + int numDirectBits = (int)((posSlot >> 1) - 1); + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + } + } + else + rep0 = posSlot; + } + if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) + { + if (rep0 == 0xFFFFFFFF) + break; + throw new DataErrorException(); + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + } + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + } + + public void SetDecoderProperties(byte[] properties) + { + if (properties.Length < 5) + throw new InvalidParamException(); + int lc = properties[0] % 9; + int remainder = properties[0] / 9; + int lp = remainder % 5; + int pb = remainder / 5; + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + UInt32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); + SetDictionarySize(dictionarySize); + SetLiteralProperties(lp, lc); + SetPosBitsProperties(pb); + } + + public bool Train(System.IO.Stream stream) + { + _solid = true; + return m_OutWindow.Train(stream); + } + + /* + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return true; }} + public override bool CanSeek { get { return true; }} + public override long Length { get { return 0; }} + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + public override void Write(byte[] buffer, int offset, int count) + { + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + return 0; + } + public override void SetLength(long value) {} + */ + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaEncoder.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaEncoder.cs new file mode 100644 index 000000000..3341be17a --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/LZMA/LzmaEncoder.cs @@ -0,0 +1,1480 @@ +// LzmaEncoder.cs + +using System; + +namespace Tango.Transport.Compression.LZMA +{ + using RangeCoder; + + public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + { + enum EMatchFinderType + { + BT2, + BT4, + }; + + const UInt32 kIfinityPrice = 0xFFFFFFF; + + static Byte[] g_FastPos = new Byte[1 << 11]; + + static Encoder() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } + + static UInt32 GetPosSlot(UInt32 pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (UInt32)(g_FastPos[pos >> 10] + 20); + return (UInt32)(g_FastPos[pos >> 20] + 40); + } + + static UInt32 GetPosSlot2(UInt32 pos) + { + if (pos < (1 << 17)) + return (UInt32)(g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (UInt32)(g_FastPos[pos >> 16] + 32); + return (UInt32)(g_FastPos[pos >> 26] + 52); + } + + Base.State _state = new Base.State(); + Byte _previousByte; + UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; + + void BaseInit() + { + _state.Init(); + _previousByte = 0; + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + const int kDefaultDictionaryLogSize = 22; + const UInt32 kNumFastBytesDefault = 0x20; + + class LiteralEncoder + { + public struct Encoder2 + { + BitEncoder[] m_Encoders; + + public void Create() { m_Encoders = new BitEncoder[0x300]; } + + public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } + + public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) + { + uint context = 1; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + m_Encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) + { + uint context = 1; + bool same = true; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + uint state = context; + if (same) + { + uint matchBit = (uint)((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + m_Encoders[state].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public uint GetPrice(bool matchMode, byte matchByte, byte symbol) + { + uint price = 0; + uint context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + uint matchBit = (uint)(matchByte >> i) & 1; + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; + } + } + + Encoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) + { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } + } + + class LenEncoder + { + RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); + RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); + RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); + + public LenEncoder() + { + for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(UInt32 numPosStates) + { + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + if (symbol < Base.kNumLowLenSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + _choice.Encode(rangeEncoder, 1); + if (symbol < Base.kNumMidLenSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) + { + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + }; + + const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + class LenPriceTableEncoder : LenEncoder + { + UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; + UInt32 _tableSize; + UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; + + public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } + + public UInt32 GetPrice(UInt32 symbol, UInt32 posState) + { + return _prices[posState * Base.kNumLenSymbols + symbol]; + } + + void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); + _counters[posState] = _tableSize; + } + + public void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + + public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + base.Encode(rangeEncoder, symbol, posState); + if (--_counters[posState] == 0) + UpdateTable(posState); + } + } + + const UInt32 kNumOpts = 1 << 12; + class Optimal + { + public Base.State State; + + public bool Prev1IsChar; + public bool Prev2; + + public UInt32 PosPrev2; + public UInt32 BackPrev2; + + public UInt32 Price; + public UInt32 PosPrev; + public UInt32 BackPrev; + + public UInt32 Backs0; + public UInt32 Backs1; + public UInt32 Backs2; + public UInt32 Backs3; + + public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } + public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + public bool IsShortRep() { return (BackPrev == 0); } + }; + Optimal[] _optimum = new Optimal[kNumOpts]; + LZ.IMatchFinder _matchFinder = null; + RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); + + RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; + + RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); + + LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); + LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); + + LiteralEncoder _literalEncoder = new LiteralEncoder(); + + UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; + + UInt32 _numFastBytes = kNumFastBytesDefault; + UInt32 _longestMatchLength; + UInt32 _numDistancePairs; + + UInt32 _additionalOffset; + + UInt32 _optimumEndIndex; + UInt32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; + UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; + UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; + UInt32 _alignPriceCount; + + UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); + + int _posStateBits = 2; + UInt32 _posStateMask = (4 - 1); + int _numLiteralPosStateBits = 0; + int _numLiteralContextBits = 3; + + UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); + UInt32 _dictionarySizePrev = 0xFFFFFFFF; + UInt32 _numFastBytesPrev = 0xFFFFFFFF; + + Int64 nowPos64; + bool _finished; + System.IO.Stream _inStream; + + EMatchFinderType _matchFinderType = EMatchFinderType.BT4; + bool _writeEndMark = false; + + bool _needReleaseMFStream; + + void Create() + { + if (_matchFinder == null) + { + LZ.BinTree bt = new LZ.BinTree(); + int numHashBytes = 4; + if (_matchFinderType == EMatchFinderType.BT2) + numHashBytes = 2; + bt.SetType(numHashBytes); + _matchFinder = bt; + } + _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return; + _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + } + + public Encoder() + { + for (int i = 0; i < kNumOpts; i++) + _optimum[i] = new Optimal(); + for (int i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); + } + + void SetWriteEndMarkerMode(bool writeEndMarker) + { + _writeEndMark = writeEndMarker; + } + + void Init() + { + BaseInit(); + _rangeEncoder.Init(); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= _posStateMask; j++) + { + uint complexState = (i << Base.kNumPosStatesBitsMax) + j; + _isMatch[complexState].Init(); + _isRep0Long[complexState].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + _literalEncoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + _posEncoders[i].Init(); + + _lenEncoder.Init((UInt32)1 << _posStateBits); + _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + } + + void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) + { + lenRes = 0; + numDistancePairs = _matchFinder.GetMatches(_matchDistances); + if (numDistancePairs > 0) + { + lenRes = _matchDistances[numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + } + + + void MovePos(UInt32 num) + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + UInt32 GetRepLen1Price(Base.State state, UInt32 posState) + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); + } + + UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) + { + UInt32 price; + if (repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) + { + UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) + { + UInt32 price; + UInt32 lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + UInt32 Backward(out UInt32 backRes, UInt32 cur) + { + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + UInt32[] reps = new UInt32[Base.kNumRepDistances]; + UInt32[] repLens = new UInt32[Base.kNumRepDistances]; + + + UInt32 GetOptimum(UInt32 position, out UInt32 backRes) + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + ReadMatchDistances(out lenMain, out numDistancePairs); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = 0xFFFFFFFF; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + UInt32 repMaxIndex = 0; + UInt32 i; + for (i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + UInt32 lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + Byte currentByte = _matchFinder.GetIndexByte(0 - 1); + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)0xFFFFFFFF; + return 1; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if (matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for (i = 0; i < Base.kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while (--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (; ; len++) + { + UInt32 distance = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(out backRes, cur); + UInt32 newLen; + ReadMatchDistances(out newLen, out numDistancePairs); + if (newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(out backRes, cur); + } + position++; + UInt32 posPrev = _optimum[cur].PosPrev; + Base.State state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state.UpdateRep(); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + UInt32 curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); + + posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!state.IsCharState(), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + { + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + + for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + UInt32 lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, + _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = lenTest + 1 + lenTest2; + while(lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (UInt32 lenTest = startLen; ; lenTest++) + { + UInt32 curBack = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). + GetPrice(true, + _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + UInt32 offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + bool ChangePair(UInt32 smallDist, UInt32 bigDist) + { + const int kDif = 7; + return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); + } + + void WriteEndMarker(UInt32 posState) + { + if (!_writeEndMark) + return; + + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + UInt32 posReduced = (((UInt32)1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + void Flush(UInt32 nowPos) + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) + { + inSize = 0; + outSize = 0; + finished = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + if (_trainSize > 0) + _matchFinder.Skip(_trainSize); + } + + if (_finished) + return; + _finished = true; + + + Int64 progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + UInt32 len, numDistancePairs; // it's not used + ReadMatchDistances(out len, out numDistancePairs); + UInt32 posState = (UInt32)(nowPos64) & _posStateMask; + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + while (true) + { + UInt32 pos; + UInt32 len = GetOptimum((UInt32)nowPos64, out pos); + + UInt32 posState = ((UInt32)nowPos64) & _posStateMask; + UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[complexState].Encode(_rangeEncoder, 0); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); + if (!_state.IsCharState()) + { + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state.UpdateChar(); + } + else + { + _isMatch[complexState].Encode(_rangeEncoder, 1); + if (pos < Base.kNumRepDistances) + { + _isRep[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 0) + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 0); + if (len == 1) + _isRep0Long[complexState].Encode(_rangeEncoder, 0); + else + _isRep0Long[complexState].Encode(_rangeEncoder, 1); + } + else + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); + } + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state.UpdateRep(); + } + UInt32 distance = _repDistances[pos]; + if (pos != 0) + { + for (UInt32 i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + UInt32 distance = pos; + for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize = nowPos64; + outSize = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished = false; + return; + } + } + } + } + + void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } + void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); + + nowPos64 = 0; + } + + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream, inSize, outSize); + while (true) + { + Int64 processedInSize; + Int64 processedOutSize; + bool finished; + CodeOneBlock(out processedInSize, out processedOutSize, out finished); + if (finished) + return; + if (progress != null) + { + progress.SetProgress(processedInSize, processedOutSize); + } + } + } + finally + { + ReleaseStreams(); + } + } + + const int kPropSize = 5; + Byte[] properties = new Byte[kPropSize]; + + public void WriteCoderProperties(System.IO.Stream outStream) + { + properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (Byte)(_dictionarySize >> (8 * i)); + outStream.Write(properties, 0, kPropSize); + } + + UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; + UInt32 _matchPriceCount; + + void FillDistancesPrices() + { + for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + UInt32 st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); + + UInt32 st2 = lenToPosState * Base.kNumFullDistances; + UInt32 i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + void FillAlignPrices() + { + for (UInt32 i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + static string[] kMatchFinderIDs = + { + "BT2", + "BT4", + }; + + static int FindMatchFinder(string s) + { + for (int m = 0; m < kMatchFinderIDs.Length; m++) + if (s == kMatchFinderIDs[m]) + return m; + return -1; + } + + public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) + { + for (UInt32 i = 0; i < properties.Length; i++) + { + object prop = properties[i]; + switch (propIDs[i]) + { + case CoderPropID.NumFastBytes: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 numFastBytes = (Int32)prop; + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + throw new InvalidParamException(); + _numFastBytes = (UInt32)numFastBytes; + break; + } + case CoderPropID.Algorithm: + { + /* + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 maximize = (Int32)prop; + _fastMode = (maximize == 0); + _maxMode = (maximize >= 2); + */ + break; + } + case CoderPropID.MatchFinder: + { + if (!(prop is String)) + throw new InvalidParamException(); + EMatchFinderType matchFinderIndexPrev = _matchFinderType; + int m = FindMatchFinder(((string)prop).ToUpper()); + if (m < 0) + throw new InvalidParamException(); + _matchFinderType = (EMatchFinderType)m; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = 0xFFFFFFFF; + _matchFinder = null; + } + break; + } + case CoderPropID.DictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (!(prop is Int32)) + throw new InvalidParamException(); ; + Int32 dictionarySize = (Int32)prop; + if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || + dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) + throw new InvalidParamException(); + _dictionarySize = (UInt32)dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= ((UInt32)(1) << dicLogSize)) + break; + _distTableSize = (UInt32)dicLogSize * 2; + break; + } + case CoderPropID.PosStateBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _posStateBits = (int)v; + _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; + break; + } + case CoderPropID.LitPosBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _numLiteralPosStateBits = (int)v; + break; + } + case CoderPropID.LitContextBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) + throw new InvalidParamException(); ; + _numLiteralContextBits = (int)v; + break; + } + case CoderPropID.EndMarker: + { + if (!(prop is Boolean)) + throw new InvalidParamException(); + SetWriteEndMarkerMode((Boolean)prop); + break; + } + default: + throw new InvalidParamException(); + } + } + } + + uint _trainSize = 0; + public void SetTrainSize(uint trainSize) + { + _trainSize = trainSize; + } + + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoder.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoder.cs new file mode 100644 index 000000000..0ce6d5a56 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoder.cs @@ -0,0 +1,234 @@ +using System; + +namespace Tango.Transport.Compression.RangeCoder +{ + class Encoder + { + public const uint kTopValue = (1 << 24); + + System.IO.Stream Stream; + + public UInt64 Low; + public uint Range; + uint _cacheSize; + byte _cache; + + long StartPosition; + + public void SetStream(System.IO.Stream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + StartPosition = Stream.Position; + + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() + { + Stream.Flush(); + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Encode(uint start, uint size, uint total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public void ShiftLow() + { + if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) + { + byte temp = _cache; + do + { + Stream.WriteByte((byte)(temp + (Low >> 32))); + temp = 0xFF; + } + while (--_cacheSize != 0); + _cache = (byte)(((uint)Low) >> 24); + } + _cacheSize++; + Low = ((uint)Low) << 8; + } + + public void EncodeDirectBits(uint v, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((v >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + public void EncodeBit(uint size0, int numTotalBits, uint symbol) + { + uint newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public long GetProcessedSizeAdd() + { + return _cacheSize + + Stream.Position - StartPosition + 4; + // (long)Stream.GetProcessedSize(); + } + } + + class Decoder + { + public const uint kTopValue = (1 << 24); + public uint Range; + public uint Code; + // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); + public System.IO.Stream Stream; + + public void Init(System.IO.Stream stream) + { + // Stream.Init(stream); + Stream = stream; + + Code = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | (byte)Stream.ReadByte(); + } + + public void ReleaseStream() + { + // Stream.ReleaseStream(); + Stream = null; + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public void Normalize2() + { + if (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public uint GetThreshold(uint total) + { + return Code / (Range /= total); + } + + public void Decode(uint start, uint size, uint total) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + public uint DecodeDirectBits(int numTotalBits) + { + uint range = Range; + uint code = Code; + uint result = 0; + for (int i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + uint t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | (byte)Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + public uint DecodeBit(uint size0, int numTotalBits) + { + uint newBound = (Range >> numTotalBits) * size0; + uint symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBit.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBit.cs new file mode 100644 index 000000000..72b22da7a --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBit.cs @@ -0,0 +1,117 @@ +using System; + +namespace Tango.Transport.Compression.RangeCoder +{ + struct BitEncoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + const int kNumMoveReducingBits = 2; + public const int kNumBitPriceShiftBits = 6; + + uint Prob; + + public void Init() { Prob = kBitModelTotal >> 1; } + + public void UpdateModel(uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + else + Prob -= (Prob) >> kNumMoveBits; + } + + public void Encode(Encoder encoder, uint symbol) + { + // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); + // UpdateModel(symbol); + uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; + if (symbol == 0) + { + encoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + } + else + { + encoder.Low += newBound; + encoder.Range -= newBound; + Prob -= (Prob) >> kNumMoveBits; + } + if (encoder.Range < Encoder.kTopValue) + { + encoder.Range <<= 8; + encoder.ShiftLow(); + } + } + + private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; + + static BitEncoder() + { + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = (UInt32)1 << (kNumBits - i - 1); + UInt32 end = (UInt32)1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + } + + public uint GetPrice(uint symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } + public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } + } + + struct BitDecoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + + uint Prob; + + public void UpdateModel(int numMoveBits, uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } + + public void Init() { Prob = kBitModelTotal >> 1; } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; + if (rangeDecoder.Code < newBound) + { + rangeDecoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 0; + } + else + { + rangeDecoder.Range -= newBound; + rangeDecoder.Code -= newBound; + Prob -= (Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 1; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBitTree.cs b/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBitTree.cs new file mode 100644 index 000000000..de2376d02 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/Compress/RangeCoder/RangeCoderBitTree.cs @@ -0,0 +1,157 @@ +using System; + +namespace Tango.Transport.Compression.RangeCoder +{ + struct BitTreeEncoder + { + BitEncoder[] Models; + int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitEncoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public void Encode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (UInt32 i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public UInt32 GetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + price += Models[m].GetPrice(bit); + m = (m << 1) + bit; + } + return price; + } + + public UInt32 ReverseGetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, + int NumBitLevels, UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[startIndex + m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, + Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) + { + UInt32 m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[startIndex + m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + } + + struct BitTreeDecoder + { + BitDecoder[] Models; + int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitDecoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + m = (m << 1) + Models[m].Decode(rangeDecoder); + return m - ((uint)1 << NumBitLevels); + } + + public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, + RangeCoder.Decoder rangeDecoder, int NumBitLevels) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[startIndex + m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/ICoder.cs b/Software/Visual_Studio/Tango.Transport/Compression/ICoder.cs new file mode 100644 index 000000000..de7804504 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/ICoder.cs @@ -0,0 +1,145 @@ +// ICoder.h + +using System; + +namespace Tango.Transport.Compression +{ + /// + /// The exception that is thrown when an error in input stream occurs during decoding. + /// + class DataErrorException : ApplicationException + { + public DataErrorException(): base("Data Error") { } + } + + /// + /// The exception that is thrown when the value of an argument is outside the allowable range. + /// + class InvalidParamException : ApplicationException + { + public InvalidParamException(): base("Invalid Parameter") { } + } + + public interface ICodeProgress + { + /// + /// Callback progress. + /// + /// + /// input size. -1 if unknown. + /// + /// + /// output size. -1 if unknown. + /// + void SetProgress(Int64 inSize, Int64 outSize); + }; + + public interface ICoder + { + /// + /// Codes streams. + /// + /// + /// input Stream. + /// + /// + /// output Stream. + /// + /// + /// input Size. -1 if unknown. + /// + /// + /// output Size. -1 if unknown. + /// + /// + /// callback progress reference. + /// + /// + /// if input stream is not valid + /// + void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress); + }; + + /* + public interface ICoder2 + { + void Code(ISequentialInStream []inStreams, + const UInt64 []inSizes, + ISequentialOutStream []outStreams, + UInt64 []outSizes, + ICodeProgress progress); + }; + */ + + /// + /// Provides the fields that represent properties idenitifiers for compressing. + /// + public enum CoderPropID + { + /// + /// Specifies size of dictionary. + /// + DictionarySize = 0x400, + /// + /// Specifies size of memory for PPM*. + /// + UsedMemorySize, + /// + /// Specifies order for PPM methods. + /// + Order, + /// + /// Specifies number of postion state bits for LZMA (0 <= x <= 4). + /// + PosStateBits = 0x440, + /// + /// Specifies number of literal context bits for LZMA (0 <= x <= 8). + /// + LitContextBits, + /// + /// Specifies number of literal position bits for LZMA (0 <= x <= 4). + /// + LitPosBits, + /// + /// Specifies number of fast bytes for LZ*. + /// + NumFastBytes = 0x450, + /// + /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". + /// + MatchFinder, + /// + /// Specifies number of passes. + /// + NumPasses = 0x460, + /// + /// Specifies number of algorithm. + /// + Algorithm = 0x470, + /// + /// Specifies multithread mode. + /// + MultiThread = 0x480, + /// + /// Specifies mode with end marker. + /// + EndMarker = 0x490 + }; + + + public interface ISetCoderProperties + { + void SetCoderProperties(CoderPropID[] propIDs, object[] properties); + }; + + public interface IWriteCoderProperties + { + void WriteCoderProperties(System.IO.Stream outStream); + } + + public interface ISetDecoderProperties + { + void SetDecoderProperties(byte[] properties); + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Compression/SevenZipHelper.cs b/Software/Visual_Studio/Tango.Transport/Compression/SevenZipHelper.cs new file mode 100644 index 000000000..e23648aa9 --- /dev/null +++ b/Software/Visual_Studio/Tango.Transport/Compression/SevenZipHelper.cs @@ -0,0 +1,105 @@ +// 7Zip helper code by Peter Bromberg +// http://www.eggheadcafe.com/tutorials/aspnet/064b41e4-60bc-4d35-9136-368603bcc27a/7zip-lzma-inmemory-com.aspx + +using System; +using System.IO; + + +namespace Tango.Transport.Compression +{ + public static class SevenZipHelper + { + + static int dictionary = 1 << 23; + + // static Int32 posStateBits = 2; + // static Int32 litContextBits = 3; // for normal files + // UInt32 litContextBits = 0; // for 32-bit data + // static Int32 litPosBits = 0; + // UInt32 litPosBits = 2; // for 32-bit data + // static Int32 algorithm = 2; + // static Int32 numFastBytes = 128; + + static bool eos = false; + + + + + + static CoderPropID[] propIDs = + { + CoderPropID.DictionarySize, + CoderPropID.PosStateBits, + CoderPropID.LitContextBits, + CoderPropID.LitPosBits, + CoderPropID.Algorithm, + CoderPropID.NumFastBytes, + CoderPropID.MatchFinder, + CoderPropID.EndMarker + }; + + // these are the default properties, keeping it simple for now: + static object[] properties = + { + (Int32)(dictionary), + (Int32)(2), + (Int32)(3), + (Int32)(0), + (Int32)(2), + (Int32)(128), + "bt4", + eos + }; + + + public static byte[] Compress(byte[] inputBytes) + { + + MemoryStream inStream = new MemoryStream(inputBytes); + MemoryStream outStream = new MemoryStream(); + LZMA.Encoder encoder = new LZMA.Encoder(); + encoder.SetCoderProperties(propIDs, properties); + encoder.WriteCoderProperties(outStream); + long fileSize = inStream.Length; + for (int i = 0; i < 8; i++) + outStream.WriteByte((Byte)(fileSize >> (8 * i))); + encoder.Code(inStream, outStream, -1, -1, null); + return outStream.ToArray(); + } + + public static byte[] Decompress(byte[] inputBytes) + { + MemoryStream newInStream = new MemoryStream(inputBytes); + + LZMA.Decoder decoder = new LZMA.Decoder(); + + newInStream.Seek(0, 0); + MemoryStream newOutStream = new MemoryStream(); + + byte[] properties2 = new byte[5]; + if (newInStream.Read(properties2, 0, 5) != 5) + throw (new Exception("input .lzma is too short")); + long outSize = 0; + for (int i = 0; i < 8; i++) + { + int v = newInStream.ReadByte(); + if (v < 0) + throw (new Exception("Can't Read 1")); + outSize |= ((long)(byte)v) << (8 * i); + } + decoder.SetDecoderProperties(properties2); + + long compressedSize = newInStream.Length - newInStream.Position; + decoder.Code(newInStream, newOutStream, compressedSize, outSize, null); + + byte[] b = newOutStream.ToArray(); + + return b; + + + + } + + + } +} diff --git a/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj b/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj index e7e9ccca5..a49b68520 100644 --- a/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj +++ b/Software/Visual_Studio/Tango.Transport/Tango.Transport.csproj @@ -82,6 +82,22 @@ + + + + + + + + + + + + + + + + @@ -153,12 +169,13 @@ + - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs index b8aa96ea6..633d1a0ff 100644 --- a/Software/Visual_Studio/Tango.Transport/TransporterBase.cs +++ b/Software/Visual_Studio/Tango.Transport/TransporterBase.cs @@ -983,6 +983,11 @@ namespace Tango.Transport { TransportMessageBase message = _sendingQueue.BlockDequeue(); + if (this.GetType().Name.Contains("Receiver")) + { + System.Diagnostics.Debug.WriteLine("Sending Queue: " + _sendingQueue.Count); + } + try { if (Adapter.State == TransportComponentState.Connected) diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Hubs/ExternalBridgeHub.cs b/Software/Visual_Studio/Web/Tango.MachineService/Hubs/ExternalBridgeHub.cs index 564ff4831..d5ce0d145 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Hubs/ExternalBridgeHub.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Hubs/ExternalBridgeHub.cs @@ -10,10 +10,10 @@ namespace Tango.MachineService.Hubs { public class ExternalBridgeHub : Hub { - private static List _machines; + private static List _externalBridges; private static List _sessions; - public class RegisteredMachine + public class ExternalBridgeInfo { public String ConnectionID { get; set; } public MachineInfo MachineInfo { get; set; } @@ -21,36 +21,27 @@ namespace Tango.MachineService.Hubs public class MachineSession { + public String SessionID { get; set; } + public String ReceiverConnectionID { get; set; } public String ControllerConnectionID { get; set; } - public RegisteredMachine RegisteredMachine { get; set; } + public ExternalBridgeInfo ExternalBridge { get; set; } + + public MachineSession() + { + SessionID = Guid.NewGuid().ToString(); + } } static ExternalBridgeHub() { - _machines = new List(); + _externalBridges = new List(); _sessions = new List(); } - public class ExternalBridgeSession - { - public String ClientA { get; set; } - public String ClientB { get; set; } - } - - public void Test(String msg) - { - this.Clients.Caller.Test(msg); - } - - public int Calc(int a, int b) - { - return a + b; - } - public void RegisterMachine(MachineInfo machineInfo) { - _machines.RemoveAll(x => x.MachineInfo.SerialNumber == machineInfo.SerialNumber); - _machines.Add(new RegisteredMachine() + _externalBridges.RemoveAll(x => x.MachineInfo.SerialNumber == machineInfo.SerialNumber); + _externalBridges.Add(new ExternalBridgeInfo() { MachineInfo = machineInfo, ConnectionID = Context.ConnectionId, @@ -59,46 +50,78 @@ namespace Tango.MachineService.Hubs public void UnregisterMachine() { - _machines.RemoveAll(x => x.ConnectionID == Context.ConnectionId); + _externalBridges.RemoveAll(x => x.ConnectionID == Context.ConnectionId); } public List GetAvailableMachines() { - return _machines.Select(x => x.MachineInfo).ToList(); + return _externalBridges.Select(x => x.MachineInfo).ToList(); } - public void Connect(String serialNumber) + public String CreateSession(String serialNumber) { - var registeredMachine = _machines.SingleOrDefault(x => x.MachineInfo.SerialNumber == serialNumber); + var externalBridge = _externalBridges.SingleOrDefault(x => x.MachineInfo.SerialNumber == serialNumber); - if (registeredMachine != null) + if (externalBridge != null) { MachineSession session = new MachineSession(); session.ControllerConnectionID = Context.ConnectionId; - session.RegisteredMachine = registeredMachine; + session.ExternalBridge = externalBridge; _sessions.Add(session); + Clients.Client(externalBridge.ConnectionID).OnSessionCreated(session.SessionID); + return session.SessionID; } + + return null; } - public void Write(byte[] data) + //public void NotifySessionCreated() + //{ + // var session = _sessions.SingleOrDefault(x => x.ReceiverConnectionID == Context.ConnectionId); + + // if (session != null) + // { + // Clients.Client(session.ControllerConnectionID).SessionCreated(); + // } + //} + + public void JoinSession(String sessionID) { - var session = _sessions.SingleOrDefault(x => x.ControllerConnectionID == Context.ConnectionId || x.RegisteredMachine.ConnectionID == Context.ConnectionId); + var session = _sessions.SingleOrDefault(x => x.SessionID == sessionID); + + if (session != null) + { + session.ReceiverConnectionID = Context.ConnectionId; + Clients.Client(session.ControllerConnectionID).SessionCreated(); + } + } + + public void Write(List dataCollection) + { + var session = _sessions.SingleOrDefault(x => x.ReceiverConnectionID == Context.ConnectionId || x.ControllerConnectionID == Context.ConnectionId); if (session != null) { String connectionID = String.Empty; - if (session.ControllerConnectionID == Context.ConnectionId) + if (session.ReceiverConnectionID == Context.ConnectionId) { - connectionID = session.RegisteredMachine.ConnectionID; + connectionID = session.ControllerConnectionID; } else { - connectionID = session.ControllerConnectionID; + connectionID = session.ReceiverConnectionID; } - Clients.Client(connectionID).DataAvailable(data); + Clients.Client(connectionID).DataAvailable(dataCollection); } } + + public override Task OnDisconnected(bool stopCalled) + { + _externalBridges.RemoveAll(x => x.ConnectionID == Context.ConnectionId); + _sessions.RemoveAll(x => x.ControllerConnectionID == Context.ConnectionId || x.ReceiverConnectionID == Context.ConnectionId); + return base.OnDisconnected(stopCalled); + } } } \ No newline at end of file -- cgit v1.3.1 From 8d1933f305e8fb4aa4cc7633fa02c419d77766ff Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 15 Jan 2020 21:13:45 +0200 Subject: External bridge improvements. --- .../ViewModels/MachineTechViewVM.cs | 2 +- .../Images/external-bridge-signalr.png | Bin 0 -> 3238 bytes .../Tango.MachineStudio.UI.csproj | 3 +- .../Views/ConnectedMachineView.xaml | 48 +++++++++++++++ .../Views/MachineConnectionView.xaml | 4 +- .../ViewModels/ExternalBridgeViewVM.cs | 8 +-- .../PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml | 4 +- .../PPC/Tango.PPC.UI/Views/MainView.xaml | 2 +- .../ExternalBridge/ExternalBridgeReceiver.cs | 2 +- .../ExternalBridge/ExternalBridgeScanner.cs | 21 +++++-- .../ExternalBridge/ExternalBridgeService.cs | 38 ++++++++---- .../ExternalBridge/ExternalBridgeSignalRClient.cs | 6 +- .../ExternalBridge/ExternalBridgeTcpClient.cs | 11 +++- .../ExternalBridge/IExternalBridgeService.cs | 30 +++++----- .../Adapters/SignalRTransportAdapter.cs | 39 ++++++++++--- .../Tango.MachineService/Hubs/ExternalBridgeHub.cs | 65 +++++++++++++++------ 16 files changed, 212 insertions(+), 71 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-signalr.png (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs index 7cb680527..139d85493 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs @@ -459,7 +459,7 @@ namespace Tango.MachineStudio.Technician.ViewModels /// The data. private void PopulateDiagnosticsData(StartDiagnosticsResponse data) { - if (data.Monitors == null) return; + if (data.Monitors == null || _machineOperator == null || _machineOperator.DeviceInformation == null) return; _diagnostics_index++; uint interval = _machineOperator.DeviceInformation.DiagnosticsInterval; diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-signalr.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-signalr.png new file mode 100644 index 000000000..dc9b06e72 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-signalr.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 1762205ad..565489f0b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -363,6 +363,7 @@ TCC\template.bmp Always + @@ -675,7 +676,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectedMachineView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectedMachineView.xaml index e69ac516e..a5283f346 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectedMachineView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ConnectedMachineView.xaml @@ -32,6 +32,10 @@ + + + + @@ -65,6 +69,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml index 0ef498420..58ff03107 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml @@ -58,13 +58,13 @@ - + S/N: - IP Address: + Hub: Organization: diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/ExternalBridgeViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/ExternalBridgeViewVM.cs index f1127ebfe..66b982ffe 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/ExternalBridgeViewVM.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/ExternalBridgeViewVM.cs @@ -79,7 +79,7 @@ namespace Tango.PPC.UI.ViewModels LogManager.Log("Disconnecting current external bridge session."); _disconnecting = true; InvalidateRelayCommands(); - ExternalBridgeService.DisconnectSession(); + ExternalBridgeService.DisconnectFullControlSession(); } #endregion @@ -103,7 +103,7 @@ namespace Tango.PPC.UI.ViewModels public override void OnApplicationStarted() { ExternalBridgeService.ConnectionRequest += ExternalBridgeService_ConnectionRequest; - ExternalBridgeService.ClientDisconnected += ExternalBridgeService_ClientDisconnected; + ExternalBridgeService.FullControlSessionDisconnected += ExternalBridgeService_FullControlSessionDisconnected; } #endregion @@ -111,11 +111,11 @@ namespace Tango.PPC.UI.ViewModels #region Event Handlers /// - /// Handles the event. + /// Handles the event. /// /// The sender. /// The instance containing the event data. - private void ExternalBridgeService_ClientDisconnected(object sender, EventArgs e) + private void ExternalBridgeService_FullControlSessionDisconnected(object sender, EventArgs e) { if (IsVisible) { diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml index 4de00120f..377d1b531 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/ExternalBridgeView.xaml @@ -23,7 +23,7 @@ + + + + + + + + + + + + Environment selection requires restarting the application + Remember me + + + + + Logging you in... + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 020343ba0..48f7b46d3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -55,7 +55,7 @@ IsChecked="{Binding Source={x:Reference MenuToggleButton}, Path=IsChecked, Mode=TwoWay}" /> - + diff --git a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs index 263574f68..3d330b797 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesContextExtension.cs @@ -5,6 +5,7 @@ using System.Collections.ObjectModel; using System.Data.Entity; using System.Data.Entity.Core.Objects; using System.Data.Entity.Infrastructure; +using System.Data.SqlClient; using System.Data.SQLite; using System.IO; using System.Linq; @@ -25,18 +26,27 @@ namespace Tango.BL private ObservablesContextAdapter _adapter; private static DataSource _override_datasource; private DataSource _dataSource; + private static List _open_contexts; /// /// Gets a value indicating whether this instance is disposed. /// public bool IsDisposed { get; private set; } + /// + /// Initializes the class. + /// + static ObservablesContext() + { + _open_contexts = new List(); + } + /// /// Initializes a new instance of the class. /// public ObservablesContext() { - + _open_contexts.Add(this); } /// @@ -46,6 +56,7 @@ namespace Tango.BL /// if set to true will try to connect to an .mdf file. public ObservablesContext(DataSource dataSource) : base(dataSource.ToConnection(), true) { + _open_contexts.Add(this); _dataSource = dataSource; Database.SetInitializer(null); Configuration.LazyLoadingEnabled = false; @@ -286,6 +297,7 @@ namespace Tango.BL /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { + _open_contexts.Remove(this); base.Dispose(disposing); IsDisposed = true; } @@ -296,6 +308,16 @@ namespace Tango.BL { _override_datasource.AccessToken = accessToken; _override_datasource.AccessTokenExpiration = expiration; + + foreach (var context in _open_contexts.Where(x => x._dataSource.Type == DataSourceType.AccessToken)) + { + context._dataSource = _override_datasource; + var connection = context.Database.Connection as SqlConnection; + if (connection != null) + { + connection.AccessToken = context._dataSource.AccessToken; + } + } } } } diff --git a/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs b/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs index ce83d387c..8bc84f7b5 100644 --- a/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs +++ b/Software/Visual_Studio/Tango.Web/SQLServer/SQLServerManager.cs @@ -15,6 +15,7 @@ namespace Tango.Web.SQLServer public AuthenticationResult GetAccessToken() { var authContext = new AuthenticationContext(_service_root); + authContext.TokenCache.Clear(); ClientCredential clientCredentials = new ClientCredential(WebConfig.CLIENT_ID, WebConfig.APP_SECRET); AuthenticationResult authResult = authContext.AcquireTokenAsync("https://database.windows.net/", clientCredentials).Result; return authResult; diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs index da5ce16f7..0fd116361 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs @@ -286,20 +286,9 @@ namespace Tango.MachineService.Controllers public LoginResponse Login(LoginRequest request) { AuthenticationResult authResult = null; - - try - { - authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); - } - catch (Exception ex) - { - throw new AuthenticationException(ex.FlattenMessage()); - } - - if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email)) - { - throw new AuthenticationException($"You do not have permissions to access the {MachineServiceConfig.DEPLOYMENT_SLOT.ToDescription()} environment."); - } + User user = null; + DataSource dataSource = null; + IHashGenerator hash = new BasicHashGenerator(); Version client_version; @@ -310,84 +299,122 @@ namespace Tango.MachineService.Controllers bool versionChangeRequired = false; String requiredVersion = null; + bool isPasswordOK = false; - User user = null; - - using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + try { - db.Roles.ToList(); - db.Permissions.ToList(); - db.UsersRoles.ToList(); - db.RolesPermissions.ToList(); + authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); + isPasswordOK = true; + } + catch {} - user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower()).WithRolesAndPermissions().WithDeleted().Build(); + //Login via Active Directory + if (request.Method == LoginMethod.ActiveDirectory) + { + try + { + authResult = _ad_manager.ValidateUserCredentials(request.Email, request.Password); + } + catch (Exception ex) + { + throw new AuthenticationException(ex.FlattenMessage()); + } - IHashGenerator g = new BasicHashGenerator(); + if (!_ad_manager.CanUserAccessCurrentEnvironment(request.Email)) + { + throw new AuthenticationException($"You do not have permissions to access the {MachineServiceConfig.DEPLOYMENT_SLOT.ToDescription()} environment."); + } - if (user == null) + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) { - //Than add the user !! - User new_user = new User(); - new_user.Email = request.Email; - new_user.Password = g.Encrypt(request.Password); - new_user.Organization = db.Organizations.Include(x => x.Address).Single(x => x.Name == "Twine"); - new_user.Address = new_user.Organization.Address.Clone(); - new_user.Contact = new Contact() - { - FirstName = authResult.UserInfo.GivenName, - LastName = authResult.UserInfo.FamilyName, - FullName = authResult.UserInfo.GivenName + " " + authResult.UserInfo.FamilyName, - Email = request.Email, - }; + db.Roles.ToList(); + db.Permissions.ToList(); + db.UsersRoles.ToList(); + db.RolesPermissions.ToList(); - db.UsersRoles.Add(new UsersRole() - { - User = new_user, - Role = db.Roles.Single(x => (Roles)x.Code == Roles.User), - }); + user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower()).WithRolesAndPermissions().WithDeleted().Build(); - db.UsersRoles.Add(new UsersRole() + if (user == null) { - User = new_user, - Role = db.Roles.Single(x => (Roles)x.Code == Roles.MachineStudioUser), - }); + user = new User(); + user.Email = request.Email; + user.Password = hash.Encrypt(request.Password); + user.Organization = db.Organizations.Include(x => x.Address).Single(x => x.Name == "Twine"); + user.Address = user.Organization.Address.Clone(); + user.Contact = new Contact() + { + FirstName = authResult.UserInfo.GivenName, + LastName = authResult.UserInfo.FamilyName, + FullName = authResult.UserInfo.GivenName + " " + authResult.UserInfo.FamilyName, + Email = request.Email, + }; - new_user.LastLogin = DateTime.UtcNow; - db.Users.Add(new_user); - } - else - { - if (user.Deleted) + db.UsersRoles.Add(new UsersRole() + { + User = user, + Role = db.Roles.Single(x => (Roles)x.Code == Roles.User), + }); + + db.UsersRoles.Add(new UsersRole() + { + User = user, + Role = db.Roles.Single(x => (Roles)x.Code == Roles.MachineStudioUser), + }); + + user.Password = hash.Encrypt(request.Password); + + db.Users.Add(user); + } + else { - throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); + if (user.Deleted) + { + throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); + } } user.LastLogin = DateTime.UtcNow; - user.Password = g.Encrypt(request.Password); + + db.SaveChanges(); } - db.SaveChanges(); + dataSource = new DataSource() + { + Address = MachineServiceConfig.DB_ADDRESS, + Catalog = MachineServiceConfig.DB_CATALOG, + Type = Core.DataSourceType.Azure, + IntegratedSecurity = false, + UserName = request.Email, + Password = request.Password, + }; + } + //Login via Database standard user + else + { + var password = hash.Encrypt(request.Password); - if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION) + using (var db = ObservablesContextHelper.CreateContext()) { - var latest_version = db.MachineStudioVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + user = new UserBuilder(db).Set(x => x.Email.ToLower() == request.Email.ToLower() && (isPasswordOK || x.Password == password)).WithRolesAndPermissions().WithDeleted().Build(); - if (latest_version != null && Version.Parse(latest_version.Version) != client_version) + if (user == null) { - versionChangeRequired = true; - requiredVersion = latest_version.Version; + throw new AuthenticationException("Invalid email or password."); } - } - } - Core.DataSource dataSource = null; + if (user.Deleted) + { + throw new AuthenticationException("Your account has been disabled. Please contact your administrator."); + } + + user.LastLogin = DateTime.UtcNow; + db.SaveChanges(); + } - if (MachineServiceConfig.USE_DB_ACCESS_TOKENS) - { SQLServerManager sqlServer = new SQLServerManager(); var accessToken = sqlServer.GetAccessToken(); - dataSource = new Core.DataSource() + dataSource = new DataSource() { Address = MachineServiceConfig.DB_ADDRESS, Catalog = MachineServiceConfig.DB_CATALOG, @@ -397,19 +424,23 @@ namespace Tango.MachineService.Controllers AccessTokenExpiration = accessToken.ExpiresOn.UtcDateTime }; } - else + + //Enforce Machine Studio Version ? + if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION) { - dataSource = new Core.DataSource() + using (var db = ObservablesContextHelper.CreateContext()) { - Address = MachineServiceConfig.DB_ADDRESS, - Catalog = MachineServiceConfig.DB_CATALOG, - Type = Core.DataSourceType.Azure, - IntegratedSecurity = false, - UserName = request.Email, - Password = request.Password, - }; + var latest_version = db.MachineStudioVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); + + if (latest_version != null && Version.Parse(latest_version.Version) != client_version) + { + versionChangeRequired = true; + requiredVersion = latest_version.Version; + } + } } + //Return data source return new LoginResponse() { DataSource = dataSource, -- cgit v1.3.1 From 09d432566f696f0eeb3fce97d2c870cfd1c91f89 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 19 Jan 2020 12:05:37 +0200 Subject: Improved ms logging screen. Improved ObservableStaticCollection init speed. --- .../Views/MachineJobSelectionView.xaml | 2 +- .../Authentication/IAuthenticationProvider.cs | 2 +- .../DefaultAuthenticationProvider.cs | 12 +++++- .../Tango.MachineStudio.UI.csproj | 2 +- .../ViewModels/LoginViewVM.cs | 14 +++++-- .../Tango.MachineStudio.UI/Views/LoginView.xaml | 7 +++- .../Tango.BL/ObservablesStaticCollections.cs | 44 +++++++++++++++++----- 7 files changed, 63 insertions(+), 20 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml index f8a10e7c4..bf626f462 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml @@ -64,7 +64,7 @@ - + MACHINE JOBS diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs index cb231fa05..2929ea405 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs @@ -29,7 +29,7 @@ namespace Tango.MachineStudio.Common.Authentication /// The email. /// The password. /// - AuthenticationLoginResult Login(String email, String password, LoginMethod method, bool bypassVersionCheck = false); + AuthenticationLoginResult Login(String email, String password, LoginMethod method, bool bypassVersionCheck = false, Action logAction = null); /// /// Logs-out the current logged-in user. diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs index 209b26505..0131cd209 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs @@ -90,7 +90,7 @@ namespace Tango.MachineStudio.UI.Authentication /// The password. /// /// Login failed for user " + email - public AuthenticationLoginResult Login(string email, string password, LoginMethod method, bool bypassVersionCheck = false) + public AuthenticationLoginResult Login(string email, string password, LoginMethod method, bool bypassVersionCheck = false, Action logAction = null) { _refreshTokenTimer.Stop(); @@ -112,6 +112,8 @@ namespace Tango.MachineStudio.UI.Authentication try { + logAction?.Invoke("Logging in to machine service..."); + response = _client.Login(new LoginRequest() { @@ -147,7 +149,10 @@ namespace Tango.MachineStudio.UI.Authentication try { - ObservablesStaticCollections.Instance.Initialize(); + ObservablesStaticCollections.Instance.Initialize((x) => + { + logAction.Invoke(x); + }); } catch (Exception ex) { @@ -156,6 +161,7 @@ namespace Tango.MachineStudio.UI.Authentication using (ObservablesContext db = ObservablesContext.CreateDefault()) { + logAction.Invoke("Loading user permissions..."); User user = new UserBuilder(db).Set(x => x.Email.ToLower() == email.ToLower()).WithRolesAndPermissions().WithOrganization().Build(); if (user == null) @@ -167,6 +173,8 @@ namespace Tango.MachineStudio.UI.Authentication _refreshTokenTimer.Start(); + logAction.Invoke("Starting application..."); + return new AuthenticationLoginResult() { User = user, diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index efe8fc6b1..13f22dfda 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -679,7 +679,7 @@ if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)Roslyn\" - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs index 9c2367f93..dce469dbd 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs @@ -116,7 +116,12 @@ namespace Tango.MachineStudio.UI.ViewModels set { _isStandardUser = value; RaisePropertyChangedAuto(); if (value) IsActiveDirectory = false; } } - + private String _progressLog; + public String ProgressLog + { + get { return _progressLog; } + set { _progressLog = value; RaisePropertyChangedAuto(); } + } /// /// Gets or sets the login command. @@ -146,7 +151,7 @@ namespace Tango.MachineStudio.UI.ViewModels Email = _settings.LastLoginEmail; DeploymentSlot = _settings.DeploymentSlot; RememberMe = _settings.RememberMe; - + if (_settings.LastLoginMethod == LoginMethod.ActiveDirectory) { IsActiveDirectory = true; @@ -184,7 +189,10 @@ namespace Tango.MachineStudio.UI.ViewModels { _settings.DeploymentSlot = DeploymentSlot; - LoginResponse result = _authenticationProvider.Login(Email, Password, loginMethod, _settings.ByPassEnvironmentVersionCheck).Response; + LoginResponse result = _authenticationProvider.Login(Email, Password, loginMethod, _settings.ByPassEnvironmentVersionCheck, (progress) => + { + ProgressLog = progress; + }).Response; if (result.VersionChangeRequired && !_settings.ByPassEnvironmentVersionCheck) { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index e7428dd28..ff13ec2c7 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -91,8 +91,11 @@ - - Logging you in... + + + + + diff --git a/Software/Visual_Studio/Tango.BL/ObservablesStaticCollections.cs b/Software/Visual_Studio/Tango.BL/ObservablesStaticCollections.cs index 5d1c3e148..1b45e959d 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesStaticCollections.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesStaticCollections.cs @@ -52,55 +52,79 @@ namespace Tango.BL /// /// Initializes this instance. /// - public void Initialize() + public void Initialize(Action progressLog = null) { if (!_initialized) { + progressLog.Invoke("Loading static collections..."); db = ObservablesContext.CreateDefault(); WindingMethods = db.WindingMethods.ToObservableCollection(); + progressLog.Invoke("Loading color spaces..."); ColorSpaces = db.ColorSpaces.ToObservableCollection(); + + progressLog.Invoke("Loading spools..."); SpoolTypes = db.SpoolTypes.ToObservableCollection(); + progressLog.Invoke("Loading event..."); EventTypes = db.EventTypes.ToObservableCollection(); + progressLog.Invoke("Loading blowers..."); HardwareBlowerTypes = db.HardwareBlowerTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwareBlowers = db.HardwareBlowers.ToObservableCollection(); + //HardwareBlowers = db.HardwareBlowers.ToObservableCollection(); + progressLog.Invoke("Loading break sensors..."); HardwareBreakSensorTypes = db.HardwareBreakSensorTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwareBreakSensors = db.HardwareBreakSensors.ToObservableCollection(); + //HardwareBreakSensors = db.HardwareBreakSensors.ToObservableCollection(); + progressLog.Invoke("Loading dancers..."); HardwareDancerTypes = db.HardwareDancerTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwareDancers = db.HardwareDancers.ToObservableCollection(); + //HardwareDancers = db.HardwareDancers.ToObservableCollection(); + progressLog.Invoke("Loading motors..."); HardwareMotorTypes = db.HardwareMotorTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwareMotors = db.HardwareMotors.ToObservableCollection(); + //HardwareMotors = db.HardwareMotors.ToObservableCollection(); + progressLog.Invoke("Loading pid controls..."); HardwarePidControlTypes = db.HardwarePidControlTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwarePidControls = db.HardwarePidControls.ToObservableCollection(); + //HardwarePidControls = db.HardwarePidControls.ToObservableCollection(); + progressLog.Invoke("Loading speed sensors..."); HardwareSpeedSensorTypes = db.HardwareSpeedSensorTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwareSpeedSensors = db.HardwareSpeedSensors.ToObservableCollection(); + //HardwareSpeedSensors = db.HardwareSpeedSensors.ToObservableCollection(); + progressLog.Invoke("Loading winders..."); HardwareWinderTypes = db.HardwareWinderTypes.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); - HardwareWinders = db.HardwareWinders.ToObservableCollection(); + //HardwareWinders = db.HardwareWinders.ToObservableCollection(); + progressLog.Invoke("Loading tech controllers..."); TechControllers = db.TechControllers.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); + + progressLog.Invoke("Loading tech dispensers..."); TechDispensers = db.TechDispensers.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); + + progressLog.Invoke("Loading tech io's..."); TechIos = db.TechIos.ToObservableCollection(); + + progressLog.Invoke("Loading tech monitors..."); TechMonitors = db.TechMonitors.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); + + progressLog.Invoke("Loading tech valves..."); TechValves = db.TechValves.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); + + progressLog.Invoke("Loading tech heaters..."); TechHeaters = db.TechHeaters.ToList().OrderByAlphaNumeric(x => x.Description).ToObservableCollection(); + progressLog.Invoke("Loading machines..."); Machines = db.Machines.Include(x => x.Organization).ToObservableCollection(); + progressLog.Invoke("Loading users..."); Users = db.Users.Where(x => !x.Deleted).Include(x => x.Contact).ToObservableCollection(); + progressLog.Invoke("Loading machine versions..."); MachineVersions = db.MachineVersions.ToObservableCollection(); - - //Load later... Task.Factory.StartNew(() => { -- cgit v1.3.1 From 7ffd0bab3c6f397936f8ef9f6829cdf33b850efa Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Sun, 19 Jan 2020 16:10:55 +0200 Subject: Implemented new ms user creation + PASSWORD_CHANGE_REQUIRED. Improved ms login design + password change. Improved ms main menu and current user design. --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes .../DB/SQLExaminer Projects/LOCAL TO DEV.seproj | 68 +++++++++ Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../Views/MachineCreationDialog.xaml | 2 +- .../Images/login.png | Bin 0 -> 6401 bytes .../Tango.MachineStudio.UsersAndRoles.csproj | 21 ++- .../ViewModels/MainViewVM.cs | 31 ++-- .../ViewModels/UserCreationDialogVM.cs | 74 ++++++++++ .../Views/UserCreationDialog.xaml | 53 +++++++ .../Views/UserCreationDialog.xaml.cs | 28 ++++ .../Views/UserManagementView.xaml | 2 +- .../Views/UserView.xaml | 2 - .../packages.config | 1 + .../Web/LoginResponse.cs | 1 + .../DefaultAuthenticationProvider.cs | 8 ++ .../Tango.MachineStudio.UI/Images/login_white.png | Bin 0 -> 3308 bytes .../Tango.MachineStudio.UI.csproj | 1 + .../ViewModels/LoginViewVM.cs | 135 +++++++++++++++++- .../Tango.MachineStudio.UI/Views/LoginView.xaml | 45 +++++- .../Tango.MachineStudio.UI/Views/MainView.xaml | 75 +++++----- .../Visual_Studio/Tango.BL/DTO/JobRunDTOBase.cs | 8 +- Software/Visual_Studio/Tango.BL/DTO/UserDTOBase.cs | 8 ++ .../Visual_Studio/Tango.BL/Entities/JobRunBase.cs | 52 +++---- Software/Visual_Studio/Tango.BL/Entities/User.cs | 39 ------ .../Visual_Studio/Tango.BL/Entities/UserBase.cs | 38 +++++ .../Visual_Studio/Tango.DAL.Remote/DB/JOB_RUNS.cs | 2 +- .../Tango.DAL.Remote/DB/RemoteADO.edmx | 9 +- .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 156 ++++++++++----------- Software/Visual_Studio/Tango.DAL.Remote/DB/USER.cs | 1 + .../Controllers/MachineStudioController.cs | 3 +- 32 files changed, 649 insertions(+), 214 deletions(-) create mode 100644 Software/DB/SQLExaminer Projects/LOCAL TO DEV.seproj create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Images/login.png create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/UserCreationDialogVM.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml.cs create mode 100644 Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index d11f45fb6..b662518b9 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 34e1b9a60..2c32260dc 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/SQLExaminer Projects/LOCAL TO DEV.seproj b/Software/DB/SQLExaminer Projects/LOCAL TO DEV.seproj new file mode 100644 index 000000000..ba509261c --- /dev/null +++ b/Software/DB/SQLExaminer Projects/LOCAL TO DEV.seproj @@ -0,0 +1,68 @@ + + + + MsSqlServer + LiveDb + localhost\sqlexpress + Tango + True + + + MsSqlAzure + LiveDb + twine.database.windows.net + Tango_DEV + False + SqlServer + Roy + Aa123456 + true + + + + + + + + false + false + false + false + false + false + false + false + true + false + false + false + true + true + true + true + false + true + false + false + false + false + true + false + false + false + false + false + false + false + true + false + false + true + + + + + + + + \ No newline at end of file diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index fbfed2eae..966874e5f 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 6099b8a73..5b42f3fba 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineCreationDialog.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineCreationDialog.xaml index e3ba1bff4..2d380c0d2 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineCreationDialog.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.MachineDesigner/Views/MachineCreationDialog.xaml @@ -8,7 +8,7 @@ xmlns:vm="clr-namespace:Tango.MachineStudio.MachineDesigner.ViewModels" xmlns:local="clr-namespace:Tango.MachineStudio.MachineDesigner.Views" mc:Ignorable="d" - d:DesignHeight="400" d:DesignWidth="700" Height="400" Width="700" Background="White" d:DataContext="{d:DesignInstance Type=vm:MachineCreationDialogVM, IsDesignTimeCreatable=False}"> + d:DesignHeight="400" d:DesignWidth="700" Height="400" Width="700" Background="{StaticResource WhiteBackgroundBrush}" d:DataContext="{d:DesignInstance Type=vm:MachineCreationDialogVM, IsDesignTimeCreatable=False}"> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Images/login.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Images/login.png new file mode 100644 index 000000000..9f7d0b9ba Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Images/login.png differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj index 82376b751..035cb2b9d 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj @@ -49,6 +49,9 @@ ..\..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\..\packages\SimpleValidator.0.6.1.0\lib\net40\SimpleValidator.dll + @@ -80,6 +83,7 @@ + AddressView.xaml @@ -95,6 +99,9 @@ OrganizationSelectionView.xaml + + UserCreationDialog.xaml + UserManagementView.xaml @@ -120,7 +127,9 @@ ResXFileCodeGenerator Resources.Designer.cs - + + Designer + SettingsSingleFileGenerator @@ -186,6 +195,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -210,11 +223,13 @@ - + + + - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/MainViewVM.cs index 2f4e5c9a3..81ef04dd4 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/MainViewVM.cs @@ -370,20 +370,19 @@ namespace Tango.MachineStudio.UsersAndRoles.ViewModels } } - private async void AddNewUser() + private void AddNewUser() { - String email = _notification.ShowTextInput("Enter user email", "email"); - - if (!String.IsNullOrWhiteSpace(email)) + _notification.ShowModalDialog(async (vm) => { User user = new User(); - user.Email = email; - user.Password = "1111"; + user.Email = vm.Email; + user.Password = User.GetPasswordHash(vm.Password); + user.PasswordChangeRequired = true; user.Contact = new Contact() { - FirstName = "Twine", - LastName = "User", - Email = email, + FirstName = vm.FirstName, + LastName = vm.LastName, + Email = vm.Email, }; user.Address = new Address(); @@ -394,6 +393,18 @@ namespace Tango.MachineStudio.UsersAndRoles.ViewModels Role = _manageContext.Roles.SingleOrDefault(x => x.Code == (int)BL.Enumerations.Roles.User) }); + user.UsersRoles.Add(new UsersRole() + { + User = user, + Role = _manageContext.Roles.SingleOrDefault(x => x.Code == (int)BL.Enumerations.Roles.MachineStudioUser) + }); + + user.UsersRoles.Add(new UsersRole() + { + User = user, + Role = _manageContext.Roles.SingleOrDefault(x => x.Code == (int)BL.Enumerations.Roles.PPCUser) + }); + try { user.Validate(_manageContext); @@ -413,7 +424,7 @@ namespace Tango.MachineStudio.UsersAndRoles.ViewModels await LoadOrganizations(); SelectedOrganization = Organizations.SingleOrDefault(x => x.Guid == ManagedOrganization.Guid); } - } + }); } private void SetUserPlace(Place place) diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/UserCreationDialogVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/UserCreationDialogVM.cs new file mode 100644 index 000000000..08762ac96 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/ViewModels/UserCreationDialogVM.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SimpleValidator.Extensions; +using Tango.SharedUI; + +namespace Tango.MachineStudio.UsersAndRoles.ViewModels +{ + public class UserCreationDialogVM : DialogViewVM + { + private static Random rnd = new Random(); + + private String _email; + [Required(ErrorMessage = "Email is required")] + [EmailAddress(ErrorMessage = "Please provide a valid email")] + public String Email + { + get { return _email; } + set { _email = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _password; + public String Password + { + get { return _password; } + set { _password = value; RaisePropertyChangedAuto(); } + } + + private String _firstName; + [Required(ErrorMessage = "First name is required")] + public String FirstName + { + get { return _firstName; } + set { _firstName = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _lastName; + [Required(ErrorMessage = "Last name is required")] + public String LastName + { + get { return _lastName; } + set { _lastName = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + protected override void Accept() + { + if (Validate()) + { + base.Accept(); + } + } + + public override void OnShow() + { + base.OnShow(); + Password = GetRandomPassword(4); + } + + private String GetRandomPassword(int count) + { + String pass = String.Empty; + + for (int i = 0; i < count; i++) + { + pass += rnd.Next(0, 9).ToString(); + } + + return pass; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml new file mode 100644 index 000000000..7433d3768 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml @@ -0,0 +1,53 @@ + + + + + + + + + + NEW USER + + + + + + + + + + + + + + EMAIL + + FIRST NAME + + LAST NAME + + + + + Provide this password to the user + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml.cs new file mode 100644 index 000000000..cfa389ed1 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserCreationDialog.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.UsersAndRoles.Views +{ + /// + /// Interaction logic for UserCreationDialog.xaml + /// + public partial class UserCreationDialog : UserControl + { + public UserCreationDialog() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml index 5246ae09c..3964abfc8 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml @@ -50,7 +50,7 @@ LOGIN - + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserView.xaml index 0858d7e08..37f649a7a 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserView.xaml @@ -16,8 +16,6 @@ - - diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/packages.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/packages.config index fe4f26e87..8696cb880 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/packages.config +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/packages.config @@ -7,4 +7,5 @@ + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs index 4ae22fa93..3515c32d1 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs @@ -14,5 +14,6 @@ namespace Tango.MachineStudio.Common.Web public DataSource DataSource { get; set; } public bool VersionChangeRequired { get; set; } public String RequiredVersion { get; set; } + public bool PasswordChangeRequired { get; set; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs index 0131cd209..26938b203 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs @@ -147,6 +147,14 @@ namespace Tango.MachineStudio.UI.Authentication }; } + if (response.PasswordChangeRequired) + { + return new AuthenticationLoginResult() + { + Response = response + }; + } + try { ObservablesStaticCollections.Instance.Initialize((x) => diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png new file mode 100644 index 000000000..10a054147 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/login_white.png differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index 13f22dfda..0525c2351 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -363,6 +363,7 @@ TCC\template.bmp Always + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs index dce469dbd..c00caf72a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs @@ -22,6 +22,9 @@ using Tango.MachineStudio.UI.Messages; using Tango.Settings; using Tango.SharedUI; using Tango.Web; +using SimpleValidator.Extensions; +using Tango.BL.Entities; +using System.Data.Entity; namespace Tango.MachineStudio.UI.ViewModels { @@ -38,6 +41,7 @@ namespace Tango.MachineStudio.UI.ViewModels private Rfc2898Cryptographer cryptographer; private MachineStudioSettings _settings; private MachineStudioWebClient _machineStudioWebClient; + private TaskCompletionSource _updatePasswordCompletionSource; private String _email; /// @@ -82,6 +86,14 @@ namespace Tango.MachineStudio.UI.ViewModels set { _isLogging = value; RaisePropertyChangedAuto(); } } + private bool _showLogginDetails; + public bool ShowLoggingDetails + { + get { return _showLogginDetails; } + set { _showLogginDetails = value; RaisePropertyChangedAuto(); } + } + + private bool _rememberMe; /// /// Gets or sets a value indicating whether to remember the last user email and password. @@ -123,11 +135,37 @@ namespace Tango.MachineStudio.UI.ViewModels set { _progressLog = value; RaisePropertyChangedAuto(); } } + private bool _isChangingPassword; + public bool IsChangingPassword + { + get { return _isChangingPassword; } + set { _isChangingPassword = value; RaisePropertyChangedAuto(); } + } + + private String _newPassword1; + public String NewPassword1 + { + get { return _newPassword1; } + set { _newPassword1 = value; RaisePropertyChangedAuto(); } + } + + private String _newPassword2; + public String NewPassword2 + { + get { return _newPassword2; } + set { _newPassword2 = value; RaisePropertyChangedAuto(); } + } + /// /// Gets or sets the login command. /// public RelayCommand LoginCommand { get; set; } + /// + /// Gets or sets the update password command. + /// + public RelayCommand UpdatePasswordCommand { get; set; } + /// /// Initializes a new instance of the class. /// @@ -137,6 +175,7 @@ namespace Tango.MachineStudio.UI.ViewModels public LoginViewVM(MachineStudioWebClient machineStudioWebClient, IAuthenticationProvider authenticationProvider, INavigationManager navigationManager, INotificationProvider notificationProvider, IEventLogger eventLogger) { EnableSlotSelection = true; + ShowLoggingDetails = true; _machineStudioWebClient = machineStudioWebClient; _settings = SettingsManager.Default.GetOrCreate(); @@ -146,6 +185,7 @@ namespace Tango.MachineStudio.UI.ViewModels _authenticationProvider = authenticationProvider; _eventLogger = eventLogger; LoginCommand = new RelayCommand(Login, () => !IsLogging); + UpdatePasswordCommand = new RelayCommand(UpdatePassword, () => IsChangingPassword); cryptographer = new Rfc2898Cryptographer(); Email = _settings.LastLoginEmail; @@ -181,6 +221,10 @@ namespace Tango.MachineStudio.UI.ViewModels try { IsLogging = true; + ShowLoggingDetails = false; + NewPassword1 = String.Empty; + NewPassword2 = String.Empty; + InvalidateRelayCommands(); LoginMethod loginMethod = IsActiveDirectory ? LoginMethod.ActiveDirectory : LoginMethod.StandardUser; @@ -190,9 +234,9 @@ namespace Tango.MachineStudio.UI.ViewModels _settings.DeploymentSlot = DeploymentSlot; LoginResponse result = _authenticationProvider.Login(Email, Password, loginMethod, _settings.ByPassEnvironmentVersionCheck, (progress) => - { - ProgressLog = progress; - }).Response; + { + ProgressLog = progress; + }).Response; if (result.VersionChangeRequired && !_settings.ByPassEnvironmentVersionCheck) { @@ -211,6 +255,14 @@ namespace Tango.MachineStudio.UI.ViewModels return; } + if (result.PasswordChangeRequired) + { + StartUpdatePassword().Task.GetAwaiter().GetResult(); + Password = NewPassword1; + Login(); + return; + } + _eventLogger.Log(EventTypes.APPLICATION_STARTED, "Application Started!"); _navigationManager.NavigateTo(NavigationView.MainView); @@ -224,19 +276,94 @@ namespace Tango.MachineStudio.UI.ViewModels _eventLogger.Log("User logged in."); EnableSlotSelection = false; + + IsLogging = false; + ShowLoggingDetails = true; + IsChangingPassword = false; + InvalidateRelayCommands(); }); } catch (Exception ex) { + IsLogging = false; + ShowLoggingDetails = true; + IsChangingPassword = false; + InvalidateRelayCommands(); LogManager.Log(ex, "Login Error."); _notificationProvider.ShowError($"An error occurred while trying to perform the log-in operation.\n{ex.FlattenMessage()}"); } - finally + } + } + + private TaskCompletionSource StartUpdatePassword() + { + _updatePasswordCompletionSource = new TaskCompletionSource(); + + IsChangingPassword = true; + ShowLoggingDetails = false; + IsLogging = false; + InvalidateRelayCommands(); + + return _updatePasswordCompletionSource; + } + + private async void UpdatePassword() + { + await Task.Factory.StartNew(() => + { + try + { + if (!Validate()) + { + return; + } + + ProgressLog = "Updating your password..."; + IsChangingPassword = false; + IsLogging = true; + InvalidateRelayCommands(); + + using (var db = ObservablesContext.CreateDefault()) + { + var user = db.Users.SingleOrDefault(x => x.Email == Email); + user.PasswordChangeRequired = false; + user.Password = User.GetPasswordHash(NewPassword1); + db.SaveChanges(); + } + + _updatePasswordCompletionSource.SetResult(true); + } + catch (Exception ex) { IsLogging = false; + IsChangingPassword = false; + ShowLoggingDetails = true; + InvalidateRelayCommands(); + _updatePasswordCompletionSource.SetException(ex); + } + finally + { InvalidateRelayCommands(); } + }); + } + + protected override void OnValidating() + { + if (IsChangingPassword) + { + if (!NewPassword1.IsBetweenLength(6, 8)) + { + InsertError(nameof(NewPassword1), "Password must be 6 to 8 characters long"); + } + + if (NewPassword1 != NewPassword2) + { + InsertError(nameof(NewPassword2), "Passwords do not match"); + } } + + base.OnValidating(); } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index ff13ec2c7..9a3b3405e 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -47,7 +47,7 @@ - + @@ -57,10 +57,36 @@ - + + + + + - + Login to your account @@ -97,6 +123,19 @@ + + + Password change required + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 48f7b46d3..2d5a5c3aa 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -50,48 +50,19 @@ + + - - - - - - - - , - - - - - - - - - - - - - - - ... - - - - - - - - - - - - Home - - + MODULES @@ -148,8 +119,36 @@ - + + + + + + + + + , + + + + + + + + + + + + + + + ... + + + + + - Device COM Port - - Auto Login @@ -109,7 +120,7 @@ - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index 2d5a5c3aa..15f2a30e0 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -70,7 +70,7 @@ -