diff --git a/License.txt b/License.txt new file mode 100644 index 00000000..e12bbfb0 --- /dev/null +++ b/License.txt @@ -0,0 +1,31 @@ +Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. + +1. Definitions + +The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the software. + +A "contributor" is any person that distributes its contribution under this license. + +"Licensed patents" are a contributor's patent claims that read directly on its contribution. + +2. Grant of Rights + +(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. + +(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. + +3. Conditions and Limitations + +(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. + +(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. + +(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. + +(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. + +(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. diff --git a/README.md b/README.md index 24bc533d..4c80e6dc 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,38 @@ - - - # Lively - Animated Wallpaper System [![GitHub release](https://img.shields.io/github/release/rocksdanister/lively/all.svg)](https://github.com/rocksdanister/lively/releases) [![Github all releases](https://img.shields.io/github/downloads/rocksdanister/lively/total.svg)](https://github.com/rocksdanister/lively/releases) ## Contents - - [About](#about) -- [Download](#download) - [Features](#features) +- [Download](#download) - [Issues](#issues) -- [Attribution](#attribution) +- [Contributing](#contributing) +- [Support](#support) - [License](#license) ## About ![demo-gif](/resources/preview.gif?raw=true "demo") -Turn Video & GIF Files, Emulators, HTML, Web address & Shaders, Games into Windows desktop wallpaper; Software will completely pause( 0% cpu & gpu usage) when fullscreen application/games are running. +Turn Video & GIF Files, Emulators, HTML, Web address & Shaders, Games into Windows desktop wallpaper; **Wallpapers will completely pause playback( 0% cpu & gpu usage) when fullscreen application/games are running.** -Originally made this as a console application for personal use before working on my other projects "rePaper" & "GBWallpaper". Lively is still in early development. -## Download -##### SOON +![demo-gif2](/resources/dragdrop.gif?raw=true "dragdrop") -## Features +Just drag & drop files, webpages to set as wallpaper.. + +#### Join Discussions: +* Discord group +* Reddit + +Lively is still in development, if you encounter bugs create a github Issue along with log file +Documentation +## Features +*Wait a sec, preview gif clips take some time to load.* #### Video -![demo-gif2](/resources/sea_extended.gif?raw=true "vlc") +![demo-gif2](/resources/vid.gif?raw=true "video") -Waves by Tom Fisk +Foggy Landscape by Tom Fisk * Use external codec packs or internal windows codec. * Play .mp4, mkv, webm, avi, mov etc * Hardware Acceleration support. @@ -40,43 +44,83 @@ Originally made this as a console application for personal use before working on * Chromium Embedded Framework. * Load HTML file or web address as wallpaper. * Runs webgl, javascript .. basically anything that works on chrome. -* Audio Reactive Wallpaper support, create wallpapers that react system audio. +* Audio Reactive Wallpaper support, create wallpapers that react to system audio #### Shaders ![demo-gif7](/resources/shadertoy.gif?raw=true "htmlshadertoy") -Hexagone by BigWIngs +The Universe Within, The Drive Home by BigWIngs * Run GLSL shaders in browser. -* Shadertoy urls are supported in browser. -#### Emulators +* Shadertoy.com urls are supported as wallpaper. +#### Retro Game Emulators ![demo-gif4](/resources/emulator.gif?raw=true "html") -* Emulator used currently is BizHawk, supports many retro systems: [https://github.com/TASVideos/BizHawk](https://github.com/TASVideos/BizHawk) -* Emulator will pause when not on desktop. +* Coming soon #### Games ![demo-gif5](/resources/unity.gif?raw=true "unity") * Can launch Unity & Godot games as wallpaper. -* Audio visualisers, 3D wallpapers etc.. +* Dynamic audio visualisers, 3D scenes.. #### GIFs ![demo-gif6](/resources/gif.gif?raw=true "gif") -Nyan Cat + Nyan cat * Make Memes/Cinemagraphs as wallpaper ... +#### Other Applications +* Experimentail, works for some. +#### & more: +- Easy to use, Just drag & drop media files & webpages into lively window to set it as wallpaper. +- Easy to share Lively-zip format, just drag & drop the zip file to import it into Library, use the built-in creator to make them (ensures compatibility). +- Full Multiple monitor support, play different wallpaper per screen or span a single wallpaper across all screens. +- Hardware accelerated video playback, with option to use external Directshow codec of your choice. ( LAV(recommended), K-Lite, Kawaii Codec..) +- Library to browse and preview wallpapers. +- You can use it alongside rainmeter. +- Efficient, its a native c# wpf application with c++ calls. +- Fully opensource & free; no blackmagic, no features behind paywall. +#### Regarding Performance: + * Wallpaper playback pauses when fullscreen application/games run on the machine (~0% cpu, gpu usage). + * Optionally you can set wallpaper to only play when on desktop. + * Application rules: Set wallpaper playback rules based on running foreground application.(like always pause when photoshop is open etc) + * Based on display(multiple monitor): Pause wallpaper playback per-display(depending on which monitor fullscreen apps/games run) or all display(s). + * Kill wallpaper when fullscreen apps/games run(coming soon). + * Mute audio when not on desktop (or optionally always mute). + +**_I'm not officially affiliated with Unity technologies, godot, bizhawk, shadertoy;_** +## Download +##### Latest version: v0.3.4.0 (Windows 10, 8.1, 7 32bit) +- [`lively_full_x86.zip`][direct-full-win32] + _130MB, Web wallpaper support & some sample wallpapers included._ + +- [`lively_lite_x86.zip`][direct-lite-win32] + _5MB, No web wallpaper support._ + +[direct-full-win32]: https://github.com/rocksdanister/lively/releases/download/v0.3.4.0/lively_full_x86.zip + +[direct-lite-win32]: https://github.com/rocksdanister/lively/releases/download/v0.3.4.0/lively_lite_x86.zip + +Unzip the file, select livelywpf.exe to get started, first run will be slow due to windows defender scanning. + +[Trouble Getting started? ](https://github.com/rocksdanister/lively/wiki/Getting-Started) + +Certain antivirus software heuristics algorithm will detect lively as a virus, this is a false positive +**lively is fully opensource, you are free to inspect the code.** + + +## Issues +[TODO List](https://trello.com/b/rdFFxuMF/lively-wallpaper-system) + +## Contributing +Code contributions are welcome, check [guidelines](https://github.com/rocksdanister/lively/wiki) for making pull request. + +Currently Lively is only in English, other languages are machine translated. If interested in translating: -### Other Applications -* in the works. +##### Related Projects +https://github.com/rocksdanister/lively-cef -**_I'm not officially affiliated with unity, godot, bizhawk, shadertoy;_** -## Issues & roadmap -#### Priority:- -* Passing input to child window turned out to be not as simple as using SetForegroundWindow, currently bizhawk uses its own keyhook. Complete mouse & keyboard(optional) will need to be implemented next. -* Unity games compiled with "run in background" disabled will pause since its not in focus, need to find a solution. -* Tweaking Cefsharp audio reactive parameters. -* Multimonitor is currently limited to certain types of wallpapers, more types need to be supported in multiple display systems. -#### Not priority:- -* Wallpaper creation tools. +https://github.com/rocksdanister/lively-gallery -## Attribution -todo +## Support +You can always help development by buying me a cup of coffee(paypal): +[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/P5P1U8NQ) ## License -todo +Lively is licensed under Microsoft Public License (Ms-PL). +Individual license of libraries used is found in license file in the source. diff --git a/resources/dragdrop.gif b/resources/dragdrop.gif new file mode 100644 index 00000000..3be10fe5 Binary files /dev/null and b/resources/dragdrop.gif differ diff --git a/resources/dragdrop2.gif b/resources/dragdrop2.gif new file mode 100644 index 00000000..e7aa4f87 Binary files /dev/null and b/resources/dragdrop2.gif differ diff --git a/resources/emulator.gif b/resources/emulator.gif index 0c94ab78..fcaa8f73 100644 Binary files a/resources/emulator.gif and b/resources/emulator.gif differ diff --git a/resources/preview.gif b/resources/preview.gif index 168ac386..daa60137 100644 Binary files a/resources/preview.gif and b/resources/preview.gif differ diff --git a/resources/sea.gif b/resources/sea.gif deleted file mode 100644 index 9ea83da6..00000000 Binary files a/resources/sea.gif and /dev/null differ diff --git a/resources/sea_extended.gif b/resources/sea_extended.gif deleted file mode 100644 index 065f37da..00000000 Binary files a/resources/sea_extended.gif and /dev/null differ diff --git a/resources/shadertoy.gif b/resources/shadertoy.gif index 8306806c..d92619c8 100644 Binary files a/resources/shadertoy.gif and b/resources/shadertoy.gif differ diff --git a/resources/translations/English/Resources.resx b/resources/translations/English/Resources.resx new file mode 100644 index 00000000..6742c671 --- /dev/null +++ b/resources/translations/English/Resources.resx @@ -0,0 +1,578 @@ + // Translator notes:- + // Translate the text inside value field: Hello ----> Bonjour + // Maintain similar spacing and lines if you can. + // & stands for: & + // Save the file as Resources.Languagetag.resx eg: Resources.en-US.resx. + // Languagetag: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c + // I can add your name in the about page if interested, do let me know otherwise. + // Some text are just names, ignore them. example: XamlAnimatedGif, Directshow.. + // Using an xml editing software will make editing this easy, example: Sublime-Text + // Some of my sentences are long and unnecessary, translate it however you want. + + + All Display(s) + + + XamlAnimatedGif + + + Low memory usage, high cpu usage + + + DirectShow + + + Lower cpu usage (depending on codec settings) + + + Kill(Free Memory) + + + Nothing + + + All Processes (Experimental) + + + Pause + + + Foreground Process + + + Per Display + + + Span(Experimental) + + + Media Foundation + + + DirectShow(Lav, ffdshow..) + + + + Enter commandline arguments for the application if any (optional, leave blank if none):- + + + Start Arguments + + + The selected wallpaper(application) has no graphical user interface(GUI). +Terminating application... + + + Failed to catch application window. +The wallpaper(application) is taking too long to start(more than ~30sec), it could be due to: +Virus scan/ Application is too big. +Wait & try again. (optionally you can edit the waiting time, check out wiki for more information.) +Terminating application... + + + Damaged wallpaper file, try redownloading. + + + Are you sure you want to permanently delete the wallpaper from the disk? + + + Confirm Deletion + + + Currently running as wallpaper, cannot delete! +Close this wallpaper to delete it. + + + Deletion Failed + + + This file format is not supported for drag & drop, open it in 'Type' page instead. + + + Lively: Not Supported + + + You are opening an external application as wallpaper. +Malicious applications can host malware, virus.. and do harm to your system. +Only continue if this application comes from a trusted source. + + + Warning + + + GIF file playback failed. +Is the GIF file corrupted? Try redownloading. + + + Lively cannot work properly with Windows High Contrast mode enabled! +Disable High Contrast mode & Try again. + + + You are about to open an external webpage on your browser. + +URL:- + + + Load Webpage? + + + Starting up external application.. + + + Media playback failed: Missing Codec/ Corrupted File. +Install LAV codec & Try switching to Directshow videoplayer. + +Further Instructions: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + Media playback failed: Missing Codec/ Corrupted File. +Don't forget to install LAV codec: +www.github.com/Nevcairiel/LAVFilters/releases + +Further Instructions: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + Currently restoring previous wallpaper(s), please wait. + + + Restoring previous wallpaper(s).. + + + Lively was not closed properly, starting in safe mode. +Do you wish to restore previously running wallpapers? +Error information is saved at:- + + + + Lively is already running! +If not-responding terminate process "livelywpf" in taskmanager & try again. + + + Enter website link to load, Shadertoy.com shader links are supported:- + + + Load webpage + + + You are about to load an external website. +Malicious Web pages can be harmful to your computer (malware, virus ..) +Only enter links to websites that you trust. + + + Warning + + + Web browser component is missing, either download separately:- +https://github.com/rocksdanister/lively-cef +OR +Download the full version of lively. + + + It looks like some settings needs to be set to make Lively work:- +1. Open This PC(My Computer) +2. Right-click empty area +3. Select Properties +4. Select Advanced System Settings +5. Under Performance tab select Settings +6. Enable Animate controls and elements inside windows & Apply. + +If Windows 7 just set - Adjust for best appearance & Apply. +If still not working, close & start Lively again/ restart windows. + + + About + + + Library + + + Settings + + + Type + + + I'm minimized to systemtray, right click lively icon for more options. + + + A new version is available! + + + Some wallpaper(s) were skipped because of missing file(s)! + + + Application Rules + + + Audio In: + + + Blocks browsers access to system audio. + + + Audio is always disabled in multiple monitor systems. + + + "Audio In" is disabled, Web audio visualisers will not work. + + + Audio Out: + + + Unmute/mute video player. + + + Web Browser: + + + Select web browser for web wallpapers(coming soon) + + + Close All Wallpapers + + + Coming Soon + + + Close All Wallpapers + + + Close Wallpaper + + + Delete Wallpaper + + + Exit + + + Export lively .zip + + + Open Lively + + + Show on Disk + + + Checking for update + + + Update Available! + + + Is this Beta software? + + + Lively is up-to-date! + + + Error Checking for Update + + + Create Wallpaper + + + Creating Lively zip file. + + + Display Pause Rule: + + + GIF Player: + + + Directshow requires additionals plugins to be installed. + + + Help + + + Ignore + + + Install Wallpaper + + + Select wallpaper type to load:- + + + Attribution: + + + What should I use? + + + Type: + + + Force 120FPS UI + + + Author: + + + Contact: + + + General: + settings tab + + + Require app restart: + settings tab + + + Video: + settings tab + + + Gif: + settings tab + + + Web Browser: + settings tab + + + Just drag and drop mediafiles if you prefer it that way instead. + + + Performance: + settings tab + + + Set wallpaper(s) playback behaviour based on running application:- + + + Add + + + Remove + + + Select Wallpaper Layout:- + + + Pick a wallpaper type to create:- + + + Library File: Create easy to share .zip file that loads wallpaper into Lively's library. +To simply play a file as wallpaper, this is not required; just drag and drop the file to lively window. + + + Contact Website(optional):- + + + License(optional):- + + + Title:- + + + These materials are not sponsored by or affiliated with Unity Technologies, Godot, Bizhawk, Shadertoy.com + + + Description:- + + + Select File + + + Thumbnail (200x200) + + + Create + + + Preview Gif (192x108) + + + Wallpaper Type:- + + + Files and Folders being added:- + + + Ok + + + Back + + + Installing Wallpaper + + + Media + + + Games + + + Retro + + + Other + + + Web + + + Audio Visualiser + + + Application + + + Lively + + + Rule + + + Disable Hardware Acceleration + + + This feature is currently in development. +Do NOT run programs such as CHROME, STEAM.. which spawn multiple Subprocesses. +THERE WILL BE BUGS & CRASHES, PROCEED WITH CAUTION!!! + + + Lively: Error + title for messagebox. + + + Please Wait + title for messagebox + + + Application + + + Animated GIF + + + Godot Application + + + Unity Application + + + Unity Audio Reactive + + + Video + + + Web + + + Web Audio Reactive + + + Animated Tile: + + + (Experimental, High cpu usage)Play wallpaper preview on library tile. + + + Fille all the required text fields. + + + Wallpaper file not selected + + + Note: +(1) Lively window ignores these rules. +(2) Audio is always muted when other apps are in focus {except (1), Lively window}. +(3) Foreground Process algorithm has some limitations, check wiki for more information. +(4) Application Rules has the highest priority. +(5) Web browser is being minimized for pausing, so you will see wallpaper temporarily reverting to default in some cases; fix is coming soon. + + + Off + + + On + + + Other Application Focused: + + + Other Application Fullscreen: + + + Pause Algorithm: + + + Load Failed + + + Please Wait + + + Select previewclip/thumbnail file. + + + Set as Wallpaper + + + Some wallpapers will not span across displays properly. + + + Start with Windows: + + + Make sure to uncheck this before uninstalling lively. + + + Support + + + Animated GIF + + + Godot Software + + + HTML + + + Other + + + Unity Software + + + Video + + + Website + + + Lively Wallpaper System + + + Transparent UI: + + + Make lively window semi-transparent. + + + Update available Lively + + + Video Player: + + + Directshow requires additionals plugins to be installed. + + + Wallpaper Playback: + + + Select Display + + \ No newline at end of file diff --git a/resources/vid.gif b/resources/vid.gif new file mode 100644 index 00000000..df646d5c Binary files /dev/null and b/resources/vid.gif differ diff --git a/src/livelywpf/livelySubProcess/App.config b/src/livelywpf/livelySubProcess/App.config new file mode 100644 index 00000000..56efbc7b --- /dev/null +++ b/src/livelywpf/livelySubProcess/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelySubProcess/Program.cs b/src/livelywpf/livelySubProcess/Program.cs new file mode 100644 index 00000000..7c1cde03 --- /dev/null +++ b/src/livelywpf/livelySubProcess/Program.cs @@ -0,0 +1,180 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace livelySubProcess +{ + /// + /// Runs in the background, cleans up external wp pgms in the event lively crash. + /// + class Program + { + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni); + public static UInt32 SPI_SETDESKWALLPAPER = 20; + public static UInt32 SPIF_UPDATEINIFILE = 0x1; + + static void Main(string[] args) + { + + int livelyId; + Process lively; + + if (args.Length == 0) + { + Console.WriteLine("NO arguments sent."); + //Console.Read(); + return; + } + + if (args.Length == 1) + { + try + { + livelyId = Convert.ToInt32(args[0], 10); + } + catch + { + Console.WriteLine("ERROR: converting toint"); + //Console.Read(); + return; + } + } + else + { + Console.WriteLine("Incorrent no of arguments."); + //Console.Read(); + return; + } + + try + { + lively = Process.GetProcessById(livelyId); + } + catch + { + Console.WriteLine("getting processname failure, ignoring"); + //Console.Read(); + return; + } + + if (!lively.ProcessName.Equals("livelywpf", StringComparison.InvariantCultureIgnoreCase)) + { + Console.WriteLine("Error: Not livelywpf :- " + lively.ProcessName); + //Console.Read(); + return; + } + + lively.WaitForExit(); + + Console.WriteLine("done waiting, ready to kill *_*"); + //Console.Read(); + + FileHandle.LoadRunningPrograms(); + + foreach (var proc in Process.GetProcesses()) + { + Console.WriteLine("pgm list:- " + proc.ProcessName + " " + proc.MainWindowHandle); + foreach (var wproc in FileHandle.runningPrograms) + { + if (proc.ProcessName.Equals(wproc.ProcessName, StringComparison.OrdinalIgnoreCase) && proc.Id == wproc.Pid)//&& IntPtr.Equals(proc.MainWindowHandle,wproc.handle))//proc.Handle == wproc.handle) + { + Console.WriteLine("Unclosed pgm, kill:- " + proc.ProcessName); + try + { + proc.Kill(); + } + catch { } + + } + } + } + + //force refresh desktop. + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, null, SPIF_UPDATEINIFILE); + + FileHandle.runningPrograms.Clear(); + FileHandle.SaveRunningPrograms(); + } + } + + class FileHandle + { + [Serializable] + public class RunningProgram + { + public string ProcessName { get; set; } + public int Pid { get; set; } + public RunningProgram() + { + Pid = 0; + ProcessName = null; + } + } + + public static List runningPrograms = new List(); + + public class RunningProgramsList + { + public List Item { get; set; } + } + + public static void LoadRunningPrograms() + { + if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\lively_running_pgms.json")) + { + return; + } + + try + { + + // deserialize JSON directly from a file + using (StreamReader file = File.OpenText(AppDomain.CurrentDomain.BaseDirectory + "\\lively_running_pgms.json")) + { + JsonSerializer serializer = new JsonSerializer(); + RunningProgramsList tmp = (RunningProgramsList)serializer.Deserialize(file, typeof(RunningProgramsList)); + runningPrograms = tmp.Item; + } + + } + catch (Exception e) + { + System.Diagnostics.Debug.WriteLine(e.Message + " " + e.StackTrace); + } + } + + + public static void SaveRunningPrograms() + { + RunningProgramsList tmp = new RunningProgramsList + { + Item = runningPrograms + }; + + JsonSerializer serializer = new JsonSerializer + { + Formatting = Formatting.Indented, + + //serializer.Converters.Add(new JavaScriptDateTimeConverter()); + NullValueHandling = NullValueHandling.Include + }; + + using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\lively_running_pgms.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, tmp); + } + } + + } +} diff --git a/src/livelywpf/livelySubProcess/Properties/AssemblyInfo.cs b/src/livelywpf/livelySubProcess/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f60fbda9 --- /dev/null +++ b/src/livelywpf/livelySubProcess/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("livelySubProcess")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("livelySubProcess")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("42cf8b44-9366-4579-83cf-b8e460e5330f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/livelywpf/livelySubProcess/livelySubProcess.csproj b/src/livelywpf/livelySubProcess/livelySubProcess.csproj new file mode 100644 index 00000000..f9216553 --- /dev/null +++ b/src/livelywpf/livelySubProcess/livelySubProcess.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + {42CF8B44-9366-4579-83CF-B8E460E5330F} + WinExe + livelySubProcess + livelySubProcess + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelySubProcess/packages.config b/src/livelywpf/livelySubProcess/packages.config new file mode 100644 index 00000000..a9de8b55 --- /dev/null +++ b/src/livelywpf/livelySubProcess/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf.sln b/src/livelywpf/livelywpf.sln new file mode 100644 index 00000000..cf2220d6 --- /dev/null +++ b/src/livelywpf/livelywpf.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "livelywpf", "livelywpf\livelywpf.csproj", "{A71FC3FA-C514-4F6A-97F4-BC43F9403F88}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "livelySubProcess", "livelySubProcess\livelySubProcess.csproj", "{42CF8B44-9366-4579-83CF-B8E460E5330F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Debug|x64.ActiveCfg = Debug|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Debug|x64.Build.0 = Debug|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Debug|x86.ActiveCfg = Debug|x86 + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Debug|x86.Build.0 = Debug|x86 + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Release|Any CPU.Build.0 = Release|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Release|x64.ActiveCfg = Release|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Release|x64.Build.0 = Release|Any CPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Release|x86.ActiveCfg = Release|x86 + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88}.Release|x86.Build.0 = Release|x86 + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Debug|x64.ActiveCfg = Debug|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Debug|x64.Build.0 = Debug|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Debug|x86.ActiveCfg = Debug|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Debug|x86.Build.0 = Debug|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Release|Any CPU.Build.0 = Release|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Release|x64.ActiveCfg = Release|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Release|x64.Build.0 = Release|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Release|x86.ActiveCfg = Release|Any CPU + {42CF8B44-9366-4579-83CF-B8E460E5330F}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FB61461D-CD6D-4803-86CC-C75F6431E416} + EndGlobalSection +EndGlobal diff --git a/src/livelywpf/livelywpf/App.config b/src/livelywpf/livelywpf/App.config new file mode 100644 index 00000000..f50bb5d6 --- /dev/null +++ b/src/livelywpf/livelywpf/App.config @@ -0,0 +1,37 @@ + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/App.xaml b/src/livelywpf/livelywpf/App.xaml new file mode 100644 index 00000000..6b0eb5f4 --- /dev/null +++ b/src/livelywpf/livelywpf/App.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/livelywpf/livelywpf/App.xaml.cs b/src/livelywpf/livelywpf/App.xaml.cs new file mode 100644 index 00000000..f3b4001c --- /dev/null +++ b/src/livelywpf/livelywpf/App.xaml.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.IO; +using System.Windows.Media; +using System.Windows.Interop; +using System.Globalization; + +using Props = livelywpf.Properties; + + +namespace livelywpf +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + static Mutex mutex = new Mutex(false, "LIVELY:DESKTOPWALLPAPERSYSTEM"); + + MainWindow w = null; + protected override void OnStartup(StartupEventArgs e) + { + Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData"); //create if not exist + SaveData.LoadConfig(); + + #region language + //CultureInfo.CurrentCulture = new CultureInfo("ru-RU", false); //not working? + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(SaveData.config.Language); + //System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-CN"); //zh-CN + #endregion language + + if (!SaveData.config.SafeShutdown) + { + //clearing previous wp persisting image if any. + SetupDesktop.RefreshDesktop(); + + Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\ErrorLogs\\"); + string fileName = DateTime.Now.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture) + ".txt"; + if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\ErrorLogs\\" + fileName)) + fileName = Path.GetRandomFileName() + ".txt"; + + try + { + File.Copy(AppDomain.CurrentDomain.BaseDirectory + "\\logfile.txt", + AppDomain.CurrentDomain.BaseDirectory + "\\ErrorLogs\\" + fileName); + } + catch(IOException e1) + { + System.Diagnostics.Debug.WriteLine(e1.ToString()); + } + + var result = MessageBox.Show(Props.Resources.msgSafeModeWarning + + AppDomain.CurrentDomain.BaseDirectory + "ErrorLogs\\" + fileName + , Props.Resources.txtLivelyErrorMsgTitle, MessageBoxButton.YesNo); + + if (result == MessageBoxResult.No) + { + SetupDesktop.wallpapers.Clear(); + SaveData.SaveWallpaperLayout(); //deleting saved wallpaper arrangements. + } + + } + SaveData.config.SafeShutdown = false; + SaveData.SaveConfig(); + + base.OnStartup(e); + SetupExceptionHandling(); + w = new MainWindow(); + + if (SaveData.config.IsFirstRun) + { + //SaveData.config.isFirstRun = false; //only after minimizing to tray isFirstRun is set to false. + SaveData.SaveConfig(); //creating disk file temp, not needed! + + w.Show(); + w.UpdateWallpaperLibrary(); + + HelpWindow hw = new HelpWindow + { + Owner = w, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; + hw.ShowDialog(); + + } + + if(SaveData.config.IsRestart) + { + SaveData.config.IsRestart = false; + SaveData.SaveConfig(); + + //w.WindowStartupLocation = WindowStartupLocation.Manual; + w.Show(); + w.UpdateWallpaperLibrary(); + + w.tabControl1.SelectedIndex = 2; //settings tab + } + + } + + private void SetupExceptionHandling() + { + AppDomain.CurrentDomain.UnhandledException += (s, e) => + LogUnhandledException((Exception)e.ExceptionObject, "AppDomain.CurrentDomain.UnhandledException"); + + Dispatcher.UnhandledException += (s, e) => + LogUnhandledException(e.Exception, "Application.Current.DispatcherUnhandledException"); + + TaskScheduler.UnobservedTaskException += (s, e) => + LogUnhandledException(e.Exception, "TaskScheduler.UnobservedTaskException"); + } + + private void LogUnhandledException(Exception exception, string source) + { + string message = $"Unhandled exception ({source})"; + try + { + System.Reflection.AssemblyName assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName(); + message = string.Format("Unhandled exception in {0} v{1}", assemblyName.Name, assemblyName.Version); + } + catch (Exception ex) + { + Logger.Error(ex, "Exception in LogUnhandledException"); + } + finally + { + LogSavedData(); + Logger.Error(message + "\n" + exception.ToString()); + } + + //making the external process livelymonitor.exe close running wp's instead. + //SetupDesktop.CloseAllWallpapers(); + } + + private bool _savedDataLogged = false; + private void LogSavedData() + { + if (!_savedDataLogged) + { + Logger.Info("Saved config file:-\n" + SaveData.PropertyList(SaveData.config)); + _savedDataLogged = true; + } + } + + void App_SessionEnding(object sender, SessionEndingCancelEventArgs e) + { + /* + // Ask the user if they want to allow the session to end + //string msg = string.Format("{0}. End session?", e.ReasonSessionEnding); + //MessageBoxResult result = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo); + + // End session, if specified + if (result == MessageBoxResult.No) + { + e.Cancel = true; + } + */ + + if(e.ReasonSessionEnding == ReasonSessionEnding.Shutdown || e.ReasonSessionEnding == ReasonSessionEnding.Logoff) + { + e.Cancel = true; //delay shutdown till lively close properly. + if (w != null) + w.ExitApplication(); + } + + } + + [STAThread] + public static void Main() + { + //NotifyIcon Fix: https://stackoverflow.com/questions/28833702/wpf-notifyicon-crash-on-first-run-the-root-visual-of-a-visualtarget-cannot-hav/29116917 + //Rarely I get this error "The root Visual of a VisualTarget cannot have a parent..", hard to pinpoint not knowing how to recreate the error. + System.Windows.Controls.ToolTip tt = new System.Windows.Controls.ToolTip(); + tt.IsOpen = true; + tt.IsOpen = false; + + try + { + // wait a few seconds in case that the instance is just shutting down + //if (!mutex.WaitOne()) + if (!mutex.WaitOne(TimeSpan.FromSeconds(5), false)) + { + //this is ignoring the config-file saved language, only checking system language. + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(CultureInfo.CurrentCulture.Name); + MessageBox.Show(Props.Resources.msgSingleInstanceOnly, Props.Resources.txtLivelyWaitMsgTitle); + return; + } + } + catch(AbandonedMutexException e) + { + //Note to self:- logger backup(in the even of previous lively crash) is at App() contructor fn, DO NOT start writing loghere to avoid erasing crashlog. + System.Diagnostics.Debug.WriteLine(e.Message); + } + + try + { + var application = new App(); + application.InitializeComponent(); + application.Run(); + } + finally { mutex.ReleaseMutex(); } + } + + } +} diff --git a/src/livelywpf/livelywpf/GlobalSuppressions.cs b/src/livelywpf/livelywpf/GlobalSuppressions.cs new file mode 100644 index 00000000..282d4492 --- /dev/null +++ b/src/livelywpf/livelywpf/GlobalSuppressions.cs @@ -0,0 +1,4 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. diff --git a/src/livelywpf/livelywpf/MainWindow.xaml b/src/livelywpf/livelywpf/MainWindow.xaml new file mode 100644 index 00000000..4fb66ec0 --- /dev/null +++ b/src/livelywpf/livelywpf/MainWindow.xaml @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/livelywpf/livelywpf/MainWindow.xaml.cs b/src/livelywpf/livelywpf/MainWindow.xaml.cs new file mode 100644 index 00000000..2911aba8 --- /dev/null +++ b/src/livelywpf/livelywpf/MainWindow.xaml.cs @@ -0,0 +1,2220 @@ +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; +using MahApps.Metro.Controls; +using MahApps.Metro.Controls.Dialogs; +using System.Diagnostics; + +using System.Reflection; +using Ionic.Zip; +//using System.IO.Compression; +using System.Windows.Forms; +using System.IO; +using Microsoft.Win32; +using OpenFileDialog = Microsoft.Win32.OpenFileDialog; +using MessageBox = System.Windows.MessageBox; +using Path = System.IO.Path; +using System.Security.Cryptography; +using Octokit; +using FileMode = System.IO.FileMode; +using Microsoft.WindowsAPICodePack.Shell; +using IWshRuntimeLibrary; +using System.Threading; +using File = System.IO.File; +using NLog; +using System.Collections.ObjectModel; +using System.Windows.Media.Animation; +using System.ComponentModel; + +using static livelywpf.SaveData; +using System.Text.RegularExpressions; +using System.Windows.Interop; +using SaveFileDialog = Microsoft.Win32.SaveFileDialog; +using System.Globalization; + +namespace livelywpf +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : MetroWindow + { + //CultureInfo.CurrentCulture = new CultureInfo("th-TH", false); + + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + public static bool multiscreen = false; + ProgressDialogController progressController = null; + private ObservableCollection tileDataList = new ObservableCollection(); + private ObservableCollection selectedTile = new ObservableCollection(); + + private ICollectionView tileDataFiltered; + private bool _isRestoringWallpapers = false; + public static bool highContrastFix = false; + + public MainWindow() + { + SystemInfo.LogHardwareInfo(); + + #region lively_SubProcess + //External process that runs, kills external pgm wp's( unity, app etc) & refresh desktop in the event lively crashed, could do this in UnhandledException event but this is guaranteed to work even if user kills livelywpf in taskmgr. + //todo:- should reconsider. + try + { + Process.Start(Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "\\livelySubProcess.exe"), Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture)); + } + catch(Exception e) + { + Logger.Error(e,"Starting livelybg.exe failure: " + e.ToString()); + } + #endregion lively_SubProcess + + //settings applied only during app relaunch. + #region misc_fixes + SetupDesktop.wallpaperWaitTime = SaveData.config.WallpaperWaitTime; + + if(SaveData.config.WallpaperRendering == WallpaperRenderingMode.bottom_most) + { + highContrastFix = true; + } + + if (SaveData.config.Ui120FPS) + { + //force 120fps, in some systems gpu downclocking too much due to low power usage..this is a workaround for smoother ui. + Timeline.DesiredFrameRateProperty.OverrideMetadata(typeof(Timeline), + new FrameworkPropertyMetadata { DefaultValue = 120 }); + } + + //disable UI HW-Acceleration, for very low end systems optional. + if(SaveData.config.UiDisableHW) + RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; + + //always show tooltip, even disabled ui elements. + ToolTipService.ShowOnDisabledProperty.OverrideMetadata(typeof(System.Windows.Controls.Control), + new FrameworkPropertyMetadata(true)); + #endregion misc_fixes + + InitializeComponent(); + + this.Closing += MainWindow_Closing; + SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged; //static event, unsubcribe! + //todo:- Window.DpiChangedEvent, so far not required. + //todo:- Suspend/hibernate events (SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged) + + CreateSysTray(); + //this.DataContext = SaveData.config; + RestoreSaveSettings(); + + //data binding + wallpapersLV.ItemsSource = tileDataList; + tileDataFiltered = CollectionViewSource.GetDefaultView(tileDataList); + tileInfo.ItemsSource = selectedTile; + //this.DataContext = selectedTile; //todo: figure out why is this not working? + + SubcribeUI(); + + lblVersionNumber.Text = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + + //Incomplete, currently in development:- all process algorithm & multiscreen + if (multiscreen && SaveData.config.ProcessMonitorAlgorithm == ProcessMonitorAlgorithm.all) + { + Logger.Info("Skipping all-process algorthm on multiscreen(in-development)"); + comboBoxPauseAlgorithm.SelectedIndex = (int)ProcessMonitorAlgorithm.foreground; //event will save settings. + } + + //attribution document. + TextRange textRange = new TextRange(licenseDocument.ContentStart, licenseDocument.ContentEnd); + if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "\\docs\\license.rtf"))) + { + try + { + using (FileStream fileStream = File.Open(Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "\\docs\\license.rtf"), FileMode.Open, FileAccess.Read, FileShare.Read)) + { + textRange.Load(fileStream, System.Windows.DataFormats.Rtf); + } + licenseFlowDocumentViewer.Document = licenseDocument; + } + catch + { + Logger.Error("Failed to load license file"); + } + } + /* + DoubleAnimation anim = new DoubleAnimation(); + Storyboard storyBoard = (Storyboard)this.Resources["fidgetSpinner"]; + */ + + SystemEvents_DisplaySettingsChanged(this, null); //restore previously running wp's. + } + + private async void RestoreSaveSettings() + { + //load savefiles. + SaveData.LoadApplicationRules(); + //SaveData.LoadConfig(); //app.xaml.cs loads config file. + SaveData.LoadWallpaperLayout(); + RestoreMenuSettings(); + SetStartupRegistry(SaveData.config.Startup); + + await GithubCheck(); + update_traybtn.Enabled = true; + } + + #region github_update_check + /// + /// Compares application Version string with github release version & shows native windows notification. + /// Note: Comaprison result<0 if github release tag is less than 4 digits. + /// + private async Task GithubCheck() + { + await Task.Delay(45000); //45sec delay (computer startup..) + //await Task.Delay(100); + try + { + GitHubClient client = new GitHubClient(new ProductHeaderValue("lively")); + var releases = await client.Repository.Release.GetAll("rocksdanister", "lively"); + //GitHubClient client = new GitHubClient(new ProductHeaderValue("rePaper")); + //var releases = await client.Repository.Release.GetAll("rocksdanister", "rePaper"); + var latest = releases[0]; + + //string tmp = latest.TagName.Replace("v", string.Empty); + string tmp = Regex.Replace(latest.TagName, "[A-Za-z ]", ""); + var gitVersion = new Version(tmp); + var appVersion = new Version(System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()); + var result = gitVersion.CompareTo(appVersion); + if (result > 0) //github ver greater, update available! + { + _notifyIcon.ShowBalloonTip(2000, "lively", Properties.Resources.toolTipUpdateMsg, ToolTipIcon.None); + update_traybtn.Text = Properties.Resources.txtContextMenuUpdate2; + hyperlinkUpdateBannerText.Text = Properties.Resources.txtUpdateBanner+" v" + tmp; + hyperlinkUpdateBanner.Visibility = Visibility.Visible; + } + else if (result < 0) //this is early access software. + { + update_traybtn.Text = Properties.Resources.txtContextMenuUpdate3; + } + else //up-to-date + { + update_traybtn.Text = Properties.Resources.txtContextMenuUpdate4; + } + } + catch (Exception e) + { + update_traybtn.Text = Properties.Resources.txtContextMenuUpdate5; + Logger.Error("Error checking for update: " + e.Message); + } + } + #endregion github_update_check + + #region system_events + private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) + { + throw new NotImplementedException(); + } + + bool _startupRun = true; + /// + /// Display device settings changed event. + /// Closes & restarts wp's in the event system display layout changes.(based on wallpaperlayout SaveData file) + /// Updates wp dimensions in the event ONLY resolution changes. + /// + /// + /// + public void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) + { + //bool _startupRun = false; + if (Screen.AllScreens.Length > 1) + { + foreach (var item in Screen.AllScreens) + { + Debug.WriteLine("Detected Displays:- " + item); + Logger.Debug("Detected Displays:- " + item); + } + multiscreen = true; + } + else + { + multiscreen = false; + Logger.Debug("Single Display Mode:- " + Screen.PrimaryScreen); + } + + List toBeRemoved = new List(); + List wallpapersToBeLoaded = new List(SetupDesktop.wallpapers); + + if (_startupRun) //first run. + { + _startupRun = true; + } + else + { + Debug.WriteLine("Display Settings Changed Event. "); + Logger.Info("Display Settings Changed Event.."); + } + + bool found; + foreach (var item in wallpapersToBeLoaded) + { + found = false; + foreach (var scr in Screen.AllScreens) + { + if (item.DeviceName == scr.DeviceName) //ordinal comparison + { + found = true; + break; + } + } + if (!found) + { + toBeRemoved.Add(item); + } + } + if (toBeRemoved.Count > 0) + wallpapersToBeLoaded = wallpapersToBeLoaded.Except(toBeRemoved).ToList(); //new list + + foreach (var item in wallpapersToBeLoaded) + { + Debug.WriteLine("tobereloaded:- " + item.DeviceName); + Logger.Info("Display(s) wallpapers to load:-" + item.DeviceName); + } + + if (!wallpapersToBeLoaded.SequenceEqual(SetupDesktop.wallpapers) || _startupRun) + { + SetupDesktop.CloseAllWallpapers(); //todo: only close wallpapers that which is running on disconnected display. + Logger.Info("Restarting/Restoring All Wallpaper(s)"); + + //remove wp's with file missing on disk, except for url type( filePath = website url). + if( wallpapersToBeLoaded.RemoveAll(x => !File.Exists(x.FilePath) && x.Type != SetupDesktop.WallpaperType.url) > 0) + { + _notifyIcon.ShowBalloonTip(10000,"lively",Properties.Resources.toolTipWallpaperSkip, ToolTipIcon.None); + } + + if(SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + //unlikely to happen unless user edits the json file manually or some file error? + if(wallpapersToBeLoaded.Count > 1) + { + //span across all display(s), only 1 wp allowed! + wallpapersToBeLoaded.RemoveRange(1, (wallpapersToBeLoaded.Count-1) ); + } + } + RestoreWallpaper(wallpapersToBeLoaded); + } + else + { + Logger.Info("Display(s) settings such as resolution etc changed, updating wp(s) dimensions"); + SetupDesktop.UpdateAllWallpaperRect(); + } + //wallpapersToBeLoaded.Clear(); + _startupRun = false; + } + + #endregion system_events + + #region windows_startup + /// + /// Adds startup entry in registry under application name "livelywpf", current user ONLY. (Does not require admin rights). + /// + /// false: delete entry, true: add/update entry. + private void SetStartupRegistry(bool setStartup = false) + { + Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); + Assembly curAssembly = Assembly.GetExecutingAssembly(); + if (setStartup) + { + try + { + key.SetValue(curAssembly.GetName().Name, curAssembly.Location); + } + catch (Exception ex) + { + StartupToggle.IsChecked = false; + Logger.Error(ex.ToString()); + MessageBox.Show("Failed to setup startup", Properties.Resources.txtLivelyErrorMsgTitle); + } + } + else + { + try + { + key.DeleteValue(curAssembly.GetName().Name, false); + } + catch (Exception ex) + { + Logger.Error(ex.ToString()); + } + } + key.Close(); + } + + [Obsolete("Fails to work when folderpath contains non-english characters(WshShell is ancient afterall); use SetStartupRegistry() instead.")] + /// + /// Creates application shortcut & copy to startup folder of current user(does not require admin rights). + /// + /// + private void SetStartupFolder(bool setStartup = false) + { + string shortcutAddress = Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\LivelyWallpaper.lnk"; + if (setStartup) + { + try + { + IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); + System.Reflection.Assembly curAssembly = System.Reflection.Assembly.GetExecutingAssembly(); + + IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shortcutAddress); + shortcut.Description = "Lively Wallpaper System"; + shortcut.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory; + shortcut.TargetPath = curAssembly.Location; + shortcut.Save(); + } + catch(Exception e) + { + StartupToggle.IsChecked = false; + Logger.Error(e.ToString()); + MessageBox.Show("Failed to setup startup", Properties.Resources.txtLivelyErrorMsgTitle); + } + } + else + { + if(File.Exists(shortcutAddress)) + { + try + { + File.Delete(shortcutAddress); + } + catch (UnauthorizedAccessException e) + { + Logger.Error(e.ToString()); + MessageBox.Show("UnauthorizedAccessException: The caller does not have the required permission.? try restarting lively with admin access or delete the file yourself:\n" + + Environment.GetFolderPath(Environment.SpecialFolder.Startup), Properties.Resources.txtLivelyErrorMsgTitle); + } + } + } + } + + private void StartupToggle_IsCheckedChanged(object sender, EventArgs e) + { + SetStartupRegistry(StartupToggle.IsChecked.Value); + + SaveData.config.Startup = StartupToggle.IsChecked.Value; + SaveData.SaveConfig(); + } + #endregion windows_startup + + #region wallpaper_library + + /// + /// Loads & populate lively wp library from "//wallpapers" path if any. + /// + public void UpdateWallpaperLibrary() + { + tileDataList.Clear(); + selectedTile.Clear(); + //wallpapersLV.SelectedIndex = -1; + List tmpLoadedWallpapers = new List(); + + Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\wallpapers"); //creates if does not exist. + var dir = Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory + "\\wallpapers"); + foreach (var item in dir) + { + if(File.Exists(item + "\\LivelyInfo.json")) + { + if (SaveData.LoadWallpaperMetaData(item)) + { + if (SaveData.info.Type == SetupDesktop.WallpaperType.url) + { + Logger.Info("Skipping url type wallpaper(not allowed in Library):- " + SaveData.info.FileName + " " + SaveData.info.Type); + continue; + } + + SaveData.info.FileName = item + "\\" + SaveData.info.FileName; + SaveData.info.Preview = item + "\\" + SaveData.info.Preview; + SaveData.info.Thumbnail = item + "\\" + SaveData.info.Thumbnail; + if (File.Exists(SaveData.info.FileName) && File.Exists(SaveData.info.Preview) && File.Exists(SaveData.info.Thumbnail)) + { + Logger.Info("Loading Wallpaper:- " + SaveData.info.FileName + " " + SaveData.info.Type); + //tileDataList.Add(new TileData(SaveData.info)); + tmpLoadedWallpapers.Add(info); + #region testing + for (int i = 0; i < 0; i++) + { + tileDataList.Add(new TileData(SaveData.info)); + } + + #endregion + } + else + { + Logger.Info("Files does not exist, skipping wallpaper:- " + SaveData.info.FileName + " " + SaveData.info.Type); + } + } + } + else + { + Logger.Info("Not a lively wallpaper folder, skipping:- " + item); + } + } + //tmpItems.Sort((x, y) => string.Compare(x.LivelyInfo.Title, y.LivelyInfo.Title)); + //sorting based on alphabetical order of wp title text. + var sortedList = tmpLoadedWallpapers.OrderBy(x => x.Title).ToList(); + foreach (var item in sortedList) + { + tileDataList.Add(new TileData(item)); + } + + sortedList.Clear(); + tmpLoadedWallpapers.Clear(); + sortedList = null; + tmpLoadedWallpapers = null; + + InitializeTilePreviewGifs(); + + if(prevSelectedLibIndex < tileDataList.Count ) + wallpapersLV.SelectedIndex = prevSelectedLibIndex; + } + + /// + /// User selected tile in library. + /// + /// + /// + private void WallpapersLV_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + selectedTile.Clear(); + if (wallpapersLV.SelectedIndex == -1) + { + return; + } + selectedTile.Add((TileData)wallpapersLV.SelectedItem); + } + + #region library_filter + private void TextBoxLibrarySearch_TextChanged(object sender, TextChangedEventArgs e) + { + if (String.IsNullOrWhiteSpace(textBoxLibrarySearch.Text)) + { + tileDataFiltered.Filter = null; + } + else + { + TileData tmpvar; + tileDataFiltered.Filter = i => ( (tmpvar = (TileData)i).LivelyInfo.Title + tmpvar.LivelyInfo.Desc).IndexOf(textBoxLibrarySearch.Text, StringComparison.OrdinalIgnoreCase) > -1; + } + //todo:- fix, search buggy with my dynamic gif loading code. + //prevIndexOffset = 666; + //WallpapersLV_ScrollChanged(null, null); + } + + #endregion library_filter + + #region scroll_gif_logic + + /// + /// Initialize only few gif preview to reduce cpu usage, gif's are loaded & disposed(atleast marked) based on ScrollChanged event. + /// + private void InitializeTilePreviewGifs() + { + if (!SaveData.config.LiveTile) + return; + + for (int i = 0; i < tileDataList.Count; i++) + { + if (i >= 20) + return; + tileDataList[i].TilePreview = tileDataList[i].LivelyInfo.Preview; + } + } + + private int prevIndexOffset = 0; + private void WallpapersLV_ScrollChanged(object sender, ScrollChangedEventArgs e) + { + if (!SaveData.config.LiveTile) + return; + + ScrollViewer scrollViewer = GetDescendantByType(wallpapersLV, typeof(ScrollViewer)) as ScrollViewer; + if (scrollViewer != null) + { + //Debug.WriteLine(scrollViewer.VerticalOffset ); + //Debug.WriteLine("Visible Item Count:{0}", scrollViewer.ViewportHeight); + int indexOffset = 0; + double percent = scrollViewer.ViewportHeight * .33f; + double shiftY = scrollViewer.VerticalOffset / percent; + + int startIndex = 0; + /* + for (int i = 0; i < tileDataList.Count; i++) + { + if (tileDataList[i].LivelyInfo.title.StartsWith(textBoxLibrarySearch.Text, StringComparison.OrdinalIgnoreCase)) + { + startIndex = i; + break; + } + } + */ + if (shiftY > 0 || sender == null ) + { + indexOffset = startIndex + Convert.ToInt32(shiftY) * 5; + } + + if (indexOffset != prevIndexOffset) + { + int count = 0; + for (int i = 0; i < tileDataList.Count; i++) + { + if (i >= indexOffset && count <= 20) + { + tileDataList[i].TilePreview = tileDataList[i].LivelyInfo.Preview; + count++; + } + else + { + tileDataList[i].TilePreview = null; + } + } + //wallpapersLV.Items.Refresh(); + } + prevIndexOffset = indexOffset; + } + } + + public static Visual GetDescendantByType(Visual element, Type type) + { + if (element == null) + { + return null; + } + if (element.GetType() == type) + { + return element; + } + Visual foundElement = null; + if (element is FrameworkElement) + { + (element as FrameworkElement).ApplyTemplate(); + } + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) + { + Visual visual = VisualTreeHelper.GetChild(element, i) as Visual; + foundElement = GetDescendantByType(visual, type); + if (foundElement != null) + { + break; + } + } + return foundElement; + } + + #endregion scroll_gif_logic + + /// + /// Determine video resolution + /// + /// + /// x = width, y = heigh + public static Size GetVideoSize(string videoFullPath) + { + try + { + if (File.Exists(videoFullPath)) + { + ShellFile shellFile = ShellFile.FromFilePath(videoFullPath); + + int videoWidth = (int)shellFile.Properties.System.Video.FrameWidth.Value; + int videoHeight = (int)shellFile.Properties.System.Video.FrameHeight.Value; + + return new Size(videoWidth, videoHeight); + } + } + catch(Exception) + { + return Size.Empty; + } + return Size.Empty; + } + + private async void SetWallpaperBtn_Click(object sender, RoutedEventArgs e) + { + if (wallpapersLV.SelectedIndex == -1) + return; + + var selection = (TileData)wallpapersLV.SelectedItem; + if (selection.LivelyInfo.Type == SetupDesktop.WallpaperType.app || selection.LivelyInfo.Type == SetupDesktop.WallpaperType.godot + || selection.LivelyInfo.Type == SetupDesktop.WallpaperType.unity || selection.LivelyInfo.Type == SetupDesktop.WallpaperType.unity_audio) + { + var ch = await this.ShowMessageAsync(Properties.Resources.msgExternalAppWarningTitle,Properties.Resources.msgExternalAppWarning, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + + } + } + + if(selection.LivelyInfo.Type == SetupDesktop.WallpaperType.app) + { + SetupWallpaper(selection.LivelyInfo.FileName, selection.LivelyInfo.Type, selection.LivelyInfo.Arguments); + } + else + SetupWallpaper(selection.LivelyInfo.FileName, selection.LivelyInfo.Type); + } + + private void MenuItem_SetWallpaper_Click(object sender, RoutedEventArgs e) //contextmenu + { + SetWallpaperBtn_Click(null, null); + } + + private void MenuItem_ShowOnDisk_Click(object sender, RoutedEventArgs e) + { + if (wallpapersLV.SelectedIndex == -1) + return; + + try + { + var obj = (TileData)wallpapersLV.SelectedItem; + var folderPath = System.IO.Path.GetDirectoryName(obj.LivelyInfo.FileName); + if (Directory.Exists(folderPath)) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + Arguments = folderPath, + FileName = "explorer.exe" + }; + Process.Start(startInfo); + } + } + catch (Exception e1) + { + Logger.Error("folder open error:- " + e1.ToString()); + MessageBox.Show("Failed to open folder:- " + e1.ToString(), Properties.Resources.txtLivelyErrorMsgTitle); + } + } + + /// + /// Set to true to Cancel zip creation process. + /// + private bool zipWasCanceled = false; + /// + /// Creates Lively zip file for already extracted wp's in Library. + /// + private async void MenuItem_CreateZip_Click(object sender, RoutedEventArgs e) + { + if (wallpapersLV.SelectedIndex == -1) + return; + + string savePath = ""; + SaveFileDialog saveFileDialog1 = new SaveFileDialog() + { + Title = "Select location to save the file", + Filter = "Lively/zip file|*.zip" + }; + + if (saveFileDialog1.ShowDialog() == true) + { + savePath = saveFileDialog1.FileName; + } + + if (String.IsNullOrEmpty(savePath)) + { + return; + } + + var selection = (TileData)wallpapersLV.SelectedItem; + string parentDirectory = Path.GetDirectoryName(selection.LivelyInfo.FileName); + List folderContents = new List(); + folderContents.AddRange(Directory.GetFiles(parentDirectory, "*.*", SearchOption.AllDirectories)); + + try + { + using (ZipFile zip = new ZipFile(savePath)) + { + zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression; + zip.ZipErrorAction = ZipErrorAction.Throw; + + for (int i = 0; i < folderContents.Count; i++) + { + try + { + //adding files in root directory of zip, maintaining folder structure. + zip.AddFile(folderContents[i], Path.GetDirectoryName(folderContents[i]).Replace(parentDirectory, string.Empty)); + } + catch + { + Logger.Info("zip: ignoring some files due to repeated filename."); + } + } + + zipWasCanceled = false; + progressController = await this.ShowProgressAsync(Properties.Resources.txtLivelyWaitMsgTitle, Properties.Resources.txtCreatingZip, true); + progressController.Canceled += ProgressController_Canceled; + zip.SaveProgress += Zip_SaveProgress; + await Task.Run(() => zip.Save()); + } + } + catch (Ionic.Zip.ZipException e1) + { + MessageBox.Show("File creation failure(zip):" + e1.ToString(), Properties.Resources.txtLivelyErrorMsgTitle); + Logger.Error(e1.ToString()); + } + catch (Exception e2) + { + MessageBox.Show("File creation failure:" + e2.ToString(), Properties.Resources.txtLivelyErrorMsgTitle); + Logger.Error(e2.ToString()); + } + + if (!zipWasCanceled) + { + var openDirectory = Path.GetDirectoryName(savePath); + if (Directory.Exists(openDirectory)) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + Arguments = openDirectory, + FileName = "explorer.exe" + }; + Process.Start(startInfo); + } + } + } + private async void Zip_SaveProgress(object sender, SaveProgressEventArgs e) + { + if (zipWasCanceled) { e.Cancel = true; } + + if (e.EntriesTotal != 0) + { + if (progressController != null) + { + progressController.SetProgress((float)e.EntriesSaved / (float)e.EntriesTotal); + // progressController.SetProgress(1); + } + + if (e.EntriesSaved == e.EntriesTotal && e.EntriesTotal != 0) + { + if (progressController != null) + { + await progressController.CloseAsync(); + progressController = null; + } + } + } + } + + private async void ProgressController_Canceled(object sender, EventArgs e) + { + zipWasCanceled = true; + progressController.Canceled -= ProgressController_Canceled; + await progressController.CloseAsync(); + progressController = null; + } + + private async void MenuItem_DeleteWallpaper_Click(object sender, RoutedEventArgs e) + { + if (wallpapersLV.SelectedIndex == -1) + return; + + var ch = await this.ShowMessageAsync(Properties.Resources.msgDeleteConfirmationTitle, Properties.Resources.msgDeleteConfirmation, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { AffirmativeButtonText ="Yes", NegativeButtonText ="No",DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16, AnimateShow = false, AnimateHide = false }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + + } + var selection = (TileData)wallpapersLV.SelectedItem; + //check if currently running wallpaper + if (SetupDesktop.wallpapers.FindIndex(x => x.FilePath.Equals(selection.LivelyInfo.FileName, StringComparison.OrdinalIgnoreCase) ) != -1) + { + await this.ShowMessageAsync(Properties.Resources.msgDeletionFailureTitle, Properties.Resources.msgDeletionFailure); + return; + } + + var folderPath = System.IO.Path.GetDirectoryName(selection.LivelyInfo.FileName); + if (Directory.Exists(folderPath)) + { + tileDataList.Remove(selection); + wallpapersLV.SelectedIndex = -1; //clears selectedTile info panel. + + await Task.Delay(1000); //todo:- find if gif is dealloacted & do this more elegantly. + try + { + await Task.Run(() => Directory.Delete(folderPath, true)); //thread blocking otherwise + } + catch (IOException ex1) //not throwing weird(nvrmind, I don't knw why i wrote this comment) + { + Logger.Error("IOException: failed to delete wp from library, waiting 4sec for gif to dealloac:" +ex1.ToString()); + await Task.Delay(4000); + await Task.Run(() => Directory.Delete(folderPath, true)); + } + catch (Exception ex2) + { + Logger.Error("WP folder delete error:- " + ex2.ToString()); + MessageBox.Show("Folder Delete Failure:- " + ex2.Message, Properties.Resources.txtLivelyErrorMsgTitle); + } + } + } + + #endregion wallpaper_library + + #region systray + private static System.Windows.Forms.NotifyIcon _notifyIcon; + private static bool _isExit; + + private void CreateSysTray() + { + _notifyIcon = new System.Windows.Forms.NotifyIcon(); + _notifyIcon.DoubleClick += (s, args) => ShowMainWindow(); + //_notifyIcon.Click += (s, args) => ShowMainWindow(); + //_notifyIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(System.Reflection.Assembly.GetEntryAssembly().ManifestModule.Name); + _notifyIcon.Icon = Properties.Icons.icons8_seed_of_life_96_normal; + _notifyIcon.Visible = true; + + CreateContextMenu(); + } + public static void SwitchTrayIcon(bool isPaused) + { + try + { + //don't make much sense with per-display rule in multiple display systems, so turning off. + if (!multiscreen && !_isExit) + { + if (isPaused) + { + _notifyIcon.Icon = Properties.Icons.icons8_seed_of_life_96_pause; + } + else + { + _notifyIcon.Icon = Properties.Icons.icons8_seed_of_life_96_normal; + } + } + } + catch (NullReferenceException) + { + //app closing. + } + } + + System.Windows.Forms.ToolStripMenuItem update_traybtn; + private void CreateContextMenu() + { + _notifyIcon.ContextMenuStrip = + new System.Windows.Forms.ContextMenuStrip(); + _notifyIcon.Text = Properties.Resources.txtTitlebar; + + _notifyIcon.ContextMenuStrip.Items.Add(Properties.Resources.txtContextMenuOpenLively, Properties.Icons.icon_monitor).Click += (s, e) => ShowMainWindow(); + _notifyIcon.ContextMenuStrip.Items.Add(Properties.Resources.txtContextMenuCloseAll, Properties.Icons.icon_erase).Click += (s, e) => SetupDesktop.CloseAllWallpapers(); + update_traybtn = new System.Windows.Forms.ToolStripMenuItem(Properties.Resources.txtContextMenuUpdate1, Properties.Icons.icon_update); + update_traybtn.Click += (s, e) => Process.Start("https://github.com/rocksdanister/lively"); + update_traybtn.Enabled = false; + _notifyIcon.ContextMenuStrip.Items.Add(update_traybtn); + + _notifyIcon.ContextMenuStrip.Items.Add("-"); + _notifyIcon.ContextMenuStrip.Items.Add(Properties.Resources.txtContextMenuExit, Properties.Icons.icon_close).Click += (s, e) => ExitApplication(); + } + + private int prevSelectedLibIndex = -1; + private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + if (!_isExit) + { + e.Cancel = true; + if (SaveData.config.IsFirstRun) + { + _notifyIcon.ShowBalloonTip(3000, "Lively",Properties.Resources.toolTipMinimizeMsg,ToolTipIcon.None); + + SaveData.config.IsFirstRun = false; + SaveData.SaveConfig(); + } + + prevSelectedLibIndex = wallpapersLV.SelectedIndex; + tileDataList.Clear(); + selectedTile.Clear(); + + this.Hide(); + //testing + GC.Collect(); + } + else + { + //MessageBox.Show(System.Windows.Application.Current.Windows.Count.ToString()); + SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged; + + SaveData.config.SafeShutdown = true; + SaveData.SaveConfig(); + + SetupDesktop.CloseAllWallpapers(true); + + SetupDesktop.RefreshDesktop(); + + //systraymenu dispose + _notifyIcon.Visible = false; + //_notifyIcon.Icon = null; + _notifyIcon.Icon.Dispose(); + _notifyIcon.Icon = null; + _notifyIcon.Dispose(); + } + } + + public void ExitApplication() + { + _isExit = true; + System.Windows.Application.Current.Shutdown(); + //this.Close(); // MainWindow_Closing() handles the exit actions. + } + + private void ShowMainWindow() + { + //TODO:- add error if waitin to kill browser process, onclose runnin and user call this fn. + if (this.IsVisible) + { + if (this.WindowState == WindowState.Minimized) + { + this.WindowState = WindowState.Normal; + } + this.Activate(); + } + else + { + UpdateWallpaperLibrary(); + this.Show(); + this.Activate(); + } + } + + #endregion systray + + #region wp_setup + /// + /// Sets up wallpaper, shows dialog to select display if multiple displays are detected. + /// + /// wallpaper location. + /// wallpaper category. + private async void SetupWallpaper(string path, SetupDesktop.WallpaperType type, string args = null) + { + if(_isRestoringWallpapers) + { + MessageBox.Show(Properties.Resources.msgRestoringInProgress, Properties.Resources.txtLivelyWaitMsgTitle); + return; + } + + + SaveData.WallpaperLayout tmpData = new SaveData.WallpaperLayout(); + tmpData.Arguments = args; + if (type == SetupDesktop.WallpaperType.app && args == null) + { + var arg = await this.ShowInputAsync(Properties.Resources.msgAppCommandLineArgsTitle, Properties.Resources.msgAppCommandLineArgs, new MetroDialogSettings() { DialogTitleFontSize = 16, DialogMessageFontSize = 14}); + if (arg == null) //cancel btn or ESC key + return; + + if (!string.IsNullOrWhiteSpace(arg)) + tmpData.Arguments = arg; + } + else if(type == SetupDesktop.WallpaperType.web || type == SetupDesktop.WallpaperType.url || type == SetupDesktop.WallpaperType.web_audio) + { + if(highContrastFix) + { + Logger.Info("behind-icon mode, skipping cef."); + System.Windows.MessageBox.Show("Web wallpaper is not available in High Contrast mode workaround, coming soon.", "Lively: Error, High Contrast Mode"); + return; + } + + if (!File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "\\external\\cef\\LivelyCefSharp.exe"))) + { + Logger.Info("cefsharp is missing, skipping wallpaper."); + System.Windows.MessageBox.Show(Properties.Resources.msgWebBrowserMissing, Properties.Resources.txtLivelyErrorMsgTitle); + return; + } + } + + if (multiscreen && SaveData.config.WallpaperArrangement == WallpaperArrangement.per) + { /* + if(type == SetupDesktop.WallpaperType.bizhawk) + { + System.Windows.MessageBox.Show("Currently Bizhawk is not supported in multiple monitor configuration.", "Lively: Hold up"); + return; + } + */ + //monitor select dialog + DisplaySelectWindow displaySelectWindow = new DisplaySelectWindow + { + Owner = this, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; + displaySelectWindow.ShowDialog(); + + Debug.WriteLine("selecterd display:- " + DisplaySelectWindow.selectedDisplay); + + if (DisplaySelectWindow.selectedDisplay == null) //none + { + return; + } + else + { + tmpData.FilePath = path; + tmpData.Type = type; + + tmpData.DeviceName = DisplaySelectWindow.selectedDisplay; + + //remove prev if new wallpaper on same screen + int i = 0; + if ((i = SetupDesktop.wallpapers.FindIndex(x => x.DeviceName == tmpData.DeviceName)) != -1) + { + SetupDesktop.CloseWallpaper(SetupDesktop.wallpapers[i].DeviceName); + } + } + } + else //single screen + { + tmpData.FilePath = path; + tmpData.Type = type; + //tmpData.displayID = 0; + tmpData.DeviceName = Screen.PrimaryScreen.DeviceName; + + SetupDesktop.CloseAllWallpapers(); //close previous wallpapers. + } + + //progressbar + if (type == SetupDesktop.WallpaperType.app || type == SetupDesktop.WallpaperType.unity || type == SetupDesktop.WallpaperType.bizhawk || type == SetupDesktop.WallpaperType.godot + || type == SetupDesktop.WallpaperType.unity_audio) + { + progressController = await this.ShowProgressAsync(Properties.Resources.txtLivelyWaitMsgTitle, Properties.Resources.msgLoadingAppWallpaper, true, + new MetroDialogSettings() { AnimateHide = true, AnimateShow = true }); + //progressController.Canceled += ProgressController_Canceled; + } + + Logger.Info("Setting up wallpaper:-" + tmpData.FilePath); + SetupDesktop.SetWallpaper(tmpData); //set wallpaper + float progress = 0; + while (SetupDesktop.IsProcessWaitDone() == 0) + { + if (progress > 1) + progress = 1; + progressController.SetProgress(progress); + progress += 100f/SetupDesktop.wallpaperWaitTime; //~approximation + await Task.Delay(100); + + if (progressController.IsCanceled) + { + //cancelled = true; + SetupDesktop.TaskProcessWaitCancel(); + break; + } + } + if (progressController != null) + { + progressController.SetProgress(1); + //progressController.Canceled -= ProgressController_Canceled; + await progressController.CloseAsync(); + progressController = null; + } + } + /* + private async void ProgressController_Canceled(object sender, EventArgs e) + { + SetupDesktop.TaskProcessWaitCancel(); + await progressController.CloseAsync(); + progressController = null; + } + */ + + /// + /// Restores saved list of wallpapers. (no dialog asking user for input etc compared to setupdesktop()); + /// + /// + private async void RestoreWallpaper(List layoutList) + { + float progress = 0; + int loadedWallpaperCount = 0; + _isRestoringWallpapers = true; + //cant show dialog when app started with window minimized. + if (this.IsVisible) + { + try + { + progressController = await this.ShowProgressAsync(Properties.Resources.txtLivelyWaitMsgTitle, Properties.Resources.msgRestoringPrevWallpapers, false, + new MetroDialogSettings() { AnimateHide = true, AnimateShow = false }); + } + catch(Exception) //just in case. + { + progressController = null; + } + } + + foreach (var layout in layoutList) + { + if (layout.Type == SetupDesktop.WallpaperType.web || layout.Type == SetupDesktop.WallpaperType.url || layout.Type == SetupDesktop.WallpaperType.web_audio) + { + if (highContrastFix) + { + Logger.Info("behind-icon mode, skipping cef."); + System.Windows.MessageBox.Show("Web wallpaper is not available in High Contrast mode workaround, coming soon.", Properties.Resources.txtLivelyErrorMsgTitle); + continue; + } + + if (!File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "\\external\\cef\\LivelyCefSharp.exe"))) + { + Logger.Info("cefsharp is missing, skipping wallpaper."); + System.Windows.MessageBox.Show(Properties.Resources.msgWebBrowserMissing, Properties.Resources.txtLivelyErrorMsgTitle); + continue; + } + } + + SaveData.WallpaperLayout tmpData = new SaveData.WallpaperLayout(); + if (multiscreen && SaveData.config.WallpaperArrangement == WallpaperArrangement.per) + { + /* + if (layout.Type == SetupDesktop.WallpaperType.bizhawk) + { + System.Windows.MessageBox.Show("Currently Bizhawk is not supported in multiple monitor configuration.", "hold up"); + continue; + } + */ + + tmpData.FilePath = layout.FilePath; + tmpData.Type = layout.Type; + tmpData.Arguments = layout.Arguments; + + tmpData.DeviceName = layout.DeviceName; + + //remove prev if new wallpaper on same screen, in restore case this can happen if savefile is messed up or user just messed with it? + int i = 0; + if ((i = SetupDesktop.wallpapers.FindIndex(x => x.DeviceName == tmpData.DeviceName)) != -1) + { + SetupDesktop.CloseWallpaper(SetupDesktop.wallpapers[i].DeviceName); + } + } + else //single screen + { + tmpData.FilePath = layout.FilePath; + tmpData.Type = layout.Type; + tmpData.DeviceName = Screen.PrimaryScreen.DeviceName; + tmpData.Arguments = layout.Arguments; + + SetupDesktop.CloseAllWallpapers(); //close previous wallpapers. + } + + //SetupDesktop.wallpapers.Add(tmpData); + while (SetupDesktop.IsProcessWaitDone() == 0) + { + Debug.WriteLine("waiting waiting"); + await Task.Delay(100); + } + + Logger.Info("Setting up wallpaper:-" + tmpData.FilePath); + SetupDesktop.SetWallpaper(tmpData); //set wallpaper + loadedWallpaperCount++; + + if (progressController != null) + { + if (progress > 1) + progress = 1; + progressController.SetProgress(progress); + progress += (float)loadedWallpaperCount / (float)layoutList.Count; + } + } + + _isRestoringWallpapers = false; + if (progressController != null) + { + progressController.SetProgress(1); + //progressController.Canceled -= ProgressController_Canceled; + await progressController.CloseAsync(); + progressController = null; + } + layoutList.Clear(); + layoutList = null; + } + #endregion wp_setup + + #region wallpaper_installer + private async void WallpaperInstaller(string zipLocation) + { + string extractPath = null; + extractPath = AppDomain.CurrentDomain.BaseDirectory + "\\wallpapers\\" + Path.GetRandomFileName(); + + //Todo: implement CheckZip() {thread blocking}, Error will be thrown during extractiong, which is being handled so not a big deal. + //Ionic.Zip.ZipFile.CheckZip(zipLocation) + + if (Directory.Exists(extractPath)) //likely impossible. + { + Debug.WriteLine("same foldername with files, should be impossible... retrying with new random foldername"); + extractPath = AppDomain.CurrentDomain.BaseDirectory + "\\wallpapers\\" + Path.GetRandomFileName(); + + if (Directory.Exists(extractPath)) + { + Logger.Error("same folderpath name, stopping wallpaper installation"); + return; + } + } + Directory.CreateDirectory(extractPath); + + string zipPath = zipLocation; + // Normalizes the path. + extractPath = Path.GetFullPath(extractPath); + + // Ensures that the last character on the extraction path + // is the directory separator char. + // Without this, a malicious zip file could try to traverse outside of the expected + // extraction path. + if (!extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + extractPath += Path.DirectorySeparatorChar; + + try + { + // Specifying Console.Out here causes diagnostic msgs to be sent to the Console + // In a WinForms or WPF or Web app, you could specify nothing, or an alternate + // TextWriter to capture diagnostic messages. + + //var options = new ReadOptions { StatusMessageWriter = System.Console.Out }; + using (ZipFile zip = ZipFile.Read(zipPath))//, options)) + { + zip.ZipErrorAction = ZipErrorAction.Throw; //todo:- test with a corrupted zip that starts extracting. + //zip.ZipError += Zip_ZipError; + // This call to ExtractAll() assumes: + // - none of the entries are password-protected. + // - want to extract all entries to current working directory + // - none of the files in the zip already exist in the directory; + // if they do, the method will throw. + if (zip.ContainsEntry("LivelyInfo.json")) //outer directory only. + { + progressController = await this.ShowProgressAsync(Properties.Resources.txtLivelyWaitMsgTitle, Properties.Resources.txtLabel39, true); + zip.ExtractProgress += Zip_ExtractProgress; + //zip.ExtractAll(extractPath); + await Task.Run(() => zip.ExtractAll(extractPath)); + + } + else + { + try + { + Directory.Delete(extractPath, true); + } + catch (Exception) + { + Logger.Error("Extractionpath delete error"); + //Debug.WriteLine("extractionpath deletion error"); + } + + await this.ShowMessageAsync("Error", "Not Lively wallpaper file.\nCheck out wiki page on how to create proper wallpaper file", MessageDialogStyle.Affirmative, + new MetroDialogSettings() { DialogTitleFontSize = 25, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + return; + } + } + } + catch (Ionic.Zip.ZipException e) + { + try + { + Directory.Delete(extractPath, true); + } + catch (Exception) + { + Logger.Error("Extractionpath delete error"); + Debug.WriteLine("extractionpath deletion error"); + } + + if (progressController != null) + { + await progressController.CloseAsync(); + progressController = null; + } + + Logger.Error(e.ToString()); + MessageBox.Show(Properties.Resources.msgDamangedLivelyFile, Properties.Resources.txtLivelyErrorMsgTitle); + return; + } + catch (Exception ex) + { + try + { + Directory.Delete(extractPath, true); + } + catch (Exception) + { + Logger.Error("Extractionpath delete error"); + Debug.WriteLine(" extractiontpath deletion error"); + } + + //System.Console.Error.WriteLine("zip-exception: " + ex.Message); + if (progressController != null) + { + await progressController.CloseAsync(); + progressController = null; + } + + Logger.Error(ex.ToString()); + MessageBox.Show(ex.Message, "Zip Error"); + return; + } + + UpdateWallpaperLibrary(); + foreach (var item in tileDataList) + { + if(Path.GetDirectoryName(item.LivelyInfo.FileName).Equals(Path.GetDirectoryName(extractPath), StringComparison.Ordinal)) + { + wallpapersLV.SelectedItem = item; + break; + } + } + + + //add new wallpaper to library + //var dir = Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory + "\\wallpapers"); + /* + if (File.Exists(extractPath + "\\LivelyInfo.json")) + { + //load it into SaveData.info + if (SaveData.LoadWallpaperMetaData(extractPath)) + { + SaveData.info.FileName = extractPath + "\\" + SaveData.info.FileName; + SaveData.info.Preview = extractPath + "\\" + SaveData.info.Preview; + SaveData.info.Thumbnail = extractPath + "\\" + SaveData.info.Thumbnail; + Debug.WriteLine(SaveData.info.FileName + " " + SaveData.info.Type); + + tileDataList.Add(new TileData(SaveData.info)); + textBoxLibrarySearch.Text = null; + wallpapersLV.SelectedIndex = wallpapersLV.Items.Count - 1; + } + else + { + MessageBox.Show("Damaged wallpaper file, redownload the file & try again.", "Zip Error"); + try + { + Directory.Delete(extractPath, true); + } + catch (Exception) + { + Logger.Error("Extractionpath delete error"); + Debug.WriteLine(" extractiontpath deletion error"); + } + } + } + */ + } + + public void Button_Click_InstallWallpaper(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog() + { + Title = "Open Lively Wallpaper File", + Filter = "Lively Wallpaper (*.zip) |*.zip" + }; + + if (openFileDialog1.ShowDialog() == true) + { + if (tabControl1.SelectedIndex != 0) //switch to library tab.) + tabControl1.SelectedIndex = 0; + WallpaperInstaller(openFileDialog1.FileName); + } + } + + private async void Zip_ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if (e.EntriesTotal != 0) + { + if (progressController != null) + { + progressController.SetProgress((float)e.EntriesExtracted / (float)e.EntriesTotal); + // progressController.SetProgress(1); + } + + Debug.WriteLine((float)e.EntriesExtracted / (float)e.EntriesTotal); + } + + if(e.EntriesExtracted == e.EntriesTotal && e.EntriesTotal != 0) + { + if (progressController != null) + { + await progressController.CloseAsync(); + progressController = null; + } + } + } + + /// + /// Calculates SHA256 hash of file. + /// + /// path to the file. + string CalculateFileCheckSum(string filepath) + { + using (SHA256 sha256 = SHA256.Create()) + { + using (var stream = File.OpenRead(filepath)) + { + var hash = sha256.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } + + #endregion wallpaper_installer + + #region tile_events + + private void Tile_Video_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Filter = "All Videos Files |*.dat; *.wmv; *.3g2; *.3gp; *.3gp2; *.3gpp; *.amv; *.asf; *.avi; *.bin; *.cue; *.divx; *.dv; *.flv; *.gxf; *.iso; *.m1v; *.m2v; *.m2t; *.m2ts; *.m4v; " + + " *.mkv; *.mov; *.mp2; *.mp2v; *.mp4; *.mp4v; *.mpa; *.mpe; *.mpeg; *.mpeg1; *.mpeg2; *.mpeg4; *.mpg; *.mpv2; *.mts; *.nsv; *.nuv; *.ogg; *.ogm; *.ogv; *.ogx; *.ps; *.rec; *.rm; *.rmvb; *.tod; *.ts; *.tts; *.vob; *.vro; *.webm" + }; + + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.video); + } + + } + + private void Tile_GIF_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog() + { + Filter = "Animated GIF (*.gif) |*.gif" + }; + + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.gif); + } + + } + + private async void Tile_Unity_Click(object sender, RoutedEventArgs e) + { + if (SaveData.config.WarningUnity == 0) + { + var ch = await this.ShowMessageAsync(Properties.Resources.msgExternalAppWarningTitle, Properties.Resources.msgExternalAppWarning, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + SaveData.config.WarningUnity++; + SaveData.SaveConfig(); + } + } + OpenFileDialog openFileDialog1 = new OpenFileDialog() + { + Title = "Select Unity game", + Filter = "Executable |*.exe" + }; + + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.unity); + } + } + + private async void Tile_UNITY_AUDIO_Click(object sender, RoutedEventArgs e) + { + if (SaveData.config.WarningUnity == 0) + { + var ch = await this.ShowMessageAsync(Properties.Resources.msgExternalAppWarningTitle, Properties.Resources.msgExternalAppWarning, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + SaveData.config.WarningUnity++; + SaveData.SaveConfig(); + } + } + + OpenFileDialog openFileDialog1 = new OpenFileDialog() + { + Title = "Select Unity audio visualiser", + Filter = "Executable |*.exe" + }; + + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.unity_audio); + } + + } + + private void Tile_LIVELY_ZIP_Click(object sender, RoutedEventArgs e) + { + //tabControl1.SelectedIndex = 0; //switch to library tab. + Button_Click_InstallWallpaper(this, null); + } + + private async void Tile_Godot_Click(object sender, RoutedEventArgs e) + { + if (SaveData.config.WarningGodot == 0) + { + var ch = await this.ShowMessageAsync(Properties.Resources.msgExternalAppWarningTitle, Properties.Resources.msgExternalAppWarning, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + SaveData.config.WarningGodot++; + SaveData.SaveConfig(); + } + } + + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Title = "Select Godot game", + Filter = "Executable |*.exe" + }; + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.godot); + } + } + + private async void Tile_BizHawk_Click(object sender, RoutedEventArgs e) + { + MessageBox.Show(Properties.Resources.txtComingSoon); + return; + + var dir = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + @"\external\bizhawk", "EmuHawk.exe", SearchOption.AllDirectories); //might be slow, only check top? + if (dir.Length != 0) + { + SetupWallpaper(dir[0], SetupDesktop.WallpaperType.bizhawk); + } + else if (File.Exists(SaveData.config.BizHawkPath)) + { + SetupWallpaper(SaveData.config.BizHawkPath, SetupDesktop.WallpaperType.bizhawk); + } + else + { + var ch = await this.ShowMessageAsync("Bizhawk Not Found", "Download BizHawk Emulator:\nhttps://github.com/TASVideos/BizHawk\nExtract & copy contents to:\nexternal\\bizhawk folder" + + "\n\n\t\tOR\n\nClick Browse & select EmuHawk.exe", MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { AffirmativeButtonText = "Ok", NegativeButtonText = "Browse", DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Theme, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Affirmative) //Ok + { + return; + } + else if (ch == MessageDialogResult.Negative) //Browse + { + + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Title = "Select EmuHawk.exe", + FileName = "EmuHawk.exe" + }; + // openFileDialog1.Filter = formatsVideo; + if (openFileDialog1.ShowDialog() == true) + { + SaveData.config.BizHawkPath = openFileDialog1.FileName; + SaveData.SaveConfig(); + + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.bizhawk); + } + } + } + + } + + private async void Tile_Other_Click(object sender, RoutedEventArgs e) + { + var ch = await this.ShowMessageAsync(Properties.Resources.txtLivelyWaitMsgTitle, Properties.Resources.txtLivelyAppWarning, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + + } + + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Filter = "Application (*.exe) |*.exe" + }; + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.app); + } + } + + private void Tile_HTML_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Filter = "Web Page (*.html) |*.html" + }; + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.web); + } + } + + + private void Tile_HTML_AUDIO_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Filter = "Web Page with visualiser (*.html) |*.html" + }; + if (openFileDialog1.ShowDialog() == true) + { + SetupWallpaper(openFileDialog1.FileName, SetupDesktop.WallpaperType.web_audio); + } + } + + private async void Tile_URL_Click(object sender, RoutedEventArgs e) + { + if (SaveData.config.WarningURL == 0) + { + var ch = await this.ShowMessageAsync(Properties.Resources.msgUrlWarningTitle, Properties.Resources.msgUrlWarning, MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + SaveData.config.WarningURL++; + SaveData.SaveConfig(); + } + } + + var url = await this.ShowInputAsync(Properties.Resources.msgUrlLoadTitle, Properties.Resources.msgUrlLoad, new MetroDialogSettings() { DialogTitleFontSize = 16, DialogMessageFontSize = 14, DefaultText = SaveData.config.DefaultURL }); + if (string.IsNullOrEmpty(url)) + return; + + SaveData.config.DefaultURL = url; + SaveData.SaveConfig(); + SetupWallpaper(url, SetupDesktop.WallpaperType.url); + } + + #endregion tile_events + + #region ui_events + private void SubcribeUI() + { + //Subscribe to events here to prevent triggering calls during RestoreSaveSettings() todo: rewrite with data binding instead(Enum type need some extra code for convertion, skipping for now). + comboBoxVideoPlayer.SelectionChanged += ComboBoxVideoPlayer_SelectionChanged; + comboBoxGIFPlayer.SelectionChanged += ComboBoxGIFPlayer_SelectionChanged; + comboBoxFocusedPerf.SelectionChanged += ComboBoxFocusedPerf_SelectionChanged; + comboBoxFullscreenPerf.SelectionChanged += ComboBoxFullscreenPerf_SelectionChanged; + comboBoxMonitorPauseRule.SelectionChanged += ComboBoxMonitorPauseRule_SelectionChanged; + transparencyToggle.IsCheckedChanged += TransparencyToggle_IsCheckedChanged; + StartupToggle.IsCheckedChanged += StartupToggle_IsCheckedChanged; + videoMuteToggle.IsCheckedChanged += VideoMuteToggle_IsCheckedChanged; + comboBoxFullscreenPerf.SelectionChanged += ComboBoxFullscreenPerf_SelectionChanged1; + cefAudioInMuteToggle.IsCheckedChanged += CefAudioInMuteToggle_IsCheckedChanged; + comboBoxPauseAlgorithm.SelectionChanged += ComboBoxPauseAlgorithm_SelectionChanged; + TileAnimateToggle.IsCheckedChanged += TileAnimateToggle_IsCheckedChanged; + fpsUIToggle.IsCheckedChanged += FpsUIToggle_IsCheckedChanged; + disableUIHWToggle.IsCheckedChanged += DisableUIHWToggle_IsCheckedChanged; + comboBoxLanguage.SelectionChanged += ComboBoxLanguage_SelectionChanged; + } + private void RestoreMenuSettings() + { + if (SaveData.config.AppTransparency) + { + this.Opacity = 0.9f; + transparencyToggle.IsChecked = true; + } + else + { + this.Opacity = 1.0f; + transparencyToggle.IsChecked = false; + } + + TileAnimateToggle.IsChecked = SaveData.config.LiveTile; + fpsUIToggle.IsChecked = SaveData.config.Ui120FPS; + disableUIHWToggle.IsChecked = SaveData.config.UiDisableHW; + + try + { + comboBoxPauseAlgorithm.SelectedIndex = (int)SaveData.config.ProcessMonitorAlgorithm; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.ProcessMonitorAlgorithm = SaveData.ProcessMonitorAlgorithm.foreground; + SaveData.SaveConfig(); + comboBoxPauseAlgorithm.SelectedIndex = (int)SaveData.config.ProcessMonitorAlgorithm; + } + + + cefAudioInMuteToggle.IsChecked = !SaveData.config.MuteCefAudioIn; + if (!SaveData.config.MuteCefAudioIn) + web_audio_WarningText.Visibility = Visibility.Hidden; + else + web_audio_WarningText.Visibility = Visibility.Visible; + + videoMuteToggle.IsChecked = !SaveData.config.MuteVideo; + + // performance ui + + try + { + comboBoxFullscreenPerf.SelectedIndex = (int)SaveData.config.AppFullscreenPause; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.AppFullscreenPause = SaveData.AppRulesEnum.pause; + SaveData.SaveConfig(); + comboBoxFullscreenPerf.SelectedIndex = (int)SaveData.config.AppFullscreenPause; + } + + try + { + comboBoxFocusedPerf.SelectedIndex = (int)SaveData.config.AppFocusPause; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.AppFocusPause = SaveData.AppRulesEnum.ignore; + SaveData.SaveConfig(); + comboBoxFocusedPerf.SelectedIndex = (int)SaveData.config.AppFocusPause; + } + + try + { + comboBoxFullscreenPerf.SelectedIndex = (int)SaveData.config.AppFullscreenPause; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.AppFullscreenPause = SaveData.AppRulesEnum.pause; + SaveData.SaveConfig(); + comboBoxFullscreenPerf.SelectedIndex = (int)SaveData.config.AppFullscreenPause; + } + + try + { + comboBoxMonitorPauseRule.SelectedIndex = (int)SaveData.config.DisplayPauseSettings; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.DisplayPauseSettings = SaveData.DisplayPauseEnum.perdisplay; + SaveData.SaveConfig(); + comboBoxMonitorPauseRule.SelectedIndex = (int)SaveData.config.DisplayPauseSettings; + } + + try + { + comboBoxVideoPlayer.SelectedIndex = (int)SaveData.config.VidPlayer; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.VidPlayer = SaveData.VideoPlayer.windowsmp; + SaveData.SaveConfig(); + comboBoxVideoPlayer.SelectedIndex = (int)SaveData.config.VidPlayer; + } + + try + { + comboBoxGIFPlayer.SelectedIndex = (int)SaveData.config.GifPlayer; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.VidPlayer = (int)SaveData.GIFPlayer.xaml; + SaveData.SaveConfig(); + comboBoxGIFPlayer.SelectedIndex = (int)SaveData.config.GifPlayer; + } + StartupToggle.IsChecked = SaveData.config.Startup; + + #region shit + //todo:- do it more elegantly. + foreach (var item in SaveData.supportedLanguages) + { + comboBoxLanguage.Items.Add(item.Language); + } + + bool detectedLang = false; + for (int i = 0; i < SaveData.supportedLanguages.Length; i++) + { + if (Array.Exists(SaveData.supportedLanguages[i].Codes, x => x.Equals(SaveData.config.Language, StringComparison.OrdinalIgnoreCase))) + { + comboBoxLanguage.SelectedIndex = i; + detectedLang = true; + break; + } + } + if (!detectedLang) + { + comboBoxLanguage.SelectedIndex = 0; //en-US + } + + #endregion shit + + } + + private void ComboBoxPauseAlgorithm_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (comboBoxPauseAlgorithm.SelectedIndex == 1) + { + if (multiscreen) + { + comboBoxPauseAlgorithm.SelectedIndex = 0; + MessageBox.Show("Currently this algorithm is incomplete in multiple display systems, disabling."); + return; + } + } + + SaveData.config.ProcessMonitorAlgorithm = (SaveData.ProcessMonitorAlgorithm)comboBoxPauseAlgorithm.SelectedIndex; + SaveData.SaveConfig(); + } + + private void CefAudioInMuteToggle_IsCheckedChanged(object sender, EventArgs e) + { + + SaveData.config.MuteCefAudioIn = !cefAudioInMuteToggle.IsChecked.Value; + SaveData.SaveConfig(); + + if (!SaveData.config.MuteCefAudioIn) + web_audio_WarningText.Visibility = Visibility.Hidden; + else + web_audio_WarningText.Visibility = Visibility.Visible; + } + + private void ComboBoxFullscreenPerf_SelectionChanged1(object sender, SelectionChangedEventArgs e) + { + SaveData.config.AppFullscreenPause = (SaveData.AppRulesEnum)comboBoxFullscreenPerf.SelectedIndex; + SaveData.SaveConfig(); + } + + private void VideoMuteToggle_IsCheckedChanged(object sender, EventArgs e) + { + SaveData.config.MuteVideo = !videoMuteToggle.IsChecked.Value; + SaveData.SaveConfig(); + } + + private void ComboBoxMonitorPauseRule_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + SaveData.config.DisplayPauseSettings = (SaveData.DisplayPauseEnum)comboBoxMonitorPauseRule.SelectedIndex; + try + { + comboBoxMonitorPauseRule.SelectedIndex = (int)SaveData.config.DisplayPauseSettings; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.DisplayPauseSettings = SaveData.DisplayPauseEnum.perdisplay; + comboBoxMonitorPauseRule.SelectedIndex = (int)SaveData.config.DisplayPauseSettings; + } + SaveData.SaveConfig(); + } + + private void ComboBoxFullscreenPerf_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + SaveData.config.AppFullscreenPause = (SaveData.AppRulesEnum)comboBoxFullscreenPerf.SelectedIndex; + try + { + comboBoxFullscreenPerf.SelectedIndex = (int)SaveData.config.AppFullscreenPause; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.AppFullscreenPause = SaveData.AppRulesEnum.pause; + comboBoxFullscreenPerf.SelectedIndex = (int)SaveData.config.AppFullscreenPause; + } + SaveData.SaveConfig(); + } + + private void ComboBoxFocusedPerf_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + SaveData.config.AppFocusPause = (SaveData.AppRulesEnum)comboBoxFocusedPerf.SelectedIndex; + try + { + comboBoxFocusedPerf.SelectedIndex = (int)SaveData.config.AppFocusPause; + } + catch (ArgumentOutOfRangeException) + { + SaveData.config.AppFocusPause = SaveData.AppRulesEnum.ignore; + comboBoxFocusedPerf.SelectedIndex = (int)SaveData.config.AppFocusPause; + } + SaveData.SaveConfig(); + } + + private void TransparencyToggle_IsCheckedChanged(object sender, EventArgs e) + { + if (transparencyToggle.IsChecked == true) + { + this.Opacity = 0.9f; + SaveData.config.AppTransparency = true; + } + else + { + this.Opacity = 1.0f; + SaveData.config.AppTransparency = false; + } + SaveData.SaveConfig(); + } + + + private void TileAnimateToggle_IsCheckedChanged(object sender, EventArgs e) + { + if (TileAnimateToggle.IsChecked == true) + { + SaveData.config.LiveTile = true; + foreach (var item in tileDataList) + { + item.Img = null; + } + InitializeTilePreviewGifs(); //loads first 15gifs. into TilePreview + } + else + { + SaveData.config.LiveTile = false; + foreach (var item in tileDataList) + { + item.Img = item.LoadImage(item.LivelyInfo.Thumbnail); + item.TilePreview = null; + } + } + + textBoxLibrarySearch.Text = null; + ScrollViewer scrollViewer = GetDescendantByType(wallpapersLV, typeof(ScrollViewer)) as ScrollViewer; + if (scrollViewer != null) + { + scrollViewer.ScrollToVerticalOffset(0); + } + wallpapersLV.Items.Refresh(); //force redraw: not refreshing everything, even with INotifyPropertyChanged. + SaveData.SaveConfig(); + } + + public void Button_Click_HowTo(object sender, RoutedEventArgs e) + { + //Process.Start("https://github.com/rocksdanister/lively/wiki"); + HelpWindow w = new HelpWindow + { + Owner = this, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; + w.ShowDialog(); + } + + /// + /// Display layout panel show. + /// + private void Image_Display_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + + DisplayLayoutWindow displayWindow = new DisplayLayoutWindow(this) + { + Owner = Window.GetWindow(this) + }; + displayWindow.ShowDialog(); + displayWindow.Close(); + this.Activate(); + //Debug.WriteLine("retured val:- " + DisplayLayoutWindow.index); + } + + /// + /// Videoplayer change, restarts currently playing wp's to newly selected system. + /// + /// + /// + private void ComboBoxVideoPlayer_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + SaveData.config.VidPlayer = (SaveData.VideoPlayer)comboBoxVideoPlayer.SelectedIndex; + SaveData.SaveConfig(); + + var result = SetupDesktop.wallpapers.FindAll(x => x.Type == SetupDesktop.WallpaperType.video); + SetupDesktop.CloseAllWallpapers(SetupDesktop.WallpaperType.video); + //SetupDesktop.wallpapers.RemoveAll(x => x.type == SetupDesktop.WallpaperType.video); + + //no video wp's currently running to restore; ignore. + if (result == null) + return; + else + RestoreWallpaper(result); + } + + /// + /// Gif player change, restarts currently playing wp's to newly selected system. + /// + /// + /// + private void ComboBoxGIFPlayer_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + /* + if (setup == null) + return; + */ + SaveData.config.GifPlayer = (SaveData.GIFPlayer)comboBoxGIFPlayer.SelectedIndex; + SaveData.SaveConfig(); + + var result = SetupDesktop.wallpapers.FindAll(x => x.Type == SetupDesktop.WallpaperType.gif); + SetupDesktop.CloseAllWallpapers(SetupDesktop.WallpaperType.gif); + + //no gif wp's currently running to restore; ignore. + if (result == null) + return; + else + RestoreWallpaper(result); + } + + private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) + { + Process.Start(e.Uri.AbsoluteUri); + } + + private void Hyperlink_SupportPage(object sender, RoutedEventArgs e) + { + Process.Start(@"https://ko-fi.com/rocksdanister"); + } + + private void Button_Click_CreateWallpaper(object sender, RoutedEventArgs e) + { + CreateWallpaper obj = new CreateWallpaper + { + Owner = this, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; + obj.ShowDialog(); + } + + /// + /// Shows warning msg with link before proceeding to load hyperlink. + /// + /// + /// + private async void Hyperlink_RequestNavigate_Warning(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) + { + var ch = await this.ShowMessageAsync(Properties.Resources.msgLoadExternalLinkTitle, Properties.Resources.msgLoadExternalLink + "\n" + e.Uri.ToString(), MessageDialogStyle.AffirmativeAndNegative, + new MetroDialogSettings() { DialogTitleFontSize = 18, ColorScheme = MetroDialogColorScheme.Inverted, DialogMessageFontSize = 16 }); + + if (ch == MessageDialogResult.Negative) + return; + else if (ch == MessageDialogResult.Affirmative) + { + + } + + Process.Start(e.Uri.AbsoluteUri); + } + + /// + /// Drag and Drop wallpaper. + /// + /// + /// + private void MetroWindow_Drop(object sender, System.Windows.DragEventArgs e) + { + if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop)) + { + string[] droppedFiles = e.Data.GetData(System.Windows.DataFormats.FileDrop, true) as string[]; + + if ((null == droppedFiles) || (!droppedFiles.Any())) { return; } + + Logger.Info("Dropped File, Selecting first file:- " + droppedFiles[0]); + + if (String.IsNullOrWhiteSpace(Path.GetExtension(droppedFiles[0]))) + return; + + if (Path.GetExtension(droppedFiles[0]).Equals(".gif", StringComparison.OrdinalIgnoreCase)) + SetupWallpaper(droppedFiles[0], SetupDesktop.WallpaperType.gif); + else if (Path.GetExtension(droppedFiles[0]).Equals(".html", StringComparison.OrdinalIgnoreCase)) + SetupWallpaper(droppedFiles[0], SetupDesktop.WallpaperType.web); + else if (Path.GetExtension(droppedFiles[0]).Equals(".zip", StringComparison.OrdinalIgnoreCase)) + { + tabControl1.SelectedIndex = 0; //switch to library tab. + WallpaperInstaller(droppedFiles[0]); + } + else if (IsVideoFile(droppedFiles[0])) + SetupWallpaper(droppedFiles[0], SetupDesktop.WallpaperType.video); + else + { + if (this.IsVisible) + this.Activate(); //bugfix. + MessageBox.Show(Properties.Resources.msgDragDropOtherFormats +"\n\n" + droppedFiles[0], Properties.Resources.msgDragDropOtherFormatsTitle); + } + + } + else if(e.Data.GetDataPresent(System.Windows.DataFormats.Text)) + { + string droppedText = (string)e.Data.GetData(System.Windows.DataFormats.Text, true); + Logger.Info("Dropped Text:- " + droppedText); + if ( (String.IsNullOrWhiteSpace(droppedText)) ) + { + return; + } + SetupWallpaper(droppedText, SetupDesktop.WallpaperType.url); + } + } + + public readonly static string[] formatsVideo = { ".dat", ".wmv", ".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".avi", ".bin", ".cue", ".divx", ".dv", ".flv", ".gxf", ".iso", ".m1v", ".m2v", ".m2t", ".m2ts", ".m4v", + ".mkv", ".mov", ".mp2", ".mp2v", ".mp4", ".mp4v", ".mpa", ".mpe", ".mpeg", ".mpeg1", ".mpeg2", ".mpeg4", ".mpg", ".mpv2", ".mts", ".nsv", ".nuv", ".ogg", ".ogm", ".ogv", ".ogx", ".ps", ".rec", ".rm", + ".rmvb", ".tod", ".ts", ".tts", ".vob", ".vro", ".webm" }; + static bool IsVideoFile(string path) + { + if (formatsVideo.Contains(Path.GetExtension(path), StringComparer.OrdinalIgnoreCase)) + { + return true; + } + return false; + } + + private void Button_AppRule_Click(object sender, RoutedEventArgs e) + { + ApplicationRuleDialogWindow w = new ApplicationRuleDialogWindow + { + WindowStartupLocation = WindowStartupLocation.CenterOwner, + Owner = this + }; + w.ShowDialog(); + } + + + private void DisableUIHWToggle_IsCheckedChanged(object sender, EventArgs e) + { + if (disableUIHWToggle.IsChecked == true) + SaveData.config.UiDisableHW = true; + else + SaveData.config.UiDisableHW = false; + + SaveData.SaveConfig(); + } + + private void FpsUIToggle_IsCheckedChanged(object sender, EventArgs e) + { + if (fpsUIToggle.IsChecked == true) + SaveData.config.Ui120FPS = true; + else + SaveData.config.Ui120FPS = false; + + SaveData.SaveConfig(); + } + private void ComboBoxLanguage_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (comboBoxLanguage.SelectedIndex == -1) + return; + //todo:- do it more elegantly. + SaveData.config.Language = SaveData.supportedLanguages[comboBoxLanguage.SelectedIndex].Codes[0]; + SaveData.SaveConfig(); + + + //Need more testing, mutex(for single instance of lively) release might not be quick enough. + _isExit = true; + SaveData.config.IsRestart = true; + SaveData.SaveConfig(); + System.Diagnostics.Process.Start(System.Windows.Application.ResourceAssembly.Location); + System.Windows.Application.Current.Shutdown(); + + } + + public static void RestartLively() + { + //Need more testing, mutex(for single instance of lively) release might not be quick enough. + _isExit = true; + System.Diagnostics.Process.Start(System.Windows.Application.ResourceAssembly.Location); + System.Windows.Application.Current.Shutdown(); + } + + #endregion ui_events + + } +} diff --git a/src/livelywpf/livelywpf/NLog.config b/src/livelywpf/livelywpf/NLog.config new file mode 100644 index 00000000..e491cca6 --- /dev/null +++ b/src/livelywpf/livelywpf/NLog.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/NLog.xsd b/src/livelywpf/livelywpf/NLog.xsd new file mode 100644 index 00000000..16d888c8 --- /dev/null +++ b/src/livelywpf/livelywpf/NLog.xsd @@ -0,0 +1,3556 @@ + + + + + + + + + + + + + + + Watch config file for changes and reload automatically. + + + + + Print internal NLog messages to the console. Default value is: false + + + + + Print internal NLog messages to the console error output. Default value is: false + + + + + Write internal NLog messages to the specified file. + + + + + Log level threshold for internal log messages. Default value is: Info. + + + + + Global log level threshold for application log messages. Messages below this level won't be logged. + + + + + Throw an exception when there is an internal error. Default value is: false. Not recommend to set to true in production! + + + + + Throw an exception when there is a configuration error. If not set, determined by throwExceptions. + + + + + Gets or sets a value indicating whether Variables should be kept on configuration reload. Default value is: false. + + + + + Write internal NLog messages to the System.Diagnostics.Trace. Default value is: false. + + + + + Write timestamps for internal NLog messages. Default value is: true. + + + + + Use InvariantCulture as default culture instead of CurrentCulture. Default value is: false. + + + + + Perform message template parsing and formatting of LogEvent messages (true = Always, false = Never, empty = Auto Detect). Default value is: empty. + + + + + + + + + + + + + + Make all targets within this section asynchronous (creates additional threads but the calling thread isn't blocked by any target writes). + + + + + + + + + + + + + + + + + Prefix for targets/layout renderers/filters/conditions loaded from this assembly. + + + + + Load NLog extensions from the specified file (*.dll) + + + + + Load NLog extensions from the specified assembly. Assembly name should be fully qualified. + + + + + + + + + + Name of the logger. May include wildcard characters ('*' or '?'). + + + + + Comma separated list of levels that this rule matches. + + + + + Minimum level that this rule matches. + + + + + Maximum level that this rule matches. + + + + + Level that this rule matches. + + + + + Comma separated list of target names. + + + + + Ignore further rules if this one matches. + + + + + Rule identifier to allow rule lookup with Configuration.FindRuleByName and Configuration.RemoveRuleByName. + + + + + + + + + + + + + + + Default action if none of the filters match. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the file to be included. You could use * wildcard. The name is relative to the name of the current config file. + + + + + Ignore any errors in the include file. + + + + + + + + Variable value. Note, the 'value' attribute has precedence over this one. + + + + + + Variable name. + + + + + Variable value. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events that should be processed in a batch by the lazy writer thread. + + + + + Whether to use the locking queue, instead of a lock-free concurrent queue The locking queue is less concurrent when many logger threads, but reduces memory allocation + + + + + Limit of full s to write before yielding into Performance is better when writing many small batches, than writing a single large batch + + + + + Action to be taken when the lazy writer thread request queue count exceeds the set limit. + + + + + Limit on the number of requests in the lazy writer thread request queue. + + + + + Time in milliseconds to sleep between batches. (1 or less means trigger on new activity) + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + Delay the flush until the LogEvent has been confirmed as written + + + + + Condition expression. Log events who meet this condition will cause a flush on the wrapped target. + + + + + Name of the target. + + + + + Only flush when LogEvent matches condition. Ignore explicit-flush, config-reload-flush and shutdown-flush + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Number of log events to be buffered. + + + + + Timeout (in milliseconds) after which the contents of buffer will be flushed if there's no write in the specified period of time. Use -1 to disable timed flushes. + + + + + Action to take if the buffer overflows. + + + + + Indicates whether to use sliding timeout. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP. + + + + + Maximum queue size. + + + + + The number of seconds a connection will remain idle before the first keep-alive probe is sent + + + + + NDLC item separator. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Renderer for log4j:event logger-xml-attribute (Default ${logger}) + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Option to include all properties from the log events + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + NDC item separator. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Viewer parameter name. + + + + + Whether an attribute with empty value should be included in the output + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to auto-check if the console is available. - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + Enables output using ANSI Color Codes + + + + + The encoding for writing messages to the . + + + + + Indicates whether the error stream (stderr) should be used instead of the output stream (stdout). + + + + + Indicates whether to auto-check if the console has been redirected to file - Disables coloring logic when System.Console.IsOutputRedirected = true + + + + + Indicates whether to use default row highlighting rules. + + + + + Indicates whether to auto-flush after + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Condition that must be met in order to set the specified foreground and background color. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + Compile the ? This can improve the performance, but at the costs of more memory usage. If false, the Regex Cache is used. + + + + + Indicates whether to ignore case when comparing texts. + + + + + Regular expression to be matched. You must specify either text or regex. + + + + + Text to be matched. You must specify either text or regex. + + + + + Indicates whether to match whole words only. + + + + + Background color. + + + + + Foreground color. + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether to auto-check if the console is available - Disables console writing if Environment.UserInteractive = False (Windows Service) - Disables console writing if Console Standard Input is not available (Non-Console-App) + + + + + The encoding for writing messages to the . + + + + + Indicates whether to send the log messages to the standard error instead of the standard output. + + + + + Indicates whether to auto-flush after + + + + + Whether to enable batch writing using char[]-buffers, instead of using + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this. + + + + + Database user name. If the ConnectionString is not provided this value will be used to construct the "User ID=" part of the connection string. + + + + + Name of the database provider. + + + + + Database password. If the ConnectionString is not provided this value will be used to construct the "Password=" part of the connection string. + + + + + Indicates whether to keep the database connection open between the log events. + + + + + Database name. If the ConnectionString is not provided this value will be used to construct the "Database=" part of the connection string. + + + + + Name of the connection string (as specified in <connectionStrings> configuration section. + + + + + Connection string. When provided, it overrides the values specified in DBHost, DBUserName, DBPassword, DBDatabase. + + + + + Database host name. If the ConnectionString is not provided this value will be used to construct the "Server=" part of the connection string. + + + + + Connection string using for installation and uninstallation. If not provided, regular ConnectionString is being used. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Text of the SQL command to be run on each log level. + + + + + Type of the SQL command to be run on each log level. + + + + + + + + + + + + + + + + + + + + + + + Type of the command. + + + + + Connection string to run the command against. If not provided, connection string from the target is used. + + + + + Indicates whether to ignore failures. + + + + + Command text. + + + + + + + + + + + + + + + + + + Database parameter name. + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Database parameter DbType. + + + + + Database parameter size. + + + + + Database parameter precision. + + + + + Database parameter scale. + + + + + Type of the parameter. + + + + + Convert format of the database parameter value . + + + + + Culture used for parsing parameter string-value for type-conversion + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Layout that renders event Category. + + + + + Optional entry type. When not set, or when not convertible to then determined by + + + + + Layout that renders event ID. + + + + + Name of the Event Log to write to. This can be System, Application or any user-defined name. + + + + + Name of the machine on which Event Log service is running. + + + + + Maximum Event log size in kilobytes. + + + + + Message length limit to write to the Event Log. + + + + + Value to be used as the event Source. + + + + + Action to take if the message is larger than the option. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether to return to the first target after any successful write. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + File encoding. + + + + + Line ending mode. + + + + + Indicates whether to compress archive files into the zip archive format. + + + + + Way file archives are numbered. + + + + + Name of the file to be used for an archive. + + + + + Is the an absolute or relative path? + + + + + Indicates whether to automatically archive log files every time the specified time passes. + + + + + Size in bytes above which log files will be automatically archived. Warning: combining this with isn't supported. We cannot create multiple archive files, if they should have the same name. Choose: + + + + + Maximum number of archive files that should be kept. + + + + + Indicates whether the footer should be written only when the file is archived. + + + + + Maximum number of log file names that should be stored as existing. + + + + + Is the an absolute or relative path? + + + + + Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation. + + + + + Indicates whether file creation calls should be synchronized by a system global mutex. + + + + + Indicates whether to replace file contents on each write instead of appending log message at the end. + + + + + Indicates whether to write BOM (byte order mark) in created files + + + + + Indicates whether to enable log file(s) to be deleted. + + + + + Name of the file to write to. + + + + + Value specifying the date format to use when archiving files. + + + + + Indicates whether to archive old log file on startup. + + + + + Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong. + + + + + Indicates whether to create directories if they do not exist. + + + + + Indicates whether to delete old log file on startup. + + + + + File attributes (Windows only). + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Indicates whether concurrent writes to the log file by multiple processes on different network hosts. + + + + + Maximum number of seconds that files are kept open. If this number is negative the files are not automatically closed after a period of inactivity. + + + + + Number of files to be kept open. Setting this to a higher value may improve performance in a situation where a single File target is writing to many files (such as splitting by level or by logger). + + + + + Indicates whether to keep log file open instead of opening and closing it on each logging event. + + + + + Whether or not this target should just discard all data that its asked to write. Mostly used for when testing NLog Stack except final write + + + + + Indicates whether concurrent writes to the log file by multiple processes on the same host. + + + + + Number of times the write is appended on the file before NLog discards the log message. + + + + + Delay in milliseconds to wait before attempting to write to the file again. + + + + + Log file buffer size in bytes. + + + + + Maximum number of seconds before open files are flushed. If this number is negative or zero the files are not flushed by timer. + + + + + Indicates whether to automatically flush the file buffers after each log message. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Condition expression. Log events who meet this condition will be forwarded to the wrapped target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Windows domain name to change context to. + + + + + Required impersonation level. + + + + + Type of the logon provider. + + + + + Logon Type. + + + + + User account password. + + + + + Indicates whether to revert to the credentials of the process instead of impersonating another user. + + + + + Username to change context to. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Interval in which messages will be written up to the number of messages. + + + + + Maximum allowed number of messages written per . + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Endpoint address. + + + + + Name of the endpoint configuration in WCF configuration file. + + + + + Indicates whether to use a WCF service contract that is one way (fire and forget) or two way (request-reply) + + + + + Client ID. + + + + + Indicates whether to include per-event properties in the payload sent to the server. + + + + + Indicates whether to use binary message encoding. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + Layout that should be use to calculate the value for the parameter. + + + + + Name of the parameter. + + + + + Type of the parameter. + + + + + Type of the parameter. Obsolete alias for + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Text to be rendered. + + + + + Header. + + + + + Footer. + + + + + Indicates whether NewLine characters in the body should be replaced with tags. + + + + + Priority used for sending mails. + + + + + Encoding to be used for sending e-mail. + + + + + BCC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + CC email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Indicates whether to add new lines between log entries. + + + + + Indicates whether to send message as HTML instead of plain text. + + + + + Sender's email address (e.g. joe@domain.com). + + + + + Mail message body (repeated for each log message send in one mail). + + + + + Mail subject. + + + + + Recipients' email addresses separated by semicolons (e.g. john@domain.com;jane@domain.com). + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Indicates the SMTP client timeout. + + + + + SMTP Server to be used for sending. + + + + + SMTP Authentication mode. + + + + + Username used to connect to SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Password used to authenticate against SMTP server (used when SmtpAuthentication is set to "basic"). + + + + + Indicates whether SSL (secure sockets layer) should be used when communicating with SMTP server. + + + + + Port number that SMTP Server is listening on. + + + + + Indicates whether the default Settings from System.Net.MailSettings should be used. + + + + + Folder where applications save mail messages to be processed by the local SMTP server. + + + + + Specifies how outgoing email messages will be handled. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Max number of items to have in memory + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Class name. + + + + + Method name. The method must be public and static. Use the AssemblyQualifiedName , https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx e.g. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Encoding to be used. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Maximum queue size. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP. + + + + + The number of seconds a connection will remain idle before the first keep-alive probe is sent + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Encoding to be used. + + + + + Instance of that is used to format log messages. + + + + + End of line value if a newline is appended at the end of log message . + + + + + Maximum message size in bytes. + + + + + Indicates whether to append newline at the end of log message. + + + + + Network address. + + + + + Size of the connection cache (number of connections which are kept alive). + + + + + Indicates whether to keep connection open whenever possible. + + + + + Maximum current connections. 0 = no maximum. + + + + + Action that should be taken if the will be more connections than . + + + + + Action that should be taken if the message is larger than maxMessageSize. + + + + + Get or set the SSL/TLS protocols. Default no SSL/TLS is used. Currently only implemented for TCP. + + + + + Maximum queue size. + + + + + The number of seconds a connection will remain idle before the first keep-alive probe is sent + + + + + NDLC item separator. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + Renderer for log4j:event logger-xml-attribute (Default ${logger}) + + + + + Indicates whether to include NLog-specific extensions to log4j schema. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include stack contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include dictionary contents. + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Option to include all properties from the log events + + + + + AppInfo field. By default it's the friendly name of the current AppDomain. + + + + + NDC item separator. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Indicates whether to perform layout calculation. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Indicates whether performance counter should be automatically created. + + + + + Name of the performance counter category. + + + + + Counter help text. + + + + + Name of the performance counter. + + + + + Performance counter type. + + + + + The value by which to increment the counter. + + + + + Performance counter instance name. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Default filter to be applied when no specific rule matches. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + Condition to be tested. + + + + + Resulting filter to be applied when the condition matches. + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of times to repeat each log message. + + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Number of retries that should be attempted on the wrapped target in case of a failure. + + + + + Time to wait between retries in milliseconds. + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + Name of the target. + + + + + Layout used to format log messages. + + + + + Always use independent of + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Name of the target. + + + + + Target supports reuse of internal buffers, and doesn't have to constantly allocate new buffers Required for legacy NLog-targets, that expects buffers to remain stable after Write-method exit + + + + + Should we include the BOM (Byte-order-mark) for UTF? Influences the property. This will only work for UTF-8. + + + + + Web service method name. Only used with Soap. + + + + + Web service namespace. Only used with Soap. + + + + + Protocol to be used when calling web service. + + + + + Custom proxy address, include port separated by a colon + + + + + Encoding. + + + + + Web service URL. + + + + + Value whether escaping be done according to the old NLog style (Very non-standard) + + + + + Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs) + + + + + Indicates whether to pre-authenticate the HttpWebRequest (Requires 'Authorization' in parameters) + + + + + Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see and ). + + + + + (optional) root namespace of the XML document, if POST of XML document chosen. (see and ). + + + + + Proxy configuration when calling web service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + Custom column delimiter value (valid when ColumnDelimiter is set to 'Custom'). + + + + + Column delimiter. + + + + + Quote Character. + + + + + Quoting mode. + + + + + Indicates whether CVS should include header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Layout of the column. + + + + + Name of the column. + + + + + Override of Quoting mode + + + + + + + + + + + + + + + + + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log event (as JSON) + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + How far should the JSON serializer follow object references before backing off + + + + + Option to render the empty object value {} + + + + + Option to suppress the extra spaces in the output json + + + + + Should forward slashes be escaped? If true, / will be converted to \/ + + + + + + + + + + + + + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + Determines whether or not this attribute will be Json encoded. + + + + + Indicates whether to escape non-ascii characters + + + + + Whether an attribute with empty value should be included in the output + + + + + Should forward slashes be escaped? If true, / will be converted to \/ + + + + + + + + + + + + + + Footer layout. + + + + + Header layout. + + + + + Body layout (can be repeated multiple times). + + + + + + + + + + + + + + + + + + + + + Option to include all properties from the log events + + + + + Indicates whether to include call site (class and method name) in the information sent over the network. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include contents of the stack. + + + + + Indicates whether to include source info (file name and line number) in the information sent over the network. + + + + + + + + + + + + + + Layout text. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log event (as XML) + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + How far should the XML serializer follow object references before backing off + + + + + XML element name to use for rendering IList-collections items + + + + + XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included + + + + + XML element name to use when rendering properties + + + + + XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value + + + + + Name of the root XML element + + + + + Value inside the root XML element + + + + + Whether a ElementValue with empty value should be included in the output + + + + + Auto indent and create new lines + + + + + Determines whether or not this attribute will be Xml encoded. + + + + + + + + + + + + + + + Layout that will be rendered as the attribute's value. + + + + + Name of the attribute. + + + + + Determines whether or not this attribute will be Xml encoded. + + + + + Whether an attribute with empty value should be included in the output + + + + + + + + + + + + + + + + + + + + + + + + + Determines whether or not this attribute will be Xml encoded. + + + + + Name of the element + + + + + Value inside the element + + + + + Whether a ElementValue with empty value should be included in the output + + + + + Auto indent and create new lines + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log event (as XML) + + + + + Indicates whether to include contents of the dictionary. + + + + + Indicates whether to include contents of the dictionary. + + + + + How far should the XML serializer follow object references before backing off + + + + + XML element name to use for rendering IList-collections items + + + + + XML attribute name to use when rendering property-key When null (or empty) then key-attribute is not included + + + + + XML element name to use when rendering properties + + + + + XML attribute name to use when rendering property-value When null (or empty) then value-attribute is not included and value is formatted as XML-element-value + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Condition expression. + + + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + Substring to be matched. + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + String to compare the layout to. + + + + + Indicates whether to ignore case when comparing strings. + + + + + Layout to be used to filter log messages. + + + + + + + + + + + + + + + + + + + + + + + + Action to be taken when filter matches. + + + + + Default number of unique filter values to expect, will automatically increase if needed + + + + + Applies the configured action to the initial logevent that starts the timeout period. Used to configure that it should ignore all events until timeout. + + + + + Layout to be used to filter log messages. + + + + + Max number of unique filter values to expect simultaneously + + + + + Max length of filter values, will truncate if above limit + + + + + How long before a filter expires, and logging is accepted again + + + + + Default buffer size for the internal buffers + + + + + Reuse internal buffers, and doesn't have to constantly allocate new buffers + + + + + Append FilterCount to the when an event is no longer filtered + + + + + Insert FilterCount value into when an event is no longer filtered + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/AssemblyInfo.cs b/src/livelywpf/livelywpf/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..e50ee763 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("livelywpf")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("rocksdanister")] +[assembly: AssemblyProduct("livelywpf")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en")] +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.3.4.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/livelywpf/livelywpf/Properties/Icons.Designer.cs b/src/livelywpf/livelywpf/Properties/Icons.Designer.cs new file mode 100644 index 00000000..50342370 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Icons.Designer.cs @@ -0,0 +1,123 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace livelywpf.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Icons { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Icons() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("livelywpf.Properties.Icons", typeof(Icons).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icon_close { + get { + object obj = ResourceManager.GetObject("icon_close", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icon_erase { + get { + object obj = ResourceManager.GetObject("icon_erase", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icon_monitor { + get { + object obj = ResourceManager.GetObject("icon_monitor", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icon_update { + get { + object obj = ResourceManager.GetObject("icon_update", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icons8_seed_of_life_96_normal { + get { + object obj = ResourceManager.GetObject("icons8_seed_of_life_96_normal", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + internal static System.Drawing.Icon icons8_seed_of_life_96_pause { + get { + object obj = ResourceManager.GetObject("icons8_seed_of_life_96_pause", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/src/livelywpf/livelywpf/Properties/Icons.resx b/src/livelywpf/livelywpf/Properties/Icons.resx new file mode 100644 index 00000000..ef5f2ef1 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Icons.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\icons\icons8-seed-of-life-96-normal.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icons8-seed-of-life-96-pause.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon_close.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon_erase.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon_monitor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\icons\icon_update.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/Resources.Designer.cs b/src/livelywpf/livelywpf/Properties/Resources.Designer.cs new file mode 100644 index 00000000..43d50524 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Resources.Designer.cs @@ -0,0 +1,1649 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace livelywpf.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("livelywpf.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to All Display(s). + /// + public static string cmbBoxAllDisplays { + get { + return ResourceManager.GetString("cmbBoxAllDisplays", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to XamlAnimatedGif. + /// + public static string cmbBoxGIFPlayer1 { + get { + return ResourceManager.GetString("cmbBoxGIFPlayer1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Low memory usage, high cpu usage. + /// + public static string cmbBoxGIFPlayer1ToolTip { + get { + return ResourceManager.GetString("cmbBoxGIFPlayer1ToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DirectShow. + /// + public static string cmbBoxGIFPlayer2 { + get { + return ResourceManager.GetString("cmbBoxGIFPlayer2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lower cpu usage (depending on codec settings). + /// + public static string cmbBoxGIFPlayer2ToolTip { + get { + return ResourceManager.GetString("cmbBoxGIFPlayer2ToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kill(Free Memory). + /// + public static string cmbBoxKill { + get { + return ResourceManager.GetString("cmbBoxKill", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nothing. + /// + public static string cmbBoxNothing { + get { + return ResourceManager.GetString("cmbBoxNothing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All Processes (Experimental). + /// + public static string cmbBoxPaugeAlgorithmAllProcess { + get { + return ResourceManager.GetString("cmbBoxPaugeAlgorithmAllProcess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pause. + /// + public static string cmbBoxPause { + get { + return ResourceManager.GetString("cmbBoxPause", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Foreground Process. + /// + public static string cmbBoxPauseAlgorithmForeground { + get { + return ResourceManager.GetString("cmbBoxPauseAlgorithmForeground", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Per Display. + /// + public static string cmbBoxPerDisplay { + get { + return ResourceManager.GetString("cmbBoxPerDisplay", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Span(Experimental). + /// + public static string cmbBoxSpan { + get { + return ResourceManager.GetString("cmbBoxSpan", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Media Foundation. + /// + public static string cmbBoxVideoPlayer1 { + get { + return ResourceManager.GetString("cmbBoxVideoPlayer1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DirectShow(Lav, ffdshow..). + /// + public static string cmbBoxVideoPlayer2 { + get { + return ResourceManager.GetString("cmbBoxVideoPlayer2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} + ///{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f39\fbidi [rest of string was truncated]";. + /// + public static string license { + get { + return ResourceManager.GetString("license", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter commandline arguments for the application if any (optional, leave blank if none):-. + /// + public static string msgAppCommandLineArgs { + get { + return ResourceManager.GetString("msgAppCommandLineArgs", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start Arguments. + /// + public static string msgAppCommandLineArgsTitle { + get { + return ResourceManager.GetString("msgAppCommandLineArgsTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The selected wallpaper(application) has no graphical user interface(GUI). + ///Terminating application.... + /// + public static string msgAppGUIFailure { + get { + return ResourceManager.GetString("msgAppGUIFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to catch application window. + ///The wallpaper(application) is taking too long to start(more than ~30sec), it could be due to: + ///Virus scan/ Application is too big. + ///Wait & try again. (optionally you can edit the waiting time, check out wiki for more information.) + ///Terminating application.... + /// + public static string msgAppTimeout { + get { + return ResourceManager.GetString("msgAppTimeout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Damaged wallpaper file, try redownloading.. + /// + public static string msgDamangedLivelyFile { + get { + return ResourceManager.GetString("msgDamangedLivelyFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to permanently delete the wallpaper from the disk?. + /// + public static string msgDeleteConfirmation { + get { + return ResourceManager.GetString("msgDeleteConfirmation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Confirm Deletion. + /// + public static string msgDeleteConfirmationTitle { + get { + return ResourceManager.GetString("msgDeleteConfirmationTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Currently running as wallpaper, cannot delete! + ///Close this wallpaper to delete it.. + /// + public static string msgDeletionFailure { + get { + return ResourceManager.GetString("msgDeletionFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Deletion Failed. + /// + public static string msgDeletionFailureTitle { + get { + return ResourceManager.GetString("msgDeletionFailureTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This file format is not supported for drag & drop, open it in 'Type' page instead.. + /// + public static string msgDragDropOtherFormats { + get { + return ResourceManager.GetString("msgDragDropOtherFormats", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively: Not Supported. + /// + public static string msgDragDropOtherFormatsTitle { + get { + return ResourceManager.GetString("msgDragDropOtherFormatsTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are opening an external application as wallpaper. + ///Malicious applications can host malware, virus.. and do harm to your system. + ///Only continue if this application comes from a trusted source.. + /// + public static string msgExternalAppWarning { + get { + return ResourceManager.GetString("msgExternalAppWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warning. + /// + public static string msgExternalAppWarningTitle { + get { + return ResourceManager.GetString("msgExternalAppWarningTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GIF file playback failed. + ///Is the GIF file corrupted? Try redownloading.. + /// + public static string msgGIFfailure { + get { + return ResourceManager.GetString("msgGIFfailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively cannot work properly with Windows High Contrast mode enabled! + ///Disable High Contrast mode & Try again.. + /// + public static string msgHighContrastFailure { + get { + return ResourceManager.GetString("msgHighContrastFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are about to open an external webpage on your browser. + /// + ///URL:-. + /// + public static string msgLoadExternalLink { + get { + return ResourceManager.GetString("msgLoadExternalLink", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Load Webpage?. + /// + public static string msgLoadExternalLinkTitle { + get { + return ResourceManager.GetString("msgLoadExternalLinkTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Starting up external application... + /// + public static string msgLoadingAppWallpaper { + get { + return ResourceManager.GetString("msgLoadingAppWallpaper", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Media playback failed: Missing Codec/ Corrupted File. + ///Install LAV codec & Try switching to Directshow videoplayer. + /// + ///Further Instructions: + ///www.github.com/rocksdanister/lively/wiki/Video-Guide. + /// + public static string msgMediaFoundationFailure { + get { + return ResourceManager.GetString("msgMediaFoundationFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Media playback failed: Missing Codec/ Corrupted File. + ///Don't forget to install LAV codec: + ///www.github.com/Nevcairiel/LAVFilters/releases + /// + ///Further Instructions: + ///www.github.com/rocksdanister/lively/wiki/Video-Guide. + /// + public static string msgMediakitFailure { + get { + return ResourceManager.GetString("msgMediakitFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Currently restoring previous wallpaper(s), please wait.. + /// + public static string msgRestoringInProgress { + get { + return ResourceManager.GetString("msgRestoringInProgress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Restoring previous wallpaper(s)... + /// + public static string msgRestoringPrevWallpapers { + get { + return ResourceManager.GetString("msgRestoringPrevWallpapers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively was not closed properly, starting in safe mode. + ///Do you wish to restore previously running wallpapers? + ///Error information is saved at:- + ///. + /// + public static string msgSafeModeWarning { + get { + return ResourceManager.GetString("msgSafeModeWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively is already running! + ///If not-responding terminate process "livelywpf" in taskmanager & try again.. + /// + public static string msgSingleInstanceOnly { + get { + return ResourceManager.GetString("msgSingleInstanceOnly", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter website link to load, Shadertoy.com shader links are supported:-. + /// + public static string msgUrlLoad { + get { + return ResourceManager.GetString("msgUrlLoad", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Load webpage. + /// + public static string msgUrlLoadTitle { + get { + return ResourceManager.GetString("msgUrlLoadTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are about to load an external website. + ///Malicious Web pages can be harmful to your computer (malware, virus ..) + ///Only enter links to websites that you trust.. + /// + public static string msgUrlWarning { + get { + return ResourceManager.GetString("msgUrlWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warning. + /// + public static string msgUrlWarningTitle { + get { + return ResourceManager.GetString("msgUrlWarningTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web browser component is missing, either download separately:- + ///https://github.com/rocksdanister/lively-cef + ///OR + ///Download the full version of lively.. + /// + public static string msgWebBrowserMissing { + get { + return ResourceManager.GetString("msgWebBrowserMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to It looks like some settings needs to be set to make Lively work:- + ///1. Open This PC(My Computer) + ///2. Right-click empty area + ///3. Select Properties + ///4. Select Advanced System Settings + ///5. Under Performance tab select Settings + ///6. Enable Animate controls and elements inside windows & Apply. + /// + ///If Windows 7 just set - Adjust for best appearance & Apply. + ///If still not working, close & start Lively again/ restart windows.. + /// + public static string msgWorkerWFailure { + get { + return ResourceManager.GetString("msgWorkerWFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to About. + /// + public static string titleAbout { + get { + return ResourceManager.GetString("titleAbout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Library. + /// + public static string titleLibrary { + get { + return ResourceManager.GetString("titleLibrary", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Settings. + /// + public static string titleSettings { + get { + return ResourceManager.GetString("titleSettings", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type. + /// + public static string titleType { + get { + return ResourceManager.GetString("titleType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I'm minimized to systemtray, right click lively icon for more options.. + /// + public static string toolTipMinimizeMsg { + get { + return ResourceManager.GetString("toolTipMinimizeMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A new version is available!. + /// + public static string toolTipUpdateMsg { + get { + return ResourceManager.GetString("toolTipUpdateMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some wallpaper(s) were skipped because of missing file(s)!. + /// + public static string toolTipWallpaperSkip { + get { + return ResourceManager.GetString("toolTipWallpaperSkip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Application Rules. + /// + public static string txtApplicationRules { + get { + return ResourceManager.GetString("txtApplicationRules", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Audio In:. + /// + public static string txtAudioIn { + get { + return ResourceManager.GetString("txtAudioIn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blocks browsers access to system audio.. + /// + public static string txtAudioInToolTip { + get { + return ResourceManager.GetString("txtAudioInToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Audio is always disabled in multiple monitor systems.. + /// + public static string txtAudioLabel1 { + get { + return ResourceManager.GetString("txtAudioLabel1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "Audio In" is disabled, Web audio visualisers will not work.. + /// + public static string txtAudioLabel2 { + get { + return ResourceManager.GetString("txtAudioLabel2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Audio Out:. + /// + public static string txtAudioOut { + get { + return ResourceManager.GetString("txtAudioOut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unmute/mute video player.. + /// + public static string txtAudioOutToolTip { + get { + return ResourceManager.GetString("txtAudioOutToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web Browser:. + /// + public static string txtBrowser { + get { + return ResourceManager.GetString("txtBrowser", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select web browser for web wallpapers(coming soon). + /// + public static string txtBrowserToolTip { + get { + return ResourceManager.GetString("txtBrowserToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close All Wallpapers. + /// + public static string txtCloseAllWallpapers { + get { + return ResourceManager.GetString("txtCloseAllWallpapers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Coming Soon. + /// + public static string txtComingSoon { + get { + return ResourceManager.GetString("txtComingSoon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close All Wallpapers. + /// + public static string txtContextMenuCloseAll { + get { + return ResourceManager.GetString("txtContextMenuCloseAll", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Close Wallpaper. + /// + public static string txtContextMenuCloseWallpaper { + get { + return ResourceManager.GetString("txtContextMenuCloseWallpaper", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Delete Wallpaper. + /// + public static string txtContextMenuDeleteWallpaper { + get { + return ResourceManager.GetString("txtContextMenuDeleteWallpaper", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exit. + /// + public static string txtContextMenuExit { + get { + return ResourceManager.GetString("txtContextMenuExit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Export lively .zip. + /// + public static string txtContextMenuExport { + get { + return ResourceManager.GetString("txtContextMenuExport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open Lively. + /// + public static string txtContextMenuOpenLively { + get { + return ResourceManager.GetString("txtContextMenuOpenLively", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show on Disk. + /// + public static string txtContextMenuShowOnDisk { + get { + return ResourceManager.GetString("txtContextMenuShowOnDisk", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Checking for update. + /// + public static string txtContextMenuUpdate1 { + get { + return ResourceManager.GetString("txtContextMenuUpdate1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update Available!. + /// + public static string txtContextMenuUpdate2 { + get { + return ResourceManager.GetString("txtContextMenuUpdate2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Is this Beta software?. + /// + public static string txtContextMenuUpdate3 { + get { + return ResourceManager.GetString("txtContextMenuUpdate3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively is up-to-date!. + /// + public static string txtContextMenuUpdate4 { + get { + return ResourceManager.GetString("txtContextMenuUpdate4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error Checking for Update. + /// + public static string txtContextMenuUpdate5 { + get { + return ResourceManager.GetString("txtContextMenuUpdate5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create Wallpaper. + /// + public static string txtCreateWallpaper { + get { + return ResourceManager.GetString("txtCreateWallpaper", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Creating Lively zip file.. + /// + public static string txtCreatingZip { + get { + return ResourceManager.GetString("txtCreatingZip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Display Pause Rule:. + /// + public static string txtDisplayPauseRule { + get { + return ResourceManager.GetString("txtDisplayPauseRule", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GIF Player:. + /// + public static string txtGIFPlayer { + get { + return ResourceManager.GetString("txtGIFPlayer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Directshow requires additionals plugins to be installed.. + /// + public static string txtGifPlayerToolTip { + get { + return ResourceManager.GetString("txtGifPlayerToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Help. + /// + public static string txtHelp { + get { + return ResourceManager.GetString("txtHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ignore. + /// + public static string txtIgnore { + get { + return ResourceManager.GetString("txtIgnore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Install Wallpaper. + /// + public static string txtInstallWallpaper { + get { + return ResourceManager.GetString("txtInstallWallpaper", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select wallpaper type to load:-. + /// + public static string txtLabel1 { + get { + return ResourceManager.GetString("txtLabel1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attribution:. + /// + public static string txtLabel10 { + get { + return ResourceManager.GetString("txtLabel10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to What should I use?. + /// + public static string txtLabel11 { + get { + return ResourceManager.GetString("txtLabel11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type:. + /// + public static string txtLabel12 { + get { + return ResourceManager.GetString("txtLabel12", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Force 120FPS UI. + /// + public static string txtLabel120FPS { + get { + return ResourceManager.GetString("txtLabel120FPS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Author:. + /// + public static string txtLabel13 { + get { + return ResourceManager.GetString("txtLabel13", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Contact:. + /// + public static string txtLabel14 { + get { + return ResourceManager.GetString("txtLabel14", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to General:. + /// + public static string txtLabel15 { + get { + return ResourceManager.GetString("txtLabel15", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Require app restart:. + /// + public static string txtLabel16 { + get { + return ResourceManager.GetString("txtLabel16", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Video:. + /// + public static string txtLabel17 { + get { + return ResourceManager.GetString("txtLabel17", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gif:. + /// + public static string txtLabel18 { + get { + return ResourceManager.GetString("txtLabel18", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web Browser:. + /// + public static string txtLabel19 { + get { + return ResourceManager.GetString("txtLabel19", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Just drag and drop files if you prefer it that way instead.. + /// + public static string txtLabel2 { + get { + return ResourceManager.GetString("txtLabel2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Performance:. + /// + public static string txtLabel20 { + get { + return ResourceManager.GetString("txtLabel20", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set wallpaper(s) playback behaviour based on running application:-. + /// + public static string txtLabel21 { + get { + return ResourceManager.GetString("txtLabel21", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add. + /// + public static string txtLabel22 { + get { + return ResourceManager.GetString("txtLabel22", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove. + /// + public static string txtLabel23 { + get { + return ResourceManager.GetString("txtLabel23", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select Wallpaper Layout:-. + /// + public static string txtLabel24 { + get { + return ResourceManager.GetString("txtLabel24", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pick a wallpaper type to create:-. + /// + public static string txtLabel25 { + get { + return ResourceManager.GetString("txtLabel25", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Library File: Create easy to share .zip file that loads wallpaper into Lively's library. + ///To simply play a file as wallpaper, this is not required; just drag and drop the file to lively window.. + /// + public static string txtLabel26 { + get { + return ResourceManager.GetString("txtLabel26", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Contact Website(optional):-. + /// + public static string txtLabel27 { + get { + return ResourceManager.GetString("txtLabel27", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to License(optional):-. + /// + public static string txtLabel28 { + get { + return ResourceManager.GetString("txtLabel28", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Title:-. + /// + public static string txtLabel29 { + get { + return ResourceManager.GetString("txtLabel29", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to These materials are not sponsored by or affiliated with Unity Technologies, Godot, Bizhawk, Shadertoy.com. + /// + public static string txtLabel3 { + get { + return ResourceManager.GetString("txtLabel3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Description:-. + /// + public static string txtLabel30 { + get { + return ResourceManager.GetString("txtLabel30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select File. + /// + public static string txtLabel31 { + get { + return ResourceManager.GetString("txtLabel31", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Thumbnail (200x200). + /// + public static string txtLabel32 { + get { + return ResourceManager.GetString("txtLabel32", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create. + /// + public static string txtLabel33 { + get { + return ResourceManager.GetString("txtLabel33", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Preview Gif (192x108). + /// + public static string txtLabel34 { + get { + return ResourceManager.GetString("txtLabel34", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wallpaper Type:-. + /// + public static string txtLabel35 { + get { + return ResourceManager.GetString("txtLabel35", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Files and Folders being added:-. + /// + public static string txtLabel36 { + get { + return ResourceManager.GetString("txtLabel36", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ok. + /// + public static string txtLabel37 { + get { + return ResourceManager.GetString("txtLabel37", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Back. + /// + public static string txtLabel38 { + get { + return ResourceManager.GetString("txtLabel38", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Installing Wallpaper. + /// + public static string txtLabel39 { + get { + return ResourceManager.GetString("txtLabel39", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Media. + /// + public static string txtLabel4 { + get { + return ResourceManager.GetString("txtLabel4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Games. + /// + public static string txtLabel5 { + get { + return ResourceManager.GetString("txtLabel5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retro. + /// + public static string txtLabel6 { + get { + return ResourceManager.GetString("txtLabel6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Other. + /// + public static string txtLabel7 { + get { + return ResourceManager.GetString("txtLabel7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web. + /// + public static string txtLabel8 { + get { + return ResourceManager.GetString("txtLabel8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Audio Visualiser. + /// + public static string txtLabel9 { + get { + return ResourceManager.GetString("txtLabel9", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Application. + /// + public static string txtLabelApplication { + get { + return ResourceManager.GetString("txtLabelApplication", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively. + /// + public static string txtLabelAppName { + get { + return ResourceManager.GetString("txtLabelAppName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rule. + /// + public static string txtLabelRule { + get { + return ResourceManager.GetString("txtLabelRule", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Disable Hardware Acceleration. + /// + public static string txtLabelSoftwareUIRendering { + get { + return ResourceManager.GetString("txtLabelSoftwareUIRendering", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This feature is currently in development. + ///Do NOT run programs such as CHROME, STEAM.. which spawn multiple Subprocesses. + ///THERE WILL BE BUGS & CRASHES, PROCEED WITH CAUTION!!!. + /// + public static string txtLivelyAppWarning { + get { + return ResourceManager.GetString("txtLivelyAppWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively: Error. + /// + public static string txtLivelyErrorMsgTitle { + get { + return ResourceManager.GetString("txtLivelyErrorMsgTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please Wait. + /// + public static string txtLivelyWaitMsgTitle { + get { + return ResourceManager.GetString("txtLivelyWaitMsgTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Application. + /// + public static string txtLivelyWallpaperTypeApp { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeApp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Animated GIF. + /// + public static string txtLivelyWallpaperTypeGIF { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeGIF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Godot Application. + /// + public static string txtLivelyWallpaperTypeGodot { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeGodot", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unity Application. + /// + public static string txtLivelyWallpaperTypeUnity { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeUnity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unity Audio Reactive. + /// + public static string txtLivelyWallpaperTypeUnityAudio { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeUnityAudio", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Video. + /// + public static string txtLivelyWallpaperTypeVideo { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeVideo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web. + /// + public static string txtLivelyWallpaperTypeWeb { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeWeb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web Audio Reactive. + /// + public static string txtLivelyWallpaperTypeWebAudio { + get { + return ResourceManager.GetString("txtLivelyWallpaperTypeWebAudio", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Animated Tile:. + /// + public static string txtLiveTile { + get { + return ResourceManager.GetString("txtLiveTile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (Experimental) Wallpaper preview on tile.. + /// + public static string txtLiveTileToolTip { + get { + return ResourceManager.GetString("txtLiveTileToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fille all the required text fields.. + /// + public static string txtMsgFillAllFields { + get { + return ResourceManager.GetString("txtMsgFillAllFields", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wallpaper file not selected. + /// + public static string txtMsgSelectWallpaperFile { + get { + return ResourceManager.GetString("txtMsgSelectWallpaperFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Note: + ///(1) Lively window ignores these rules. + ///(2) Audio is always muted when other apps are in focus {except (1), Lively window}. + ///(3) Foreground Process algorithm has some limitations, check wiki for more information. + ///(4) Application Rules has the highest priority.. + /// + public static string txtNotes { + get { + return ResourceManager.GetString("txtNotes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Off. + /// + public static string txtOff { + get { + return ResourceManager.GetString("txtOff", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to On. + /// + public static string txtOn { + get { + return ResourceManager.GetString("txtOn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Other Application Focused:. + /// + public static string txtOtherAppsFocus { + get { + return ResourceManager.GetString("txtOtherAppsFocus", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Other Application Fullscreen:. + /// + public static string txtOtherAppsFullScreen { + get { + return ResourceManager.GetString("txtOtherAppsFullScreen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pause Algorithm:. + /// + public static string txtPauseAlgorith { + get { + return ResourceManager.GetString("txtPauseAlgorith", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Load Failed. + /// + public static string txtPleaseWait { + get { + return ResourceManager.GetString("txtPleaseWait", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please Wait. + /// + public static string txtPleaseWait2 { + get { + return ResourceManager.GetString("txtPleaseWait2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select previewclip/thumbnail file.. + /// + public static string txtSelectPreviewThumb { + get { + return ResourceManager.GetString("txtSelectPreviewThumb", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set as Wallpaper. + /// + public static string txtSetWallpaper { + get { + return ResourceManager.GetString("txtSetWallpaper", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Some wallpapers will not span across displays properly.. + /// + public static string txtSpanWallpaperWarning { + get { + return ResourceManager.GetString("txtSpanWallpaperWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start with Windows:. + /// + public static string txtStartup { + get { + return ResourceManager.GetString("txtStartup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make sure to uncheck this before uninstalling lively.. + /// + public static string txtStartupToolTip { + get { + return ResourceManager.GetString("txtStartupToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Support. + /// + public static string txtSupport { + get { + return ResourceManager.GetString("txtSupport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Animated GIF. + /// + public static string txtTileGIF { + get { + return ResourceManager.GetString("txtTileGIF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Godot Software. + /// + public static string txtTileGodot { + get { + return ResourceManager.GetString("txtTileGodot", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to HTML. + /// + public static string txtTileHTML { + get { + return ResourceManager.GetString("txtTileHTML", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Other. + /// + public static string txtTileOther { + get { + return ResourceManager.GetString("txtTileOther", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unity Software. + /// + public static string txtTileUnity { + get { + return ResourceManager.GetString("txtTileUnity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Video. + /// + public static string txtTileVideo { + get { + return ResourceManager.GetString("txtTileVideo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Website. + /// + public static string txtTileWebsite { + get { + return ResourceManager.GetString("txtTileWebsite", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lively Wallpaper System. + /// + public static string txtTitlebar { + get { + return ResourceManager.GetString("txtTitlebar", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Transparent UI:. + /// + public static string txtTransparency { + get { + return ResourceManager.GetString("txtTransparency", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Make lively window semi-transparent.. + /// + public static string txtTransparencyToolTip { + get { + return ResourceManager.GetString("txtTransparencyToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update available Lively. + /// + public static string txtUpdateBanner { + get { + return ResourceManager.GetString("txtUpdateBanner", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Video Player:. + /// + public static string txtVideoPlayer { + get { + return ResourceManager.GetString("txtVideoPlayer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Directshow requires additionals plugins to be installed.. + /// + public static string txtVideoPlayerToolTip { + get { + return ResourceManager.GetString("txtVideoPlayerToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wallpaper Playback:. + /// + public static string txtWallpaperPlayback { + get { + return ResourceManager.GetString("txtWallpaperPlayback", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select Display. + /// + public static string txtWindowTitleSelectDisplay { + get { + return ResourceManager.GetString("txtWindowTitleSelectDisplay", resourceCulture); + } + } + } +} diff --git a/src/livelywpf/livelywpf/Properties/Resources.hi.resx b/src/livelywpf/livelywpf/Properties/Resources.hi.resx new file mode 100644 index 00000000..ab72ba46 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Resources.hi.resx @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + सभी प्रदर्शन (s) + + + XamlAnimatedGif + + + कम मेमोरी उपयोग, उच्च सीपीयू उपयोग + + + डायरेक्टशो + + + कम सीपीयू उपयोग (कोडेक सेटिंग्स के आधार पर) + + + किल (फ्री मेमोरी) + + + कुछ भी नहीं है + + + सभी प्रक्रियाएँ (प्रायोगिक) + + + रोकें + + + अग्रभूमि प्रक्रिया + + + प्रति प्रदर्शन + + + स्पैन (प्रायोगिक) + + + Media Foundation + + + DirectShow (Lav, ffdshow ..) + + + + ..\docs\license.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + यदि कोई हो, तो आवेदन के लिए कमांडलाइन तर्क दर्ज करें (यदि कोई हो तो खाली छोड़ दें): - + + + आरंभ तर्क + + + चयनित वॉलपेपर (एप्लिकेशन) का कोई ग्राफ़िकल उपयोगकर्ता इंटरफ़ेस (GUI) नहीं है। +आवेदन समाप्त ... + + + एप्लिकेशन विंडो को पकड़ने में विफल। +वॉलपेपर (एप्लिकेशन) को शुरू होने में बहुत अधिक समय लग रहा है (~ 30sec से अधिक), इसकी वजह यह हो सकती है: +वायरस स्कैन / एप्लिकेशन बहुत बड़ा है। +प्रतीक्षा करें & पुनः प्रयास करें। (वैकल्पिक रूप से आप प्रतीक्षा समय को संपादित कर सकते हैं, अधिक जानकारी के लिए विकी देखें।) +आवेदन समाप्त ... + + + क्षतिग्रस्त वॉलपेपर फ़ाइल, पुनः डाउनलोड करने का प्रयास करें। + + + क्या आप वाकई डिस्क से वॉलपेपर को स्थायी रूप से हटाना चाहते हैं? + + + हटाए जाने की पुष्टि करें + + + वर्तमान में वॉलपेपर के रूप में चल रहा है, हटा नहीं सकता! +इसे हटाने के लिए इस वॉलपेपर को बंद करें। + + + हटाए गए विफल + + + यह फ़ाइल प्रारूप ड्रैग एंड amp के लिए समर्थित नहीं है; ड्रॉप करें, इसे 'टाइप करें' पेज के बजाय खोलें। + + + जीवंत: समर्थित नहीं + + + आप वॉलपेपर के रूप में एक बाहरी एप्लिकेशन खोल रहे हैं। +दुर्भावनापूर्ण एप्लिकेशन मैलवेयर, वायरस को होस्ट कर सकते हैं .. और आपके सिस्टम को नुकसान पहुंचा सकते हैं। +केवल तभी जारी रखें जब यह एप्लिकेशन किसी विश्वसनीय स्रोत से आता है। + + + चेतावनी + + + GIF फ़ाइल प्लेबैक विफल। +क्या GIF फ़ाइल दूषित है? पुन: डाउनलोड करने का प्रयास करें। + + + जीवंत विंडोज हाई कंट्रास्ट मोड के साथ ठीक से काम नहीं कर सकता है! +उच्च कंट्रास्ट मोड को अक्षम करें & पुन: प्रयास करें। + + + आप अपने ब्राउज़र पर एक बाहरी वेबपेज खोलने वाले हैं। + +यूआरएल: - + + + वेबपृष्ठ लोड करें? + + + बाहरी अनुप्रयोग शुरू करना + + + मीडिया प्लेबैक विफल: लापता कोडेक / दूषित फ़ाइल। +LAV कोडेक & स्थापित करें; Directshow videoplayer पर स्विच करने का प्रयास करें। + +आगे के निर्देश: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + मीडिया प्लेबैक विफल: लापता कोडेक / दूषित फ़ाइल। +LAV कोडेक स्थापित करने के लिए मत भूलना: +www.github.com/Nevcairiel/LAVFilters/releases + +आगे के निर्देश: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + वर्तमान में पिछले वॉलपेपर को पुनर्स्थापित कर रहे हैं, कृपया प्रतीक्षा करें। + + + पिछले वॉलपेपर को पुनर्स्थापित करना .. + + + लाइवली को ठीक से बंद नहीं किया गया था, सुरक्षित मोड में शुरू करना। +क्या आप पहले से चल रहे वॉलपेपर को पुनर्स्थापित करना चाहते हैं? +त्रुटि सूचना यहां दी गई है: - + + + + जीवंत पहले से ही चल रहा है! +यदि नहीं तो जवाब देने की प्रक्रिया कार्यवाहक में "livelywpf" समाप्त करें & पुन: प्रयास करें। + + + लोड करने के लिए वेबसाइट लिंक दर्ज करें, Shadertoy.com shader लिंक समर्थित हैं: - + + + वेबपेज लोड करें + + + आप बाहरी वेबसाइट लोड करने वाले हैं। +दुर्भावनापूर्ण वेब पेज आपके कंप्यूटर के लिए हानिकारक हो सकते हैं (मैलवेयर, वायरस ..) +केवल उन वेबसाइटों के लिंक डालें जिन पर आप भरोसा करते हैं। + + + चेतावनी + + + वेब ब्राउज़र घटक गायब है, या तो अलग से डाउनलोड करें: - +https://github.com/rocksdanister/lively-cef +या +जीवंत का पूरा संस्करण डाउनलोड करें। + + + ऐसा लगता है कि कुछ सेटिंग्स को जीवंत बनाने के लिए सेट करने की आवश्यकता है: - +1. यह पीसी खोलें (मेरा कंप्यूटर) +2. खाली क्षेत्र पर राइट-क्लिक करें +3. गुण चुनें +4. उन्नत सिस्टम सेटिंग्स का चयन करें +5. प्रदर्शन टैब के तहत सेटिंग्स का चयन करें +6. विंडो और amp के भीतर चेतन नियंत्रण और तत्वों को सक्षम करें; लागू करें। + +अगर विंडोज 7 बस सेट है - सर्वश्रेष्ठ उपस्थिति के लिए समायोजित करें & लागू करें। +यदि अभी भी काम नहीं कर रहा है, तो & Live को फिर से शुरू / विंडोज़ को पुनरारंभ करें। + + + संक्षिप्त विवरण + + + लाइब्रेरी + + + सेटिंग + + + प्रकार + + + मुझे systemtray के लिए छोटा किया गया है, अधिक विकल्पों के लिए जीवंत आइकन पर राइट क्लिक करें। + + + एक नया संस्करण उपलब्ध है! + + + लापता फ़ाइल (नों) के कारण कुछ वॉलपेपर छोड़े गए थे + + + अनुप्रयोग नियम + + + ऑडियो इन: + + + ब्राउज़र सिस्टम ऑडियो तक पहुंच को ब्लॉक करता है। + + + ऑडियो हमेशा कई मॉनिटर सिस्टम में अक्षम होता है। + + + "ऑडियो इन" अक्षम है, वेब ऑडियो विज़ुअलाइज़र काम नहीं करेगा। + + + ऑडियो आउट: + + + वीडियो प्लेयर को अनम्यूट / म्यूट करें। + + + वेब ब्राउज़र: + + + वेब वॉलपेपर के लिए वेब ब्राउज़र का चयन करें (जल्द ही आ रहा है) + + + सभी वॉलपेपर बंद करें + + + जल्द ही आ रहा है + + + सभी वॉलपेपर बंद करें + + + वॉलपेपर बंद करें + + + वॉलपेपर हटाएं + + + बाहर निकलें + + + जीवंत निर्यात करें। ज़िप + + + जीवंत रूप से खोलें + + + डिस्क पर दिखाएँ + + + अपडेट के लिए जाँच करना + + + अपडेट उपलब्ध है! + + + क्या यह बीटा सॉफ़्टवेयर है? + + + जीवंत अप-टू-डेट है! + + + अपडेट के लिए त्रुटि जाँच + + + वॉलपेपर बनाएं + + + जीवंत ज़िप फ़ाइल बनाना। + + + ठहराव नियम प्रदर्शित करें: + + + GIF प्लेयर: + + + डायरेक्टशो को इंस्टॉल करने के लिए अतिरिक्त प्लगइन्स की आवश्यकता होती है। + + + सहायता + + + अनदेखा करें + + + वॉलपेपर स्थापित करें + + + लोड करने के लिए वॉलपेपर प्रकार चुनें: - + + + एट्रिब्यूशन: + + + मुझे क्या उपयोग करना चाहिए? + + + प्रकार: + + + बल 120FPS UI + + + लेखक: + + + संपर्क: + + + सामान्य: + सेटिंग टैब + + + एप्लिकेशन पुनरारंभ की आवश्यकता है: + सेटिंग टैब + + + वीडियो: + सेटिंग टैब + + + Gif: + सेटिंग टैब + + + वेब ब्राउज़र: + सेटिंग टैब + + + यदि आप इसके बजाय इसे पसंद करते हैं तो मीडियाफाइल्स को बस खींचें और छोड़ें। + + + प्रदर्शन: + सेटिंग टैब + + + चल रहे एप्लिकेशन के आधार पर वॉलपेपर (एस) प्लेबैक व्यवहार सेट करें: - + + + जोड़ें + + + निकालें + + + वॉलपेपर लेआउट चुनें: - + + + बनाने के लिए एक वॉलपेपर प्रकार चुनें: - + + + लाइब्रेरी फ़ाइल: साझा करने के लिए आसान बनाएँ। ज़िप फ़ाइल जो लाइवली की लाइब्रेरी में वॉलपेपर लोड करती है। +बस एक फाइल को वॉलपेपर के रूप में चलाने के लिए, यह आवश्यक नहीं है; बस जीवंत विंडो में फ़ाइल को ड्रैग और ड्रॉप करें। + + + संपर्क वेबसाइट (वैकल्पिक): - + + + लाइसेंस (वैकल्पिक): - + + + शीर्षक: - + + + ये सामग्री Unity Technologies, Godot, Bizhawk, Shadertoy.com / /> से संबद्ध या प्रायोजित नहीं हैं + + + विवरण: - + + + फ़ाइल का चयन करें + + + थंबनेल (200x200) + + + बनाएं + + + Gif का पूर्वावलोकन करें (192x108) + + + वॉलपेपर प्रकार: - + + + फ़ाइलें और फ़ोल्डर जोड़े जा रहे हैं: - + + + ठीक + + + वापस + + + वॉलपेपर स्थापित करना + + + मीडिया + + + खेल + + + रेट्रो + + + अन्य + + + वेब + + + ऑडियो विज़ुअलाइज़र + + + अनुप्रयोग + + + जीवंत + + + नियम + + + हार्डवेयर एक्सेलेरेशन को अक्षम करें + + + यह सुविधा वर्तमान में विकास में है। +CHROME, STEAM .. जैसे कार्यक्रम न चलाएं, जो कई सबप्रोसेस को स्पॉन करते हैं। +वहाँ खरीदे जाएँगे & क्रेसेस, सावधानी के साथ आगे बढ़ें !!! + + + जीवंत: त्रुटि + संदेश बॉक्स के लिए शीर्षक। + + + कृपया प्रतीक्षा करें + संदेश बॉक्स के लिए शीर्षक + + + अनुप्रयोग + + + एनिमेटेड GIF + + + गोडोट एप्लीकेशन + + + एकता अनुप्रयोग + + + एकता ऑडियो रिएक्टिव + + + वीडियो + + + वेब + + + वेब ऑडियो रिएक्टिव + + + एनिमेटेड टाइल: + + + (प्रायोगिक, उच्च सीपीयू उपयोग) लाइब्रेरी टाइल पर वॉलपेपर पूर्वावलोकन खेलें। + + + सभी आवश्यक टेक्स्ट फ़ील्ड को हटाएं। + + + वॉलपेपर फ़ाइल चयनित नहीं + + + ध्यान दें: +(१) जीवंत खिड़की इन नियमों की उपेक्षा करती है। +(2) ऑडियो हमेशा म्यूट होता है जब अन्य ऐप्स फ़ोकस में होते हैं {सिवाय (1), लाइवली विंडो}। +(3) फ़ोरग्राउंड प्रोसेस एल्गोरिदम की कुछ सीमाएँ हैं, अधिक जानकारी के लिए विकि की जाँच करें। +(4) आवेदन नियमों की सर्वोच्च प्राथमिकता है। +(5) वेब ब्राउजर को रोकने के बजाय कम से कम किया जा रहा है, इसलिए आपको कुछ मामलों में डिफ़ॉल्ट रूप से वॉलपेपर को अस्थायी रूप से पलटते हुए दिखाई देगा; फिक्स जल्द ही आ रहा है। + + + बंद + + + चालू + + + अन्य एप्लिकेशन फोकस किया गया: + + + अन्य एप्लिकेशन फुलस्क्रीन: + + + एल्गोरिथ्म रोकें: + + + लोड विफल + + + कृपया प्रतीक्षा करें + + + प्रीव्यूक्लिप / थंबनेल फ़ाइल का चयन करें। + + + वॉलपेपर के रूप में सेट करें + + + कुछ वॉलपेपर ठीक से प्रदर्शित नहीं होंगे। + + + विंडोज से शुरू करें: + + + जीवंत रूप से अनइंस्टॉल करने से पहले इसे अनचेक करना सुनिश्चित करें। + + + समर्थन + + + एनिमेटेड GIF + + + Godot Software + + + HTML + + + अन्य + + + एकता सॉफ्टवेयर + + + वीडियो + + + वेबसाइट + + + जीवंत वॉलपेपर सिस्टम + + + पारदर्शी UI: + + + जीवंत विंडो को अर्ध-पारदर्शी बनाएं। + + + जीवंत रूप से उपलब्ध अपडेट करें + + + वीडियो प्लेयर: + + + डायरेक्टशो को इंस्टॉल करने के लिए अतिरिक्त प्लगइन्स की आवश्यकता होती है। + + + वॉलपेपर प्लेबैक: + + + प्रदर्शन का चयन करें + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/Resources.ja.resx b/src/livelywpf/livelywpf/Properties/Resources.ja.resx new file mode 100644 index 00000000..ed68edbe --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Resources.ja.resx @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + すべてのディスプレイ + + + XamlAnimatedGif + + + 低メモリ使用量、高CPU使用量 + + + DirectShow + + + 低いCPU使用率(コーデック設定による) + + + キル(空きメモリ) + + + なし + + + すべてのプロセス(実験的) + + + 一時停止 + + + フォアグラウンドプロセス + + + ディスプレイごと + + + Span(実験的) + + + メディアファンデーション + + + DirectShow(Lav、ffdshow ..) + + + + ..\docs\license.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + アプリケーションのコマンドライン引数がある場合は入力します(オプション、ない場合は空白のままにします): + + + 開始引数 + + + 選択した壁紙(アプリケーション)には、グラフィカルユーザーインターフェイス(GUI)がありません。 +アプリケーションを終了しています... + + + アプリケーションウィンドウをキャッチできませんでした。 +壁紙(アプリケーション)の起動に時間がかかりすぎています(30秒以上)。原因は次のとおりです。 +ウイルススキャン/アプリケーションが大きすぎます。 +待つ&再試行する。 (オプションで、待ち時間を編集できます。詳細については、Wikiを参照してください。) +アプリケーションを終了しています... + + + 破損した壁紙ファイル、再ダウンロードしてみてください。 + + + ディスクから壁紙を完全に削除してもよろしいですか? + + + 削除の確認 + + + 現在壁紙として実行中、削除できません! +この壁紙を閉じて削除してください。 + + + 削除に失敗しました + + + このファイル形式は、ドラッグ&ではサポートされていませんドロップして、代わりに「タイプ」ページで開きます。 + + + Lively:サポートされていません + + + 外部アプリケーションを壁紙として開いています。 +悪意のあるアプリケーションは、マルウェア、ウイルスをホストし、システムに害を及ぼす可能性があります。 +このアプリケーションが信頼できるソースからのものである場合にのみ続行します。 + + + 警告 + + + GIFファイルの再生に失敗しました。 +GIFファイルは破損していますか?再ダウンロードしてみてください。 + + + Livelyは、Windowsハイコントラストモードが有効になっていると正しく動作しません! +ハイコントラストモードを無効にする&再試行してください。 + + + ブラウザで外部Webページを開こうとしています。 + +URL:- + + + Webページをロードしますか + + + 外部アプリケーションの起動.. + + + メディアの再生に失敗しました:コーデックが見つかりません/ファイルが破損しています。 +LAVコーデックをインストール& Directshow videoplayerに切り替えてみてください。 + +詳細な手順: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + メディアの再生に失敗しました:コーデックが見つかりません/ファイルが破損しています。 +LAVコーデックをインストールすることを忘れないでください: +www.github.com/Nevcairiel/LAVFilters/releases + +詳細な手順: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + 現在、以前の壁紙を復元しています。しばらくお待ちください。 + + + 以前の壁紙を復元しています.. + + + Livelyは、セーフモードで起動して、適切に閉じられませんでした。 +以前に実行していた壁紙を復元しますか? +エラー情報は次の場所に保存されます。 + + + + Livelyはすでに実行中です! +応答しない場合、taskmanager&のプロセス「livelywpf」を終了もう一度お試しください。 + + + 読み込むWebサイトリンクを入力してください。Shadertoy.comシェーダーリンクがサポートされています:- + + + ウェブページの読み込み + + + 外部Webサイトをロードしようとしています。 +悪意のあるWebページは、コンピューターに有害である可能性があります(マルウェア、ウイルス..) +信頼できるWebサイトへのリンクのみを入力してください。 + + + 警告 + + + Webブラウザコンポーネントがありません。個別にダウンロードするか、 +https://github.com/rocksdanister/lively-cef +または +livelyのフルバージョンをダウンロードします。 + + + Livelyを動作させるには、いくつかの設定を設定する必要があるようです:- +1.このPC(マイコンピュータ)を開きます +2.空の領域を右クリックします +3.プロパティを選択します +4.システムの詳細設定を選択します +5. [パフォーマンス]タブで[設定]を選択します +6.ウィンドウ内のアニメーションコントロールと要素を有効にします。適用します。 + +Windows 7が設定されている場合-最適な外観と調整適用します。 +それでも機能しない場合は、&を閉じます。 Livelyを再び起動/ウィンドウを再起動します。 + + + 概要 + + + ライブラリ + + + 設定 + + + タイプ + + + システムトレイに最小化され、オプションを追加するにはライブアイコンを右クリックします。 + + + 新しいバージョンが利用可能です + + + ファイルが欠落しているため、一部の壁紙がスキップされました! + + + アプリケーションルール + + + オーディオ入力: + + + ブラウザからシステムオーディオへのアクセスをブロックします。 + + + オーディオは、複数のモニターシステムで常に無効になっています。 + + + 「オーディオ入力」が無効になっているため、Webオーディオビジュアライザーは機能しません。 + + + 音声出力: + + + 動画プレーヤーのミュート解除/ミュート + + + Webブラウザー: + + + Web壁紙用のWebブラウザーを選択(近日公開) + + + すべての壁紙を閉じる + + + 近日公開 + + + すべての壁紙を閉じる + + + 壁紙を閉じる + + + 壁紙を削除 + + + 終了 + + + 活発な.zipをエクスポート + + + 活発に開く + + + ディスクに表示 + + + 更新の確認 + + + アップデートが利用可能です + + + これはベータ版ソフトウェアですか? + + + Livelyは最新です! + + + 更新の確認エラー + + + 壁紙を作成 + + + 活発なzipファイルを作成しています。 + + + 一時停止ルールを表示: + + + GIFプレーヤー: + + + Directshowには、追加プラグインのインストールが必要です。 + + + ヘルプ + + + 無視 + + + 壁紙をインストール + + + 読み込む壁紙の種類を選択:- + + + 属性: + + + 私は何を使うべきですか? + + + タイプ: + + + 120FPS UIを強制する + + + 作成者: + + + 連絡先: + + + 一般: + 設定タブ + + + アプリの再起動が必要: + 設定タブ + + + ビデオ: + 設定タブ + + + Gif: + 設定タブ + + + Webブラウザー: + 設定タブ + + + 代わりにメディアファイルを希望する場合は、ドラッグアンドドロップするだけです。 + + + パフォーマンス: + 設定タブ + + + 実行中のアプリケーションに基づいて壁紙の再生動作を設定します:- + + + 追加 + + + 削除 + + + 壁紙レイアウトを選択:- + + + 作成する壁紙タイプを選択:- + + + ライブラリファイル:Livelyのライブラリに壁紙を読み込む簡単に共有できる.zipファイルを作成します。 +ファイルを壁紙として単に再生するには、これは必要ありません。ファイルを活発なウィンドウにドラッグアンドドロップするだけです。 + + + 連絡先Webサイト(オプション):- + + + ライセンス(オプション):- + + + タイトル:- + + + これらの資料は、Unity Technologies、Godot、Bizhawk、Shadertoy.comがスポンサーまたは提携していません + + + 説明:- + + + ファイルを選択 + + + サムネイル(200x200) + + + 作成 + + + プレビューGif(192x108) + + + 壁紙タイプ:- + + + 追加されるファイルとフォルダー:- + + + OK + + + 戻る + + + 壁紙のインストール + + + メディア + + + ゲーム + + + レトロ + + + その他 + + + Web + + + オーディオビジュアライザー + + + アプリケーション + + + 活気のある + + + ルール + + + ハードウェアアクセラレーションを無効にする + + + この機能は現在開発中です。 +複数のサブプロセスを生成するCHROME、STEAMなどのプログラムを実行しないでください。 +バグがあります&クラッシュ、注意して進む!!! + + + ライブリー:エラー + メッセージボックスのタイトル + + + しばらくお待ちください + メッセージボックスのタイトル + + + アプリケーション + + + アニメーションGIF + + + Godotアプリケーション + + + Unity Application + + + Unity Audio Reactive + + + ビデオ + + + Web + + + Web Audio Reactive + + + アニメーションタイル: + + + (実験的、高いCPU使用率)ライブラリタイルで壁紙プレビューを再生します。 + + + 必要なすべてのテキストフィールドに入力します。 + + + 壁紙ファイルが選択されていません + + + 注: +(1)Livelyウィンドウはこれらのルールを無視します。 +(2)他のアプリにフォーカスがある場合、音声は常にミュートされます{(1)、Lively windowを除く)。 +(3)フォアグラウンドプロセスアルゴリズムにはいくつかの制限があります。詳細についてはwikiを確認してください。 +(4)アプリケーションルールが最も優先されます。 +(5)Webブラウザーは一時停止ではなく最小化されているため、場合によっては一時的に壁紙がデフォルトに戻ります。修正はすぐに来ます。 + + + オフ + + + オン + + + 他のアプリケーションにフォーカス: + + + その他のアプリケーションのフルスクリーン: + + + 一時停止アルゴリズム: + + + ロードに失敗しました + + + しばらくお待ちください + + + previewclip / thumbnailファイルを選択します。 + + + 壁紙として設定 + + + 一部の壁紙はディスプレイ全体に適切に広がりません。 + + + Windowsで開始: + + + 活発にアンインストールする前に、これのチェックを外してください。 + + + サポート + + + アニメーションGIF + + + Godotソフトウェア + + + HTML + + + その他 + + + Unity Software + + + ビデオ + + + ウェブサイト + + + ライブ壁紙システム + + + 透明UI: + + + 活発なウィンドウを半透明にします。 + + + 更新をライブで利用可能 + + + 動画プレーヤー: + + + Directshowには、追加プラグインのインストールが必要です。 + + + 壁紙の再生: + + + 表示を選択 + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/Resources.resx b/src/livelywpf/livelywpf/Properties/Resources.resx new file mode 100644 index 00000000..8c5bb09d --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Resources.resx @@ -0,0 +1,688 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + All Display(s) + + + XamlAnimatedGif + + + Low memory usage, high cpu usage + + + DirectShow + + + Lower cpu usage (depending on codec settings) + + + Kill(Free Memory) + + + Nothing + + + All Processes (Experimental) + + + Pause + + + Foreground Process + + + Per Display + + + Span(Experimental) + + + Media Foundation + + + DirectShow(Lav, ffdshow..) + + + + ..\docs\license.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + Enter commandline arguments for the application if any (optional, leave blank if none):- + + + Start Arguments + + + The selected wallpaper(application) has no graphical user interface(GUI). +Terminating application... + + + Failed to catch application window. +The wallpaper(application) is taking too long to start(more than ~30sec), it could be due to: +Virus scan/ Application is too big. +Wait & try again. (optionally you can edit the waiting time, check out wiki for more information.) +Terminating application... + + + Damaged wallpaper file, try redownloading. + + + Are you sure you want to permanently delete the wallpaper from the disk? + + + Confirm Deletion + + + Currently running as wallpaper, cannot delete! +Close this wallpaper to delete it. + + + Deletion Failed + + + This file format is not supported for drag & drop, open it in 'Type' page instead. + + + Lively: Not Supported + + + You are opening an external application as wallpaper. +Malicious applications can host malware, virus.. and do harm to your system. +Only continue if this application comes from a trusted source. + + + Warning + + + GIF file playback failed. +Is the GIF file corrupted? Try redownloading. + + + Lively cannot work properly with Windows High Contrast mode enabled! +Disable High Contrast mode & Try again. + + + You are about to open an external webpage on your browser. + +URL:- + + + Load Webpage? + + + Starting up external application.. + + + Media playback failed: Missing Codec/ Corrupted File. +Install LAV codec & Try switching to Directshow videoplayer. + +Further Instructions: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + Media playback failed: Missing Codec/ Corrupted File. +Don't forget to install LAV codec: +www.github.com/Nevcairiel/LAVFilters/releases + +Further Instructions: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + Currently restoring previous wallpaper(s), please wait. + + + Restoring previous wallpaper(s).. + + + Lively was not closed properly, starting in safe mode. +Do you wish to restore previously running wallpapers? +Error information is saved at:- + + + + Lively is already running! +If not-responding terminate process "livelywpf" in taskmanager & try again. + + + Enter website link to load, Shadertoy.com shader links are supported:- + + + Load webpage + + + You are about to load an external website. +Malicious Web pages can be harmful to your computer (malware, virus ..) +Only enter links to websites that you trust. + + + Warning + + + Web browser component is missing, either download separately:- +https://github.com/rocksdanister/lively-cef +OR +Download the full version of lively. + + + It looks like some settings needs to be set to make Lively work:- +1. Open This PC(My Computer) +2. Right-click empty area +3. Select Properties +4. Select Advanced System Settings +5. Under Performance tab select Settings +6. Enable Animate controls and elements inside windows & Apply. + +If Windows 7 just set - Adjust for best appearance & Apply. +If still not working, close & start Lively again/ restart windows. + + + About + + + Library + + + Settings + + + Type + + + I'm minimized to systemtray, right click lively icon for more options. + + + A new version is available! + + + Some wallpaper(s) were skipped because of missing file(s)! + + + Application Rules + + + Audio In: + + + Blocks browsers access to system audio. + + + Audio is always disabled in multiple monitor systems. + + + "Audio In" is disabled, Web audio visualisers will not work. + + + Audio Out: + + + Unmute/mute video player. + + + Web Browser: + + + Select web browser for web wallpapers(coming soon) + + + Close All Wallpapers + + + Coming Soon + + + Close All Wallpapers + + + Close Wallpaper + + + Delete Wallpaper + + + Exit + + + Export lively .zip + + + Open Lively + + + Show on Disk + + + Checking for update + + + Update Available! + + + Is this Beta software? + + + Lively is up-to-date! + + + Error Checking for Update + + + Create Wallpaper + + + Creating Lively zip file. + + + Display Pause Rule: + + + GIF Player: + + + Directshow requires additionals plugins to be installed. + + + Help + + + Ignore + + + Install Wallpaper + + + Select wallpaper type to load:- + + + Attribution: + + + What should I use? + + + Type: + + + Force 120FPS UI + + + Author: + + + Contact: + + + General: + settings tab + + + Require app restart: + settings tab + + + Video: + settings tab + + + Gif: + settings tab + + + Web Browser: + settings tab + + + Just drag and drop files if you prefer it that way instead. + + + Performance: + settings tab + + + Set wallpaper(s) playback behaviour based on running application:- + + + Add + + + Remove + + + Select Wallpaper Layout:- + + + Pick a wallpaper type to create:- + + + Library File: Create easy to share .zip file that loads wallpaper into Lively's library. +To simply play a file as wallpaper, this is not required; just drag and drop the file to lively window. + + + Contact Website(optional):- + + + License(optional):- + + + Title:- + + + These materials are not sponsored by or affiliated with Unity Technologies, Godot, Bizhawk, Shadertoy.com + + + Description:- + + + Select File + + + Thumbnail (200x200) + + + Create + + + Preview Gif (192x108) + + + Wallpaper Type:- + + + Files and Folders being added:- + + + Ok + + + Back + + + Installing Wallpaper + + + Media + + + Games + + + Retro + + + Other + + + Web + + + Audio Visualiser + + + Application + + + Lively + + + Rule + + + Disable Hardware Acceleration + + + This feature is currently in development. +Do NOT run programs such as CHROME, STEAM.. which spawn multiple Subprocesses. +THERE WILL BE BUGS & CRASHES, PROCEED WITH CAUTION!!! + + + Lively: Error + title for messagebox. + + + Please Wait + title for messagebox + + + Application + + + Animated GIF + + + Godot Application + + + Unity Application + + + Unity Audio Reactive + + + Video + + + Web + + + Web Audio Reactive + + + Animated Tile: + + + (Experimental) Wallpaper preview on tile. + + + Fille all the required text fields. + + + Wallpaper file not selected + + + Note: +(1) Lively window ignores these rules. +(2) Audio is always muted when other apps are in focus {except (1), Lively window}. +(3) Foreground Process algorithm has some limitations, check wiki for more information. +(4) Application Rules has the highest priority. + + + Off + + + On + + + Other Application Focused: + + + Other Application Fullscreen: + + + Pause Algorithm: + + + Load Failed + + + Please Wait + + + Select previewclip/thumbnail file. + + + Set as Wallpaper + + + Some wallpapers will not span across displays properly. + + + Start with Windows: + + + Make sure to uncheck this before uninstalling lively. + + + Support + + + Animated GIF + + + Godot Software + + + HTML + + + Other + + + Unity Software + + + Video + + + Website + + + Lively Wallpaper System + + + Transparent UI: + + + Make lively window semi-transparent. + + + Update available Lively + + + Video Player: + + + Directshow requires additionals plugins to be installed. + + + Wallpaper Playback: + + + Select Display + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/Resources.ru.resx b/src/livelywpf/livelywpf/Properties/Resources.ru.resx new file mode 100644 index 00000000..b358ede2 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Resources.ru.resx @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Все отображения + + + XamlAnimatedGif + + + Низкое использование памяти, высокое использование процессора + + + DirectShow + + + Более низкое использование процессора (в зависимости от настроек кодека) + + + Kill (Свободная память) + + + Nothing + + + Все процессы (экспериментальные) + + + Пауза + + + Процесс переднего плана + + + на дисплей + + + Спан (экспериментальный) + + + Media Foundation + + + DirectShow (Lav, ffdshow ..) + + + + ..\docs\license.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + Введите аргументы командной строки для приложения, если таковые имеются (необязательно, оставьте пустым, если их нет): - + + + Начальные аргументы + + + Выбранные обои (приложение) не имеют графического интерфейса пользователя (GUI). +Завершение приложения ... + + + Не удалось поймать окно приложения. +Обои (приложение) запускаются слишком долго (более ~ 30 секунд), это может быть связано с: +Проверка на вирусы / Приложение слишком большое. +Подождите & Попробуйте еще раз. (При желании вы можете отредактировать время ожидания, за дополнительной информацией обращайтесь к вики). +Завершение приложения ... + + + Поврежденный файл обоев, попробуйте загрузить заново. + + + Вы уверены, что хотите удалить обои с диска навсегда? + + + Подтвердить удаление + + + В настоящее время работает в качестве обоев, не может удалить! +Закройте эти обои, чтобы удалить их. + + + Ошибка удаления + + + Этот формат файла не поддерживается для перетаскивания & вместо этого откройте его на странице «Тип». + + + Lively: не поддерживается + + + Вы открываете внешнее приложение в качестве обоев. +Вредоносные программы могут содержать вредоносные программы, вирусы и наносить вред вашей системе. +Продолжайте, только если это приложение поступает из надежного источника. + + + Предупреждение + + + Ошибка воспроизведения файла GIF. +Файл GIF поврежден? Попробуйте перезагружать. + + + Lively не может работать должным образом при включенном режиме высокой контрастности Windows! +Отключить режим высокой контрастности & Попробуйте еще раз. + + + Вы собираетесь открыть внешнюю веб-страницу в своем браузере. + +URL: - + + + Загрузить веб-страницу? + + + Запуск внешнего приложения. + + + Ошибка воспроизведения мультимедиа: отсутствует кодек / поврежденный файл. +Установите кодек LAV & Попробуйте переключиться на видеоплеер Directshow. + +Дальнейшие инструкции: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + Ошибка воспроизведения мультимедиа: отсутствует кодек / поврежденный файл. +Не забудьте установить кодек LAV: +www.github.com/Nevcairiel/LAVFilters/releases + +Дальнейшие инструкции: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + В настоящее время восстановление предыдущих обоев, пожалуйста, подождите. + + + Восстановление предыдущих обоев. + + + Лайвли не был закрыт должным образом, начиная с безопасного режима. +Вы хотите восстановить ранее запущенные обои? +Информация об ошибке сохраняется в: - + + + + Lively уже запущен! +Если не отвечает, завершите процесс "livelywpf" в диспетчере задач & попробуйте еще раз. + + + Введите ссылку на сайт для загрузки, шейдерные ссылки Shadertoy.com поддерживаются: - + + + Загрузить веб-страницу + + + Вы собираетесь загрузить внешний веб-сайт. +Вредоносные веб-страницы могут быть вредны для вашего компьютера (вредоносные программы, вирусы ..) +Введите только ссылки на веб-сайты, которым вы доверяете. + + + Предупреждение + + + Компонент веб-браузера отсутствует, либо загрузите отдельно: - +https://github.com/rocksdanister/lively-cef +ИЛИ +Загрузите полную версию Lively. + + + Похоже, что некоторые настройки должны быть установлены, чтобы Lively работал: - +1. Откройте этот компьютер (мой компьютер) +2. Щелкните правой кнопкой мыши пустую область +3. Выберите Свойства +4. Выберите «Дополнительные параметры системы». +5. На вкладке «Быстродействие» выберите «Настройки». +6. Включите элементы управления Animate и элементы в окнах & Подать заявление. + +Если Windows 7 просто установлена ​​- отрегулируйте для лучшего внешнего вида & Подать заявление. +Если все еще не работает, закройте & снова запустить Lively / перезапустить Windows. + + + около + + + Библиотека + + + Настройки + + + Тип + + + Я сворачиваюсь в системный трей, щелкните правой кнопкой мыши на значке lively, чтобы получить дополнительные параметры. + + + Доступна новая версия! + + + Некоторые обои были пропущены из-за отсутствия файлов! + + + Правила применения + + + Аудио вход: + + + Блокирует доступ браузеров к системному аудио. + + + Аудио всегда отключено в системах с несколькими мониторами. + + + «Аудиовход» отключен, веб-аудио визуализаторы не будут работать. + + + Аудио выход: + + + Включить / выключить звук проигрывателя видео. + + + веб-браузер: + + + Выберите веб-браузер для веб-обоев (скоро) + + + Закрыть все обои + + + Скоро в продаже + + + Закрыть все обои + + + Закрыть обои + + + Удалить обои + + + Выход + + + Экспортировать живой .zip + + + Open Lively + + + Показать на диске + + + Проверка на наличие обновлений + + + Доступно обновление! + + + Это бета-версия программного обеспечения? + + + Lively актуален! + + + Ошибка проверки обновления + + + Создать обои + + + Создание живого zip-файла. + + + Показать правило паузы: + + + GIF Player: + + + Directshow требует установки дополнительных плагинов. + + + Справка + + + Игнорировать + + + Установить обои + + + Выберите тип обоев для загрузки: - + + + Атрибуция: + + + Что я должен использовать? + + + Тип: + + + Принудительно 120FPS UI + + + Автор: + + + Контакт: + + + Общие: + вкладка настроек + + + Требовать перезагрузки приложения: + вкладка настроек + + + Видео: + вкладка настроек + + + Gif: + вкладка настроек + + + веб-браузер: + вкладка настроек + + + Просто перетащите медиафайлы, если хотите, вместо этого. + + + Производительность: + вкладка настроек + + + Установить поведение воспроизведения обоев на основе запущенного приложения: - + + + Добавить + + + Удалить + + + Выберите макет обоев: - + + + Выберите тип обоев для создания: - + + + Библиотечный файл: создайте легкий для распространения ZIP-файл, который загружает обои в библиотеку Lively. +Чтобы просто воспроизвести файл в качестве обоев, это не требуется; просто перетащите файл в живое окно. + + + Контактный веб-сайт (необязательно): - + + + Лицензия (по желанию): - + + + Заголовок: - + + + Эти материалы не спонсируются и не связаны с Unity Technologies, Godot, Bizhawk, Shadertoy.com + + + Описание: - + + + Выбрать файл + + + Миниатюра (200x200) + + + Создать + + + Предварительный просмотр Gif (192x108) + + + Тип обоев: - + + + Добавляемые файлы и папки: - + + + ОК + + + Назад + + + Установка обоев + + + Средства массовой информации + + + Игры + + + ретро + + + Другое + + + Web + + + Аудио визуализатор + + + Применение + + + Лайвли + + + Правило + + + Отключить аппаратное ускорение + + + Эта функция в настоящее время в разработке. +НЕ запускайте такие программы, как CHROME, STEAM .., которые порождают несколько подпроцессов. +БУДУТ ЖУКИ & Аварии, продолжайте с осторожностью !!! + + + Лайвли: ошибка + заголовок для сообщения. + + + Пожалуйста, подождите + заголовок для сообщения + + + Применение + + + Анимированный GIF + + + Приложение Годо + + + Unity Application + + + Unity Audio Reactive + + + Видео + + + Web + + + Web Audio Reactive + + + Анимированная плитка: + + + (Экспериментальное, высокая загрузка ЦП) Воспроизвести предварительный просмотр обоев на плитке библиотеки. + + + Заполните все обязательные текстовые поля. + + + Файл обоев не выбран + + + Примечание: +(1) Живое окно игнорирует эти правила. +(2) Звук всегда отключается, когда в фокусе находятся другие приложения {кроме (1), окна Lively}. +(3) Алгоритм процесса переднего плана имеет некоторые ограничения, проверьте вики для получения дополнительной информации. +(4) Правила применения имеют наивысший приоритет. +(5) веб-браузер сворачивается, а не приостанавливается, поэтому вы увидите, что обои в некоторых случаях временно возвращаются к значениям по умолчанию; исправление скоро. + + + Off + + + На + + + Другое сфокусированное приложение: + + + Другое приложение в полноэкранном режиме: + + + Алгоритм паузы: + + + Ошибка загрузки + + + Пожалуйста, подождите + + + Выберите файл предварительного просмотра / файл эскиза. + + + Установить в качестве обоев + + + Некоторые обои не будут правильно отображаться на экранах. + + + Начать с Windows: + + + Обязательно снимите этот флажок перед удалением lively. + + + Поддержка + + + Анимированный GIF + + + Godot Software + + + HTML + + + Другое + + + Unity Software + + + Видео + + + Сайт + + + Lively Wallpaper System + + + Прозрачный интерфейс: + + + Сделать живое окно полупрозрачным. + + + Доступно обновление Lively + + + Видеоплеер: + + + Directshow требует установки дополнительных плагинов. + + + Обои для воспроизведения: + + + Выберите Показать + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/Resources.zh.Designer.cs b/src/livelywpf/livelywpf/Properties/Resources.zh.Designer.cs new file mode 100644 index 00000000..e69de29b diff --git a/src/livelywpf/livelywpf/Properties/Resources.zh.resx b/src/livelywpf/livelywpf/Properties/Resources.zh.resx new file mode 100644 index 00000000..90294d7d --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Resources.zh.resx @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 所有显示 + + + XamlAnimatedGif + + + 内存使用率低,cpu使用率高 + + + DirectShow + + + 降低CPU使用率(取决于编解码器设置) + + + 杀死(可用内存) + + + 没事 + + + 所有过程(实验) + + + 暂停 + + + 前景处理 + + + 每次展示 + + + 跨度(实验性) + + + 媒体基金会 + + + DirectShow(Lav,ffdshow ..) + + + + ..\docs\license.rtf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + 输入应用程序的命令行参数(如果有)(可选,如果没有则保留空白):- + + + 开始参数 + + + 所选墙纸(应用程序)没有图形用户界面(GUI)。 +终止应用程序... + + + 无法捕获应用程序窗口。 +墙纸(应用程序)启动时间过长(超过30秒),原因可能是: +病毒扫描/应用程序太大。 +等待和再试一次。 (可选地,您可以编辑等待时间,请查看Wiki以获取更多信息。) +终止应用程序... + + + 损坏的墙纸文件,请尝试重新下载。 + + + 您确定要从磁盘上永久删除墙纸吗? + + + 确认删除 + + + 当前正在作为墙纸运行,无法删除! +关闭此墙纸以将其删除。 + + + 删除失败 + + + 拖放不支持此文件格式。拖放,请改为在"类型"页面中打开它。 + + + 活跃:不受支持 + + + 您正在打开一个外部应用程序作为墙纸。 +恶意应用程序可能托管恶意软件,病毒..并损害您的系统。 +仅在此应用程序来自受信任的人/网站时继续。 + + + 警告 + + + GIF文件播放失败。 +GIF文件是否已损坏?尝试重新下载。 + + + Lively无法在启用Windows High Contrast模式的情况下正常工作! +禁用高对比度模式和再试一次。 + + + 您将要在浏览器上打开一个外部网页。 + +网址:- + + + 要加载网页吗? + + + 正在启动外部应用程序。 + + + 媒体播放失败:编解码器/文件损坏。 +安装LAV编解码器和尝试切换到Directshow视频播放器。 + +进一步的说明: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + 媒体播放失败:编解码器/文件损坏。 +不要忘记安装LAV编解码器: +www.github.com/Nevcairiel/LAVFilters/releases + +进一步的说明: +www.github.com/rocksdanister/lively/wiki/Video-Guide + + + 当前正在还原以前的墙纸,请等待。 + + + 恢复以前的壁纸。 + + + 从安全模式开始,Lively没有正确关闭。 +您是否要还原以前运行的壁纸? +错误信息保存在: + + + + 热闹已经开始了! +如果没有响应,请终止进程“ livelywpf”,然后重试。 + + + 输入要加载的网站链接,支持Shadertoy.com着色器链接:- + + + 加载网页 + + + 您将要加载外部网站。 +恶意网页可能对您的计算机有害(恶意软件,病毒..) +仅输入指向您信任的网站的链接。 + + + 警告 + + + 缺少Web浏览器组件,可以单独下载:- +https://github.com/rocksdanister/lively-cef +要么 +下载完整版本的lively。 + + + 似乎需要进行一些设置才能使Lively工作:- +1.打开这台电脑(我的电脑) +2.右键单击空白区域 +3.选择属性 +4.选择高级系统设置 +5.在性能选项卡下,选择设置 +6.在Windows&amp;中启用Animate控件和元素。应用。 + +如果仅设置了Windows 7,请调整以获取最佳外观&amp;应用。 +如果仍然无法正常工作,请关闭&amp;重新启动Lively /重新启动Windows。 + + + 关于 + + + + + + 设置 + + + 类型 + + + 将我最小化为系统托盘,右键单击生动的图标可获得更多选项。 + + + 有一个新版本! + + + 由于缺少文件而跳过了某些墙纸! + + + 应用规则 + + + 音频输入: + + + 阻止浏览器访问系统音频。 + + + 在多个监视器系统中始终禁用音频。 + + + "音频输入"被禁用,Web音频可视化工具将不起作用。 + + + 音频输出: + + + 取消静音/静音视频播放器。 + + + Web浏览器: + + + 为网络墙纸选择Web浏览器(即将推出) + + + 关闭所有壁纸 + + + 快来了 + + + 关闭所有壁纸 + + + 关闭墙纸 + + + 删除墙纸 + + + 退出 + + + 导出生动的.zip + + + 活泼开放 + + + 在磁盘上显示 + + + 检查更新 + + + 可用更新! + + + 这是Beta版软件吗? + + + 活泼是最新的! + + + 检查更新错误 + + + 创建墙纸 + + + 创建生动的zip文件。 + + + 显示暂停规则: + + + GIF播放器: + + + Directshow需要安装其他插件。 + + + 帮助 + + + 忽略 + + + 安装墙纸 + + + 选择要加载的墙纸类型:- + + + 归因: + + + 我应该使用什么? + + + 类型: + + + 强制120FPS UI + + + 作者: + + + 联系人: + + + 常规: + 设置标签 + + + 其他(需要重新启动应用程序): + 设置标签 + + + 视频: + 设置标签 + + + Gif: + 设置标签 + + + Web浏览器: + 设置标签 + + + 如果您喜欢那样,只需拖放媒体文件即可。 + + + 性能: + 设置标签 + + + 根据运行的应用程序设置墙纸的播放行为:- + + + 添加 + + + 删除 + + + 选择墙纸布局:- + + + 选择墙纸类型以创建:- + + + 库文件:创建易于共享的.zip文件,将墙纸加载到Lively的库中。 +只需将文件作为墙纸播放,这不是必需的。 只需将文件拖放到生动的窗口即可。 + + + 联系网站(可选):- + + + 许可证(可选):- + + + 标题:- + + + 这些材料不是由Unity Technologies,Godot,Bizhawk,Shadertoy.com赞助或关联的 + + + 描述:- + + + 选择文件 + + + 缩图(200x200) + + + 创建 + + + 预览Gif(192x108) + + + 墙纸类型:- + + + 正在添加的文件和文件夹:- + + + 好:- + + + 背部:- + + + 安装墙纸 + + + 媒体 + + + 游戏 + + + 复古 + + + 其他 + + + 网络 + + + 音频可视化工具 + + + 应用 + + + Lively + + + 规则 + + + 禁用硬件加速 + + + 此功能目前正在开发中。 +不要运行诸如CHROME,STEAM ..之类的程序,这些程序会产生多个子进程。 +小心操作将有伤痕和破损!!!! + + + 生动:错误 + 消息框标题。 + + + 活泼:等待 + 消息框标题 + + + 应用 + + + 动画的gif + + + Godot应用 + + + Unity应用 + + + Unity音频反应式 + + + 视频 + + + 网页 + + + 网页音频无功 + + + 动画图块: + + + (实验性,cpu使用率高)在库图块上播放墙纸预览。 + + + 填写所有必填的文本字段。 + + + 未选择墙纸文件 + + + 注意: +(1)活泼的窗户忽略了这些规则。 +(2)当其他应用程序处于焦点状态时,音频始终处于静音状态{(1),"活动窗口"除外。 +(3)前景处理算法有一些限制,请查阅Wiki了解更多信息。 +(4)申请规则具有最高优先级。 +(5)正在最小化Web浏览器而不是暂停它,因此在某些情况下您会看到墙纸暂时恢复为默认value;修复即将推出。 + + + 关闭 + + + 打开 + + + 其他应用重点: + + + 全屏其他应用程序: + + + 暂停算法: + + + 加载失败 + + + 请稍候 + + + 选择预览剪辑/缩略图文件。 + + + 设置为墙纸 + + + 某些墙纸将无法正确跨显示器显示。 + + + 从Windows开始: + + + 请确保取消选中此复选框,然后再进行生动的卸载。 + + + 支持 + + + 动画GIF + + + Godot软件 + + + HTML + + + 其他 + + + Unity软件 + + + 视频 + + + 网站 + + + Lively 墙纸系统 + + + 透明UI: + + + 使活动窗口透明 + + + 有可用更新Lively + + + 视频播放器: + + + Directshow需要安装其他插件。 + + + 墙纸播放: + + + 选择显示 + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/Properties/Settings.Designer.cs b/src/livelywpf/livelywpf/Properties/Settings.Designer.cs new file mode 100644 index 00000000..aa4443c9 --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace livelywpf.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/src/livelywpf/livelywpf/Properties/Settings.settings b/src/livelywpf/livelywpf/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/src/livelywpf/livelywpf/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/WebWindow.xaml b/src/livelywpf/livelywpf/WebWindow.xaml new file mode 100644 index 00000000..f2ad67a2 --- /dev/null +++ b/src/livelywpf/livelywpf/WebWindow.xaml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/src/livelywpf/livelywpf/WebWindow.xaml.cs b/src/livelywpf/livelywpf/WebWindow.xaml.cs new file mode 100644 index 00000000..7a632cfd --- /dev/null +++ b/src/livelywpf/livelywpf/WebWindow.xaml.cs @@ -0,0 +1,223 @@ +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.Shapes; + +//using CefSharp; +//using CefSharp.Wpf; +//using CefSharp.WinForms; +//using System.Windows.Forms; +//using CefSharp.SchemeHandler; + +namespace livelywpf +{ + /// + /// Interaction logic for WebWindow.xaml + /// + public partial class WebWindow : Window + { + + public static string currURL = null; + //private IKeyboardMouseEvents mouseHook; + //private static bool mHooked = false; + public ChromiumWebBrowser chromeBrowser; + public bool cefInitialized = false; + + string path; + public WebWindow(string _path) + { + InitializeComponent(); + path = _path; + //InitializeChromium(path); + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + InitializeChromium(path); + // Create the interop host control. + System.Windows.Forms.Integration.WindowsFormsHost host = + new System.Windows.Forms.Integration.WindowsFormsHost(); + + // Create the MaskedTextBox control. + //MaskedTextBox mtbDate = new MaskedTextBox("00/00/0000"); + + // Assign the MaskedTextBox control as the host control's child. + host.Child = chromeBrowser;//mtbDate; + + // Add the interop host control to the Grid + // control's collection of child controls. + this.webGrid.Children.Add(host); + + } + + void InitializeChromium(string path) + { + + //Program.filePath = path; + CefSettings settings = new CefSettings(); + settings.RegisterScheme(new CefCustomScheme + { + SchemeName = "localfolder", + DomainName = "cefsharp", + SchemeHandlerFactory = new FolderSchemeHandlerFactory( + rootFolder: @"C:\Users\rocks\Documents\DEMO\WEB\RainEffect-master\demo", + hostName: "cefsharp", + defaultPage: "index.html" // will default to index.html + ) + }); + + + //ref: https://magpcss.org/ceforum/apidocs3/projects/(default)/_cef_browser_settings_t.html#universal_access_from_file_urls + //settings.CefCommandLineArgs.Add("allow-universal-access-from-files", "1"); //UNSAFE, Testing Only! + //settings.CefCommandLineArgs.Add("--mute-audio", "1"); + + Cef.Initialize(settings); + //shadertoy link handling. + if (path.Contains("shadertoy.com/view")) + { + if (!path.Contains("https://")) + path = "https://" + path; + + path = path.Replace("view/", "embed/"); + ShadertoyTmpHTML(path); + path = AppDomain.CurrentDomain.BaseDirectory + @"\\shadertoy_url.html"; + //Program.filePath = path; + } + // Create a browser component + //chromeBrowser = new ChromiumWebBrowser(@path); + chromeBrowser = new ChromiumWebBrowser("localfolder://cefsharp/"); + //chromeBrowser = new ChromiumWebBrowser(@"http://localhost:8000/"); + // Add it to the form and fill it to the form window. + //webGrid.Children.Add(chromeBrowser); + //this.Controls.Add(chromeBrowser); + chromeBrowser.Dock = DockStyle.Fill; + + //Subscribe(); //mousehook + + //chromeBrowser.IsBrowserInitializedChanged += ChromeBrowser_IsBrowserInitializedChanged; + chromeBrowser.IsBrowserInitializedChanged += ChromeBrowser_IsBrowserInitializedChanged1; + //chromeBrowser.LoadError += ChromeBrowser_LoadError; + //chromeBrowser.Paint += ChromeBrowser_Paint; + + //chromeBrowser.Dispose(); + } + + public void MuteBrowser() + { + // chromeBrowser. + } + + private void ChromeBrowser_IsBrowserInitializedChanged1(object sender, EventArgs e) + { + cefInitialized = true; + //throw new NotImplementedException(); + } + + /* + private void ChromeBrowser_Paint(object sender, PaintEventArgs e) + { + System.Diagnostics.Debug.WriteLine("On PAINT CEF !!"); + //Bitmap newBitmap = new Bitmap(e.Width, e.Height, 4 * e.Width, System.Drawing.Imaging.PixelFormat.Format32bppRgb, e.Buffer); + //throw new NotImplementedException(); + } + */ + + private void ChromeBrowser_LoadError(object sender, LoadErrorEventArgs e) + { + System.Diagnostics.Debug.WriteLine("ERROR LOAD !!"); + //chromeBrowser.Reload(true); + + //throw new NotImplementedException(); + } + + private void ShadertoyTmpHTML(string path) + { + + string text = @" + Digital Brain "; + // WriteAllText creates a file, writes the specified string to the file, + // and then closes the file. You do NOT need to call Flush() or Close(). + System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + @"\\shadertoy_url.html", text); + + } + + /* + private void ChromeBrowser_IsBrowserInitializedChanged(object sender, CefSharp.IsBrowserInitializedChangedEventArgs e) + { + cefInitialized = e.IsBrowserInitialized; + //throw new NotImplementedException(); + } + */ + + public void LoadURL(string path) + { + // if (!path.Equals("about:blank")) + // Subscribe(); //mousehook + + if (path.Contains("shadertoy.com/view")) + { + if (!path.Contains("https://")) + path = "https://" + path; + + path = path.Replace("view/", "embed/"); + ShadertoyTmpHTML(path); + path = AppDomain.CurrentDomain.BaseDirectory + @"\\shadertoy_url.html"; + // Program.filePath = path; + } + + chromeBrowser.Load(@path); + } + + public string CurrURL() + { + return chromeBrowser.Address; + } + + public void Minimize() + { + // this.WindowState = FormWindowState.Minimized; + //this.Hide(); + this.WindowState = WindowState.Minimized; + this.Hide(); + } + + public void Maximize() + { + this.WindowState = WindowState.Normal; + this.Show(); + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + //not needed, exit event of app is hooked. + //Cef.Shutdown(); + + chromeBrowser.Dispose(); + cefInitialized = false; + } + + + /* + private void WebForm_FormClosing(object sender, FormClosingEventArgs e) + { + + chromeBrowser.IsBrowserInitializedChanged -= ChromeBrowser_IsBrowserInitializedChanged; + Unsubscribe(); //mousehook + Cef.Shutdown(); + + } + */ + } + +} diff --git a/src/livelywpf/livelywpf/app.manifest b/src/livelywpf/livelywpf/app.manifest new file mode 100644 index 00000000..a7660bec --- /dev/null +++ b/src/livelywpf/livelywpf/app.manifest @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + PerMonitor + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/dialogues_general/ApplicationRuleDialogWindow.xaml b/src/livelywpf/livelywpf/dialogues_general/ApplicationRuleDialogWindow.xaml new file mode 100644 index 00000000..10582b73 --- /dev/null +++ b/src/livelywpf/livelywpf/dialogues_general/ApplicationRuleDialogWindow.xaml @@ -0,0 +1,29 @@ + + + + diff --git a/src/livelywpf/livelywpf/dialogues_wpcreator/Page_Ext.xaml.cs b/src/livelywpf/livelywpf/dialogues_wpcreator/Page_Ext.xaml.cs new file mode 100644 index 00000000..698ba2d0 --- /dev/null +++ b/src/livelywpf/livelywpf/dialogues_wpcreator/Page_Ext.xaml.cs @@ -0,0 +1,421 @@ +using Ionic.Zip; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +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.Forms; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using MessageBox = System.Windows.MessageBox; +using Path = System.IO.Path; +using System.Globalization; +using Microsoft.Win32; + +namespace livelywpf +{ + /// + /// Interaction logic for Page_Ext.xaml + /// + public partial class PageZipCreate : Page + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public class BindClass + { + public SaveData.LivelyInfo LivelyInfo { get; set; } + public BitmapImage Img { get; set; } + + public BindClass(SaveData.LivelyInfo info) + { + if (info != null) + { + LivelyInfo = info; + Img = LoadImage(info.Thumbnail); + } + } + private BitmapImage LoadImage(string filename) + { + try + { + using (var stream = File.OpenRead(filename)) + { + var bmp = new BitmapImage(); + bmp.BeginInit(); + bmp.StreamSource = stream; + bmp.CacheOption = BitmapCacheOption.OnLoad; + bmp.EndInit(); + return bmp; + } + } + catch (Exception) + { + return null; + } + } + + } + + private SaveData.LivelyInfo tmpInfo = new SaveData.LivelyInfo(); + private ObservableCollection data = new ObservableCollection(); + + public PageZipCreate() + { + InitializeComponent(); + data.Add(new BindClass(tmpInfo)); + PreviewPanel.ItemsSource = data; + + foreach (var item in wallpaperTypes) + { + comboBoxType.Items.Add(item.LocalisedType); + } + comboBoxType.SelectedIndex = 0; + } + + private class FileFilter + { + public SetupDesktop.WallpaperType Type { get; set; } + public string FilterText { get; set; } + public string LocalisedType { get; set; } + + public FileFilter(SetupDesktop.WallpaperType type, string filterText) + { + this.Type = type; + this.FilterText = filterText; + + if (this.Type == SetupDesktop.WallpaperType.video) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeVideo; + } + else if (this.Type == SetupDesktop.WallpaperType.app) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeApp; + } + else if(this.Type == SetupDesktop.WallpaperType.godot) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeGodot; + } + else if (this.Type == SetupDesktop.WallpaperType.unity) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeUnity; + } + else if (this.Type == SetupDesktop.WallpaperType.unity_audio) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeUnityAudio; + } + else if (this.Type == SetupDesktop.WallpaperType.web) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeWeb; + } + else if (this.Type == SetupDesktop.WallpaperType.web_audio) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeWebAudio; + } + else if (this.Type == SetupDesktop.WallpaperType.gif) + { + LocalisedType = Properties.Resources.txtLivelyWallpaperTypeGIF; + } + else + { + LocalisedType = Type.ToString(); + } + } + } + + readonly FileFilter[] wallpaperTypes= new FileFilter[] { + new FileFilter(SetupDesktop.WallpaperType.video, "All Videos Files |*.dat; *.wmv; *.3g2; *.3gp; *.3gp2; *.3gpp; *.amv; *.asf; *.avi; *.bin; *.cue; *.divx; *.dv; *.flv; *.gxf; *.iso; *.m1v; *.m2v; *.m2t; *.m2ts; *.m4v; " + + " *.mkv; *.mov; *.mp2; *.mp2v; *.mp4; *.mp4v; *.mpa; *.mpe; *.mpeg; *.mpeg1; *.mpeg2; *.mpeg4; *.mpg; *.mpv2; *.mts; *.nsv; *.nuv; *.ogg; *.ogm; *.ogv; *.ogx; *.ps; *.rec; *.rm; *.rmvb; *.tod; *.ts; *.tts; *.vob; *.vro; *.webm"), + new FileFilter(SetupDesktop.WallpaperType.gif,"Animated GIF (*.gif) |*.gif"), new FileFilter(SetupDesktop.WallpaperType.web, "Web Page (*.html) |*.html"), + new FileFilter(SetupDesktop.WallpaperType.web_audio, "Audio Visualiser(web) (*.html) |*.html"), new FileFilter(SetupDesktop.WallpaperType.unity,"Unity Game Executable |*.exe"), + new FileFilter(SetupDesktop.WallpaperType.unity_audio,"Unity Audio Visualiser |*.exe"), new FileFilter(SetupDesktop.WallpaperType.app,"Application |*.exe"), + new FileFilter(SetupDesktop.WallpaperType.godot,"Godot Game Executable |*.exe") + }; + + List folderContents = new List(); + private void Button_Click_Browse(object sender, RoutedEventArgs e) //application + { + // folderContents.Clear(); + if (comboBoxType.SelectedIndex == -1) + return; + + OpenFileDialog openFileDialog1 = new OpenFileDialog(); + //var result = Array.Find(wallpaperTypes,x => x.Type == comboBoxType.SelectedItem); + var result = wallpaperTypes[comboBoxType.SelectedIndex]; + openFileDialog1.Filter = result.FilterText; + //openFileDialog1.Title = "Select the file, folder contents will be added based on wallpaper type"; + if (openFileDialog1.ShowDialog() == true) + { + tmpInfo.FileName = openFileDialog1.FileName; + } + else + { + return; + } + + if (result.Type == SetupDesktop.WallpaperType.video || result.Type == SetupDesktop.WallpaperType.gif) + { + folderContents.Add(tmpInfo.FileName); + } + else + { + folderContents.AddRange( Directory.GetFiles( Directory.GetParent( tmpInfo.FileName ).ToString() , "*.*", SearchOption.AllDirectories) ); + } + + CreateWallpaperAddedFiles w = new CreateWallpaperAddedFiles(folderContents) + { + Owner = Application.Current.MainWindow, + WindowStartupLocation = WindowStartupLocation.CenterOwner + }; + w.ShowDialog(); + + if (w.DialogResult.HasValue && w.DialogResult.Value) //ok btn + { + //SaveData.SaveWallpaperMetaData(tmpInfo, ) + } + else //back btn + { + folderContents.Clear(); + } + } + + private async void Button_Create_Click(object sender, RoutedEventArgs e) + { + tmpInfo.Title = textboxTitle.Text; + tmpInfo.Author = textboxAuthor.Text; + tmpInfo.Desc = textboxDesc.Text; + tmpInfo.Contact = textboxWebsite.Text; + tmpInfo.License = textboxLicense.Text; + //tmpInfo.Type = (SetupDesktop.WallpaperType)comboBoxType.SelectedItem; + tmpInfo.Type = wallpaperTypes[comboBoxType.SelectedIndex].Type; + tmpInfo.Arguments = textboxArgs.Text; + + if (folderContents.Count == 0 || String.IsNullOrWhiteSpace(tmpInfo.FileName)) + { + MessageBox.Show(Properties.Resources.txtMsgSelectWallpaperFile); + return; + } + + if ( String.IsNullOrEmpty(tmpInfo.Title) || String.IsNullOrEmpty(tmpInfo.Desc) || String.IsNullOrEmpty(tmpInfo.Author) + )//|| String.IsNullOrEmpty(tmpInfo.contact) ) + { + MessageBox.Show(Properties.Resources.txtMsgFillAllFields); + return; + } + + if( !File.Exists(tmpInfo.Thumbnail) || !File.Exists(tmpInfo.Preview) ) + { + MessageBox.Show(Properties.Resources.txtSelectPreviewThumb); + return; + } + + SaveFileDialog saveFileDialog1 = new SaveFileDialog + { + Title = "Select location to save the file", + Filter = "Lively/zip file|*.zip" + }; + + if (saveFileDialog1.ShowDialog() == true) + { + if (!String.IsNullOrEmpty(saveFileDialog1.FileName)) + { + //to write to Livelyinfo.json file only, tmp object. + SaveData.LivelyInfo tmp = new SaveData.LivelyInfo(tmpInfo); + tmp.FileName = Path.GetFileName(tmp.FileName); + tmp.Preview = Path.GetFileName(tmp.Preview); + tmp.Thumbnail = Path.GetFileName(tmp.Thumbnail); + + System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\tmpdata"); + SaveData.SaveWallpaperMetaData(tmp, AppDomain.CurrentDomain.BaseDirectory + "\\tmpdata"); + + /* + //if previous livelyinfo.json file(s) exists in wallpaper directory, remove all of them. + folderContents.RemoveAll(x => Path.GetFileName(x).Equals(Path.GetFileName(folderContents[folderContents.Count - 1]), + StringComparison.InvariantCultureIgnoreCase)); + */ + folderContents.Add(AppDomain.CurrentDomain.BaseDirectory + @"tmpdata\LivelyInfo.json"); + + //btnCreateWallpaer.IsEnabled = false; + await CreateZipFile(saveFileDialog1.FileName, folderContents); + + string folderPath = System.IO.Path.GetDirectoryName(saveFileDialog1.FileName); + if (Directory.Exists(folderPath)) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + Arguments = folderPath, + FileName = "explorer.exe" + }; + Process.Start(startInfo); + } + + //this.NavigationService.GoBack(); //won't work, since prev is window, not page. + var wnd = Window.GetWindow(this); + wnd.Close(); + } + } + else + { + return; + } + + } + + private async Task CreateZipFile(string savePath, List documentPaths) + { + string baseDirectory = Directory.GetParent(tmpInfo.FileName).ToString(); + try + { + using (ZipFile zip = new ZipFile(savePath)) + { + zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression; + zip.ZipErrorAction = ZipErrorAction.Throw; + + //relative path calculations. + if (documentPaths.Count > 0) + { + //livelyinfo.json file in root. + zip.AddFile(documentPaths[documentPaths.Count - 1], ""); + //root directory of zip. + zip.AddFile(tmpInfo.Thumbnail, ""); + zip.AddFile(tmpInfo.Preview, ""); + + for (int i = 0; i < (documentPaths.Count - 1); i++) + { + try + { + //adding files in root directory of zip, maintaining folder structure. + zip.AddFile(documentPaths[i], Path.GetDirectoryName(documentPaths[i]).Replace(baseDirectory, string.Empty)); + } + catch + { + //ignore Liveinfo.json, preview, thumbnail file if already exists in the wallpaper path(from previous wp zip maybe). + //Note: will skip other repeating files too in the path, should not be an issue in this particular case. + Logger.Info("zip: ignoring some files due to repeated filename."); + } + } + } + + zip.SaveProgress += Zip_SaveProgress; + + await Task.Run(() => zip.Save()); + } + } + catch(Ionic.Zip.ZipException e1) + { + MessageBox.Show("File creation failure:" + e1.ToString()); + Logger.Error(e1.ToString()); + } + catch(Exception e2) + { + MessageBox.Show("File creation failure:" + e2.ToString()); + Logger.Error(e2.ToString()); + } + } + + private bool initializeProgressbar = false; + private void Zip_SaveProgress(object sender, SaveProgressEventArgs e) + { + if (e.EntriesTotal != 0) + { + if (!initializeProgressbar) + { + this.Dispatcher.Invoke(() => + { + zipProgressBar.Minimum = 0; + zipProgressBar.Maximum = e.EntriesTotal; + }); + + initializeProgressbar = true; + } + + this.Dispatcher.Invoke(() => + { + zipProgressBar.Value = e.EntriesSaved; + }); + + } + } + + private void ThumbnailBtn_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Filter = "Image (*.jpg) |*.jpg; *.jpeg", + Title = "Select 200x200 Image File" + }; + if (openFileDialog1.ShowDialog() == true) + { + using (var imageStream = File.OpenRead(openFileDialog1.FileName)) + { + var decoder = BitmapDecoder.Create(imageStream, BitmapCreateOptions.IgnoreColorProfile, + BitmapCacheOption.Default); + var height = decoder.Frames[0].PixelHeight; + var width = decoder.Frames[0].PixelWidth; + + if(height != 200 & width != 200) + { + MessageBox.Show("Select ONLY 200x200(width x height) image thumbnail file"); + return; + } + else + { + tmpInfo.Thumbnail = openFileDialog1.FileName; + data.Clear(); + data.Add(new BindClass(tmpInfo)); + } + } + } + else + { + return; + } + } + + private void PreviewClipBtn_Click(object sender, RoutedEventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog + { + Filter = "Animated GIF (*.gif) |*.gif", + Title = "Select 192x108 GIF File" + }; + if (openFileDialog1.ShowDialog() == true) + { + //var size = MainWindow.GetVideoSize(openFileDialog1.FileName); + + using (var imageStream = File.OpenRead(openFileDialog1.FileName)) + { + var decoder = BitmapDecoder.Create(imageStream, BitmapCreateOptions.IgnoreColorProfile, + BitmapCacheOption.Default); + var height = decoder.Frames[0].PixelHeight; + var width = decoder.Frames[0].PixelWidth; + + if (width != 192 && height != 108) + { + MessageBox.Show("Select ONLY 192x108(width x height) GIF preview file"); + return; + } + else + { + tmpInfo.Preview = openFileDialog1.FileName; + data.Clear(); + data.Add(new BindClass(tmpInfo)); + } + } + } + else + { + return; + } + } + + } +} diff --git a/src/livelywpf/livelywpf/display/DisplayID.xaml b/src/livelywpf/livelywpf/display/DisplayID.xaml new file mode 100644 index 00000000..6d99e880 --- /dev/null +++ b/src/livelywpf/livelywpf/display/DisplayID.xaml @@ -0,0 +1,15 @@ + + + + + diff --git a/src/livelywpf/livelywpf/display/DisplayID.xaml.cs b/src/livelywpf/livelywpf/display/DisplayID.xaml.cs new file mode 100644 index 00000000..141ad30d --- /dev/null +++ b/src/livelywpf/livelywpf/display/DisplayID.xaml.cs @@ -0,0 +1,59 @@ +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.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using System.Windows.Threading; + +namespace livelywpf +{ + /// + /// Interaction logic for DisplayID.xaml + /// + public partial class DisplayID : Window + { + private int xPos = 0 , yPos = 0; + public DisplayID(string id,int xPos, int yPos, bool destroyAfterElapsedTime = false, int elapsedTime = 5) + { + InitializeComponent(); + this.xPos = xPos; + this.yPos = yPos; + + label.Text = id; + if (destroyAfterElapsedTime) + { + DispatcherTimer timer = new DispatcherTimer + { + Interval = TimeSpan.FromSeconds(elapsedTime) + }; + timer.Tick += TimerTick; + timer.Start(); + } + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + IntPtr windowHandle = new WindowInteropHelper(this).Handle; + NativeMethods.SetWindowPos(windowHandle, 1, xPos, yPos, 0, 0, 0x0010 | 0x0001); //ignores dpi, this.Left, this.Right is unreliable due to dpi differences.changes ? (SWP_NOACTIVATE,SWP_NOSIZE & Bottommost) + //NativeMethods.SetWindowPos(windowHandle, 1, 0, 0, 0, 0, 0x0002 | 0x0010 | 0x0001); // SWP_NOMOVE ,SWP_NOACTIVATE,SWP_NOSIZE & Bottom most. + } + + private void TimerTick(object sender, EventArgs e) + { + DispatcherTimer timer = (DispatcherTimer)sender; + timer.Stop(); + timer.Tick -= TimerTick; + Close(); + } + + } +} diff --git a/src/livelywpf/livelywpf/display/DisplayLayoutWindow.xaml b/src/livelywpf/livelywpf/display/DisplayLayoutWindow.xaml new file mode 100644 index 00000000..59fac494 --- /dev/null +++ b/src/livelywpf/livelywpf/display/DisplayLayoutWindow.xaml @@ -0,0 +1,57 @@ + + + + + diff --git a/src/livelywpf/livelywpf/display/DisplayLayoutWindow.xaml.cs b/src/livelywpf/livelywpf/display/DisplayLayoutWindow.xaml.cs new file mode 100644 index 00000000..279955d5 --- /dev/null +++ b/src/livelywpf/livelywpf/display/DisplayLayoutWindow.xaml.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +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.Shapes; +using static livelywpf.SaveData; + +namespace livelywpf +{ + /// + /// Interaction logic for DisplayLayoutWindow.xaml + /// + public partial class DisplayLayoutWindow : Window + { + private ObservableCollection displayLBItems = new ObservableCollection(); + + List displayIDWindows = new List(); + private MainWindow mainWindow; + public DisplayLayoutWindow(MainWindow obj) + { + InitializeComponent(); + + mainWindow = obj; + if ((int)SaveData.config.WallpaperArrangement >= 0 && (int)SaveData.config.WallpaperArrangement <= 1) + { + displayLayoutSelect.SelectedIndex = (int)SaveData.config.WallpaperArrangement; + } + else + { + SaveData.config.WallpaperArrangement = 0; + SaveData.SaveConfig(); + displayLayoutSelect.SelectedIndex = 0; + } + displayLayoutSelect.SelectionChanged += ComboBox_SelectionChanged; + + DisplayLB.ItemsSource = displayLBItems; + UpdateDisplayListBox(); + + //screen identification + foreach (var item in System.Windows.Forms.Screen.AllScreens) + { + DisplayID id = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + //does not work properly in different dpi situations, using setwindowpos instead. + //Left = item.Bounds.X, + //Top = item.Bounds.Y, + }; + id.Show(); + displayIDWindows.Add(id); + } + } + + private void UpdateDisplayListBox() + { + string filePath; + int i; + foreach (var scr in System.Windows.Forms.Screen.AllScreens) + { + filePath = null; + if ((i = SetupDesktop.wallpapers.FindIndex(x => x.DeviceName == scr.DeviceName)) != -1) + { + filePath = SetupDesktop.wallpapers[i].FilePath;// = System.IO.Path.GetFileName(SetupDesktop.wallpapers[i].filePath); + } + displayLBItems.Add(new DisplayListBox(scr.DeviceName, filePath)); + } + } + + private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (displayLayoutSelect.SelectedIndex == -1) + return; + + SaveData.config.WallpaperArrangement = (SaveData.WallpaperArrangement) displayLayoutSelect.SelectedIndex; + SaveData.SaveConfig(); + + //close all currently running wp's & reset ui + SetupDesktop.CloseAllWallpapers(); + foreach (var item in displayLBItems) + { + item.FileName = null; + item.FilePath = null; + } + } + + + private void ButtonCloseAll_Click(object sender, RoutedEventArgs e) + { + SetupDesktop.CloseAllWallpapers(); + + foreach (var item in displayLBItems) + { + item.FileName = null; + item.FilePath = null; + } + //displayLBItems.Clear(); + //UpdateDisplayListBox(); + } + private void MenuItem_Close_Click(object sender, RoutedEventArgs e) + { + if (DisplayLB.SelectedIndex == -1) + return; + + SetupDesktop.CloseWallpaper(displayLBItems[DisplayLB.SelectedIndex].DisplayDevice); + + foreach (var item in displayLBItems) + { + if(item.DisplayDevice.Equals(displayLBItems[DisplayLB.SelectedIndex].DisplayDevice)) + { + item.FileName = null; + item.FilePath = null; + break; + } + } + } + + private void MenuItem_ShowLocation_Click(object sender, RoutedEventArgs e) + { + if (DisplayLB.SelectedIndex == -1) + return; + + + foreach (var item in displayLBItems) + { + if (item.DisplayDevice.Equals(displayLBItems[DisplayLB.SelectedIndex].DisplayDevice)) + { + if (item.FilePath != null) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + Arguments = System.IO.Path.GetDirectoryName(item.FilePath), + FileName = "explorer.exe" + }; + Process.Start(startInfo); + } + break; + } + } + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + foreach (var item in displayIDWindows) + { + item.Close(); + } + } + + } +} diff --git a/src/livelywpf/livelywpf/display/DisplaySelectWindow.xaml b/src/livelywpf/livelywpf/display/DisplaySelectWindow.xaml new file mode 100644 index 00000000..954d7b76 --- /dev/null +++ b/src/livelywpf/livelywpf/display/DisplaySelectWindow.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/livelywpf/livelywpf/display/DisplaySelectWindow.xaml.cs b/src/livelywpf/livelywpf/display/DisplaySelectWindow.xaml.cs new file mode 100644 index 00000000..c2a00129 --- /dev/null +++ b/src/livelywpf/livelywpf/display/DisplaySelectWindow.xaml.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +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.Shapes; +using static livelywpf.SaveData; + +namespace livelywpf +{ + /// + /// Interaction logic for DisplaySelectWindow.xaml + /// + public partial class DisplaySelectWindow : Window + { + private ObservableCollection displayLBItems = new ObservableCollection(); + + List displayIDWindows = new List(); + public static string selectedDisplay = null; + public DisplaySelectWindow() + { + InitializeComponent(); + selectedDisplay = null; + + DisplayLB.ItemsSource = displayLBItems; + UpdateDisplayListBox(); + + //screen identification. + foreach (var item in System.Windows.Forms.Screen.AllScreens) + { + DisplayID id = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + //does not work properly in different dpi situations, using setwindowpos instead. + //Left = item.Bounds.X, + //Top = item.Bounds.Y + }; + id.Show(); + displayIDWindows.Add(id); + } + + } + + private void UpdateDisplayListBox() + { + string filePath; + int i; + foreach (var scr in System.Windows.Forms.Screen.AllScreens) + { + filePath = null; + if ((i = SetupDesktop.wallpapers.FindIndex(x => x.DeviceName == scr.DeviceName)) != -1) + { + filePath = SetupDesktop.wallpapers[i].FilePath; + } + displayLBItems.Add(new DisplayListBox(scr.DeviceName, filePath)); + } + //displayLBItems.Add(new DisplayListBox("\\\\.\\DISPLAY2", null)); + //displayLBItems.Add(new DisplayListBox("\\\\.\\DISPLAY3", null)); + //displayLBItems.Add(new DisplayListBox("\\\\.\\DISPLAY4", null)); + } + + private void DisplayLB_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (DisplayLB.SelectedIndex == -1) + return; + + selectedDisplay = displayLBItems[DisplayLB.SelectedIndex].DisplayDevice; + this.Close(); + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + foreach (var item in displayIDWindows) + { + item.Close(); + } + } + + } +} diff --git a/src/livelywpf/livelywpf/display/DpiHelper.cs b/src/livelywpf/livelywpf/display/DpiHelper.cs new file mode 100644 index 00000000..4adfb76e --- /dev/null +++ b/src/livelywpf/livelywpf/display/DpiHelper.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; + +//credit: https://github.com/emoacht/WpfBuiltinDpiTest +namespace livelywpf +{ + internal class DpiHelper + { + #region Win32 (New) + + [DllImport("User32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool EnableNonClientDpiScaling( + IntPtr hwnd); + + public enum DPI_AWARENESS + { + DPI_AWARENESS_INVALID = -1, + DPI_AWARENESS_UNAWARE = 0, + DPI_AWARENESS_SYSTEM_AWARE = 1, + DPI_AWARENESS_PER_MONITOR_AWARE = 2 + } + + public enum DPI_AWARENESS_CONTEXT + { + DPI_AWARENESS_CONTEXT_DEFAULT = 0, // Undocumented + DPI_AWARENESS_CONTEXT_UNAWARE = -1, // Undocumented + DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = -2, // Undocumented + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = -3 // Undocumented + } + + [DllImport("User32.dll")] + public static extern DPI_AWARENESS_CONTEXT GetThreadDpiAwarenessContext(); + + [DllImport("User32.dll")] + public static extern DPI_AWARENESS_CONTEXT GetWindowDpiAwarenessContext( + IntPtr hwnd); + + [DllImport("User32.dll")] + public static extern DPI_AWARENESS_CONTEXT SetThreadDpiAwarenessContext( + DPI_AWARENESS_CONTEXT dpiContext); + + [DllImport("User32.dll")] + public static extern DPI_AWARENESS GetAwarenessFromDpiAwarenessContext( + DPI_AWARENESS_CONTEXT value); + + [DllImport("User32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsValidDpiAwarenessContext( + DPI_AWARENESS_CONTEXT value); + + [DllImport("User32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool AreDpiAwarenessContextsEqual( + DPI_AWARENESS_CONTEXT dpiContextA, + DPI_AWARENESS_CONTEXT dpiContextB); + + #endregion + + #region Win32 (Old) + + public enum PROCESS_DPI_AWARENESS + { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 + } + + [DllImport("Shcore.dll", SetLastError = true)] + public static extern int GetProcessDpiAwareness( + IntPtr hprocess, + out PROCESS_DPI_AWARENESS value); + + #endregion + + #region Win32 (Other) + + [DllImport("Kernel32.dll", SetLastError = true)] + public static extern uint FormatMessage( + uint dwFlags, + IntPtr lpSource, + uint dwMessageId, + uint dwLanguageId, + StringBuilder lpBuffer, + int nSize, + IntPtr Arguments); + + public const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; + + #endregion + + public static bool EnableScaling(Window window) + { + var handle = new WindowInteropHelper(window).Handle; + + var result = EnableNonClientDpiScaling(handle); + + if (!result) + CheckLastError(); + + return result; + } + + public static bool EnableScaling(Visual visual) + { + var source = PresentationSource.FromVisual(visual) as HwndSource; + if (source == null) + return false; + + var handle = source.Handle; + + var result = EnableNonClientDpiScaling(handle); + + if (!result) + CheckLastError(); + + return result; + } + + public static DPI_AWARENESS SetThreadAwarenessContext(DPI_AWARENESS_CONTEXT newContext) + { + var oldContext = SetThreadDpiAwarenessContext(newContext); + + return GetAwarenessFromDpiAwarenessContext(oldContext); + } + + public static DPI_AWARENESS GetThreadAwarenessContext() + { + var context = GetThreadDpiAwarenessContext(); + + return GetAwarenessFromDpiAwarenessContext(context); + } + + public static DPI_AWARENESS GetWindowAwarenessContext(Window window) + { + var handle = new WindowInteropHelper(window).Handle; + + var context = GetWindowDpiAwarenessContext(handle); + + return GetAwarenessFromDpiAwarenessContext(context); + } + + public static PROCESS_DPI_AWARENESS GetProcessAwareness() + { + PROCESS_DPI_AWARENESS value; + var result = GetProcessDpiAwareness( + IntPtr.Zero, // Current process + out value); + + if (result != 0) // 0 means S_OK. + throw new InvalidOperationException(); + + return value; + } + + private static void CheckLastError() + { + var code = Marshal.GetLastWin32Error(); + + var sb = new StringBuilder(512); + + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + IntPtr.Zero, + (uint)code, + 0x0409, // US (English) + sb, + sb.Capacity, + IntPtr.Zero); + + Debug.WriteLine($"Error Code: {code}, Message: {sb.ToString().Trim()}"); + } + } +} \ No newline at end of file diff --git a/src/livelywpf/livelywpf/docs/help_vid_1.mp4 b/src/livelywpf/livelywpf/docs/help_vid_1.mp4 new file mode 100644 index 00000000..0c24d896 Binary files /dev/null and b/src/livelywpf/livelywpf/docs/help_vid_1.mp4 differ diff --git a/src/livelywpf/livelywpf/docs/license.rtf b/src/livelywpf/livelywpf/docs/license.rtf new file mode 100644 index 00000000..346e19b0 --- /dev/null +++ b/src/livelywpf/livelywpf/docs/license.rtf @@ -0,0 +1,921 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Tahoma;} +{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f41\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\f42\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f44\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f45\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f46\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\f47\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f48\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f49\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f51\fbidi \fswiss\fcharset238\fprq2 Arial CE;} +{\f52\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;}{\f54\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f55\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f56\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);} +{\f57\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);}{\f58\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f59\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f61\fbidi \fmodern\fcharset238\fprq1 Courier New CE;} +{\f62\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}{\f64\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f65\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f66\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);} +{\f67\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f68\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f69\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f61\fbidi \fmodern\fcharset238\fprq1 Courier New CE;} +{\f62\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}{\f64\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f65\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f66\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);} +{\f67\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f68\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f69\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f431\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;} +{\f432\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f434\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f435\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}{\f436\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);} +{\f437\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f438\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f439\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f440\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);} +{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;} +{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);} +{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);} +{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} +{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\caccentone\ctint255\cshade191\red46\green116\blue181;\red36\green41\blue46;}{\*\defchp \f31506\fs22 }{\*\defpap +\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\s1\ql \li0\ri0\sb240\sl259\slmult1 +\keep\keepn\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs32\alang1025 \ltrch\fcs0 \fs32\cf17\lang1033\langfe1033\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink15 \sqformat \spriority9 \styrsid16328086 heading 1;}{\*\cs10 \additive \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31506\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 \additive +\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \fs32\cf17\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 \styrsid16328086 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf2 +\sbasedon10 \ssemihidden \sunhideused \styrsid15363914 Hyperlink;}{\s17\ql \li0\ri0\widctlpar +\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af2\afs20\alang1025 \ltrch\fcs0 +\f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 \slink18 \ssemihidden \sunhideused \styrsid15098231 HTML Preformatted;}{\*\cs18 \additive \rtlch\fcs1 \af2\afs20 \ltrch\fcs0 \f2\fs20 +\sbasedon10 \slink17 \slocked \ssemihidden \styrsid15098231 HTML Preformatted Char;}{\s19\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext19 \sunhideused \styrsid14685526 Normal (Web);}{\*\cs20 \additive \rtlch\fcs1 \ai\af0 \ltrch\fcs0 \i \sbasedon10 \sqformat \spriority20 \styrsid14685526 Emphasis;}{ +\s21\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext21 \sqformat \spriority1 \styrsid16328086 +No Spacing;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0 +\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp +\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid268697\rsid527348\rsid740603\rsid810069\rsid1116686\rsid1120488\rsid1516284\rsid2173968\rsid2831276 +\rsid3150095\rsid3240521\rsid3939954\rsid4279899\rsid4465966\rsid4675836\rsid5461361\rsid6704124\rsid7042697\rsid7433477\rsid8745047\rsid8931313\rsid9845156\rsid9977545\rsid10370081\rsid10569259\rsid10833687\rsid11363778\rsid12338710\rsid12806171 +\rsid13373303\rsid13381601\rsid13643783\rsid13963034\rsid14057040\rsid14226533\rsid14367033\rsid14494510\rsid14685526\rsid14701935\rsid14877467\rsid14903299\rsid15098231\rsid15273691\rsid15363914\rsid15401395\rsid15477676\rsid15934410\rsid16328086 +\rsid16349761}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Dani John}{\operator Dani John}{\creatim\yr2019\mo9\dy7\hr22\min27} +{\revtim\yr2019\mo11\dy19\hr3\min8}{\version47}{\edmins100}{\nofpages13}{\nofwords5775}{\nofchars32919}{\nofcharsws38617}{\vern57433}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} +\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen +\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1 +\jexpand\viewkind1\viewscale150\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct +\asianbrkrule\rsidroot10833687\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0 +{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang +{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}} +\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3939954 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\chshdng0\chcfpat0\chcbpat8\insrsid3939954\charrsid3939954 These materials are not sponsored by or affiliated with Unity Technologies or its affiliates. \'93Unity\'94 + is a trademark or registered trademark of Unity Technologies or its affili}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\chshdng0\chcfpat0\chcbpat8\insrsid268697 ates in the U.S. and elsewhere.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\chshdng0\chcfpat0\chcbpat8\insrsid3939954 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\chshdng0\chcfpat0\chcbpat8\insrsid268697\charrsid3939954 These materials are not }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\chshdng0\chcfpat0\chcbpat8\insrsid268697 sponsored by or affiliated with }{ +\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 \cs20\f1\fs20\cf18\insrsid268697 Godot, Bizhawk, S}{\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 \cs20\f1\fs20\cf18\insrsid268697\charrsid3939954 hadertoy}{\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 +\cs20\f1\fs20\cf18\insrsid268697 .com}{\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 \cs20\f1\fs20\cf18\insrsid268697\charrsid3939954 or any }{\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 \cs20\f1\fs20\cf18\insrsid1516284 other services/applications listed.}{ +\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 \cs20\f1\fs20\cf18\insrsid268697 }{\rtlch\fcs1 \ab\ai\af1\afs20 \ltrch\fcs0 \f1\fs20\cf18\insrsid268697\charrsid268697 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15098231 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid1116686\charrsid4675836 Special thanks}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid3150095\charrsid4675836 :- +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid3150095\charrsid4675836 Dabjulmaros +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14701935\charrsid4675836 V}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid3150095\charrsid4675836 ell +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid527348\charrsid4675836 Abhijith}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid527348 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid268697 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid268697 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid268697 Translation}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid268697\charrsid4675836 :- +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15098231 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid268697\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\brdrb\brdrs\brdrw10\brsp20 +\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12806171 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\ul\insrsid3150095 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9977545 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid9977545 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid9977545\charrsid4675836 App Icons by icons8:- }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9977545\charrsid4675836 HYPERLINK "https://icons8.com/" }{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9977545\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b40000000680074007400700073003a002f002f00690063006f006e00730038002e0063006f006d002f000000795881f43b1d7f48af2c825dc485276300000000a5ab0003000000b0770045}}}{\fldrslt { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid9977545\charrsid4675836 https://icons8.com/}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9977545\charrsid4675836 + +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\brdrb\brdrs\brdrw10\brsp20 +\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12806171 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\ul\insrsid9977545\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15098231 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid12806171\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid10370081\charrsid4675836 CefSharp}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid10370081\charrsid4675836 HYPERLINK "https://github.com/cefsharp/CefSharp" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14494510\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b62000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f00630065006600730068006100720070002f00430065006600530068006100720070000000795881f43b1d7f48 +af2c825dc485276300000000a5ab0003000000fe00010000000077}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid10370081\charrsid4675836 https://github.com/cefsharp/CefSharp}}}\sectd \ltrsect +\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 +\par License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15098231\charrsid4675836 HYPERLINK "https://github.com/cefsharp/CefSharp/blob/master/LICENSE" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid10370081\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b8a000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f00630065006600730068006100720070002f00430065006600530068006100720070002f0062006c006f006200 +2f006d00610073007400650072002f004c004900430045004e00530045000000795881f43b1d7f48af2c825dc485276300000000a5ab000300360000686e000000000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid15098231\charrsid4675836 +https://github.com/cefsharp/CefSharp/blob/master/LICENSE}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15098231\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid15098231\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid14494510\charrsid4675836 // Copyright \'a9 The }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid15098231\charrsid4675836 CefSharp Authors. All rights reserved. +\par // +\par // Redistribution and use in source and binary forms, with or without +\par // modification, are permitted provided that the following conditions are +\par // met: +\par // +\par // * Redistributions of source code must retain the above copyright +\par // notice, this list of conditions and the following disclaimer. +\par // +\par // * Redistributions in binary form must reproduce the above +\par // copyright notice, this list of conditions and the following disclaimer +\par // in the documentation and/or other materials provided with the +\par // distribution. +\par // +\par // * Neither the name of Google Inc. nor the name Chromium Embedded +\par // Framework nor the name CefSharp nor the names of its contributors +\par // may be used to endorse or promote products derived from this software +\par // without specific prior written permission. +\par // +\par // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +\par // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +\par // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +\par // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +\par // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +\par // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +\par // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +\par // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +\par // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +\par // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +\par // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\brdrb\brdrs\brdrw10\brsp20 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid16349761 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15098231\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid10370081\charrsid4675836 WPF MediaKit}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid10370081\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 HYPERLINK "https://github.com/Sascha-L/WPF-MediaKit" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14494510\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f005300610073006300680061002d004c002f005700500046002d004d0065006400690061004b00690074000000 +795881f43b1d7f48af2c825dc485276300000000a5ab00030000006c00000000000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid10370081\charrsid4675836 https://github.com/Sascha-L/WPF-MediaKit}}}\sectd \ltrsect +\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid10370081 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 + HYPERLINK "https://github.com/Sascha-L/WPF-MediaKit/blob/master/License.txt" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14494510\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b9a000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f005300610073006300680061002d004c002f005700500046002d004d0065006400690061004b00690074002f00 +62006c006f0062002f006d00610073007400650072002f004c006900630065006e00730065002e007400780074000000795881f43b1d7f48af2c825dc485276300000000a5ab0003000000c300000000000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\cs16\f1\fs20\ul\cf2\insrsid10370081\charrsid4675836 https://github.com/Sascha-L/WPF-MediaKit/blob/master/License.txt}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid10370081\charrsid4675836 +\par +\par }\pard\plain \ltrpar\s17\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid10370081 +\rtlch\fcs1 \af2\afs20\alang1025 \ltrch\fcs0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\insrsid10370081\charrsid4675836 Microsoft Public License (Ms-PL) +\par +\par This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. +\par +\par 1. Definitions +\par +\par The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. +\par +\par A "contribution" is the original software, or any additions or changes to the software. +\par +\par A "contributor" is any person that distributes its contribution under this license. +\par +\par "Licensed patents" are a contributor's patent claims that read directly on its contribution. +\par +\par 2. Grant of Rights +\par +\par (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivat +ive works of its contribution, and distribute its contribution or any derivative works that you create. +\par +\par (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non +-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. +\par +\par 3. Conditions and Limitations +\par +\par (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +\par +\par (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. +\par +\par (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. +\par +\par (D) If you distribut +e any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so + under a license that complies with this license. +\par +\par (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws whic +h this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. +\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\brdrb\brdrs\brdrw10\brsp20 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1120488 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid10370081\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14226533 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid14226533\charrsid4675836 XamlAnimatedGif}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14226533\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14226533\charrsid4675836 HYPERLINK "https://github.com/XamlAnimatedGif/XamlAnimatedGif" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16349761\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b7e000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f00580061006d006c0041006e0069006d0061007400650064004700690066002f00580061006d006c0041006e00 +69006d0061007400650064004700690066000000795881f43b1d7f48af2c825dc485276300000000a5ab0003000d00000000000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid14226533\charrsid4675836 +https://github.com/XamlAnimatedGif/XamlAnimatedGif}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14226533\charrsid4675836 +\par License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14226533\charrsid4675836 HYPERLINK "https://github.com/XamlAnimatedGif/XamlAnimatedGif/blob/master/LICENSE.txt" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid16349761\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90bae000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f00580061006d006c0041006e0069006d0061007400650064004700690066002f00580061006d006c0041006e00 +69006d0061007400650064004700690066002f0062006c006f0062002f006d00610073007400650072002f004c004900430045004e00530045002e007400780074000000795881f43b1d7f48af2c825dc485276300000000a5ab00030a0d00000000000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\cs16\f1\fs20\ul\cf2\insrsid14226533\charrsid4675836 https://github.com/XamlAnimatedGif/XamlAnimatedGif/blob/master/LICENSE.txt}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14226533\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14226533\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15401395 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid15401395\charrsid4675836 Version 2.0, January 2004 +\par http://www.apache.org/licenses/ +\par +\par TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +\par +\par 1. Definitions. +\par +\par "License" shall mean the terms and conditions for use, reproduction, +\par and distribution as defined by Sections 1 through 9 of this document. +\par +\par "Licensor" shall mean the copyright owner or entity authorized by +\par the copyright owner that is granting the License. +\par +\par "Legal Entity" shall mean the union of the acting entity and all +\par other entities that control, are controlled by, or are under common +\par control with that entity. For the purposes of this definition, +\par "control" means (i) the power, direct or indirect, to cause the +\par direction or management of such entity, whether by contract or +\par otherwise, or (ii) ownership of fifty percent (50%) or more of the +\par outstanding shares, or (iii) beneficial ownership of such entity. +\par +\par "You" (or "Your") shall mean an individual or Legal Entity +\par exercising permissions granted by this License. +\par +\par "Source" form shall mean the preferred form for making modifications, +\par including but not limited to software source code, documentation +\par source, and configuration files. +\par +\par "Object" form shall mean any form resulting from mechanical +\par transformation or translation of a Source form, including but +\par not limited to compiled object code, generated documentation, +\par and conversions to other media types. +\par +\par "Work" shall mean the work of authorship, whether in Source or +\par Object form, made available under the License, as indicated by a +\par copyright notice that is included in or attached to the work +\par (an example is provided in the Appendix below). +\par +\par "Derivative Works" shall mean any work, whether in Source or Object +\par form, that is based on (or derived from) the Work and for which the +\par editorial revisions, annotations, elaborations, or other modifications +\par represent, as a whole, an original work of authorship. For the purposes +\par of this License, Derivative Works shall not include works that remain +\par separable from, or merely link (or bind by name) to the interfaces of, +\par the Work and Derivative Works thereof. +\par +\par "Contribution" shall mean any work of authorship, including +\par the original version of the Work and any modifications or additions +\par to that Work or Derivative Works thereof, that is intentionally +\par submitted to Licensor for inclusion in the Work by the copyright owner +\par or by an individual or Legal Entity authorized to submit on behalf of +\par the copyright owner. For the purposes of this definition, "submitted" +\par means any form of electronic, verbal, or written communication sent +\par to the Licensor or its representatives, including but not limited to +\par communication on electronic mailing lists, source code control systems, +\par and issue tracking systems that are managed by, or on behalf of, the +\par Licensor for the purpose of discussing and improving the Work, but +\par excluding communication that is conspicuously marked or otherwise +\par designated in writing by the copyright owner as "Not a Contribution." +\par +\par "Contributor" shall mean Licensor and any individual or Legal Entity +\par on behalf of whom a Contribution has been received by Licensor and +\par subsequently incorporated within the Work. +\par +\par 2. Grant of Copyright License. Subject to the terms and conditions of +\par this License, each Contributor hereby grants to You a perpetual, +\par worldwide, non-exclusive, no-charge, royalty-free, irrevocable +\par copyright license to reproduce, prepare Derivative Works of, +\par publicly display, publicly perform, sublicense, and distribute the +\par Work and such Derivative Works in Source or Object form. +\par +\par 3. Grant of Patent License. Subject to the terms and conditions of +\par this License, each Contributor hereby grants to You a perpetual, +\par worldwide, non-exclusive, no-charge, royalty-free, irrevocable +\par (except as stated in this section) patent license to make, have made, +\par use, offer to sell, sell, import, and otherwise transfer the Work, +\par where such license applies only to those patent claims licensable +\par by such Contributor that are necessarily infringed by their +\par Contribution(s) alone or by combination of their Contribution(s) +\par with the Work to which such Contribution(s) was submitted. If You +\par institute patent litigation against any entity (including a +\par cross-claim or counterclaim in a lawsuit) alleging that the Work +\par or a Contribution incorporated within the Work constitutes direct +\par or contributory patent infringement, then any patent licenses +\par granted to You under this License for that Work shall terminate +\par as of the date such litigation is filed. +\par +\par 4. Redistribution. You may reproduce and distribute copies of the +\par Work or Derivative Works thereof in any medium, with or without +\par modifications, and in Source or Object form, provided that You +\par meet the following conditions: +\par +\par (a) You must give any other recipients of the Work or +\par Derivative Works a copy of this License; and +\par +\par (b) You must cause any modified files to carry prominent notices +\par stating that You changed the files; and +\par +\par (c) You must retain, in the Source form of any Derivative Works +\par that You distribute, all copyright, patent, trademark, and +\par attribution notices from the Source form of the Work, +\par excluding those notices that do not pertain to any part of +\par the Derivative Works; and +\par +\par (d) If the Work includes a "NOTICE" text file as part of its +\par distribution, then any Derivative Works that You distribute must +\par include a readable copy of the attribution notices contained +\par within such NOTICE file, excluding those notices that do not +\par pertain to any part of the Derivative Works, in at least one +\par of the following places: within a NOTICE text file distributed +\par as part of the Derivative Works; within the Source form or +\par documentation, if provided along with the Derivative Works; or, +\par within a display generated by the Derivative Works, if and +\par wherever such third-party notices normally appear. The contents +\par of the NOTICE file are for informational purposes only and +\par do not modify the License. You may add Your own attribution +\par notices within Derivative Works that You distribute, alongside +\par or as an addendum to the NOTICE text from the Work, provided +\par that such additional attribution notices cannot be construed +\par as modifying the License. +\par +\par You may add Your own copyright statement to Your modifications and +\par may provide additional or different license terms and conditions +\par for use, reproduction, or distribution of Your modifications, or +\par for any such Derivative Works as a whole, provided Your use, +\par reproduction, and distribution of the Work otherwise complies with +\par the conditions stated in this License. +\par +\par 5. Submission of Contributions. Unless You explicitly state otherwise, +\par any Contribution intentionally submitted for inclusion in the Work +\par by You to the Licensor shall be under the terms and conditions of +\par this License, without any additional terms or conditions. +\par Notwithstanding the above, nothing herein shall supersede or modify +\par the terms of any separate license agreement you may have executed +\par with Licensor regarding such Contributions. +\par +\par 6. Trademarks. This License does not grant permission to use the trade +\par names, trademarks, service marks, or product names of the Licensor, +\par except as required for reasonable and customary use in describing the +\par origin of the Work and reproducing the content of the NOTICE file. +\par +\par 7. Disclaimer of Warranty. Unless required by applicable law or +\par agreed to in writing, Licensor provides the Work (and each +\par Contributor provides its Contributions) on an "AS IS" BASIS, +\par WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +\par implied, including, without limitation, any warranties or conditions +\par of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +\par PARTICULAR PURPOSE. You are solely responsible for determining the +\par appropriateness of using or redistributing the Work and assume any +\par risks associated with Your exercise of permissions under this License. +\par +\par 8. Limitation of Liability. In no event and under no legal theory, +\par whether in tort (including negligence), contract, or otherwise, +\par unless required by applicable law (such as deliberate and grossly +\par negligent acts) or agreed to in writing, shall any Contributor be +\par liable to You for damages, including any direct, indirect, special, +\par incidental, or consequential damages of any character arising as a +\par result of this License or out of the use or inability to use the +\par Work (including but not limited to damages for loss of goodwill, +\par work stoppage, computer failure or malfunction, or any and all +\par other commercial damages or losses), even if such Contributor +\par has been advised of the possibility of such damages. +\par +\par 9. Accepting Warranty or Additional Liability. While redistributing +\par the Work or Derivative Works thereof, You may choose to offer, +\par and charge a fee for, acceptance of support, warranty, indemnity, +\par or other liability obligations and/or rights consistent with this +\par License. However, in accepting such obligations, You may act only +\par on Your own behalf and on Your sole responsibility, not on behalf +\par of any other Contributor, and only if You agree to indemnify, +\par defend, and hold each Contributor harmless for any liability +\par incurred by, or claims asserted against, such Contributor by reason +\par of your accepting any such warranty or additional liability. +\par +\par END OF TERMS AND CONDITIONS +\par +\par APPENDIX: How to apply the Apache License to your work. +\par +\par To apply the Apache License to your work, attach the following +\par boilerplate notice, with the fields enclosed by brackets "\{\}" +\par replaced with your own identifying information. (Don't include +\par the brackets!) The text should be enclosed in the appropriate +\par comment syntax for the file format. We also recommend that a +\par file or class name and description of purpose be included on the +\par same "printed page" as the copyright notice for easier +\par identification within third-party archives. +\par +\par Copyright \{yyyy\} \{name of copyright owner\} +\par +\par Licensed under the Apache License, Version 2.0 (the "License"); +\par you may not use this file except in compliance with the License. +\par You may obtain a copy of the License at +\par +\par http://www.apache.org/licenses/LICENSE-2.0 +\par +\par Unless required by applicable law or agreed to in writing, software +\par distributed under the License is distributed on an "AS IS" BASIS, +\par WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +\par See the License for the specific language governing permissions and +\par limitations under the License. +\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\brdrb\brdrs\brdrw10\brsp20 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1120488 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid15401395\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14057040 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid14057040\charrsid4675836 Newtonsoft.Json}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14057040\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14057040\charrsid4675836 HYPERLINK "https://github.com/JamesNK/Newtonsoft.Json" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16349761\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6e000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f004a0061006d00650073004e004b002f004e006500770074006f006e0073006f00660074002e004a0073006f00 +6e000000795881f43b1d7f48af2c825dc485276300000000a5ab00030007000000000000ff}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid14057040\charrsid4675836 https://github.com/JamesNK/Newtonsoft.Json}}}\sectd \ltrsect +\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14057040\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9845156 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14057040\charrsid4675836 License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14057040\charrsid4675836 + HYPERLINK "https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid16349761\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b9c000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f004a0061006d00650073004e004b002f004e006500770074006f006e0073006f00660074002e004a0073006f00 +6e002f0062006c006f0062002f006d00610073007400650072002f004c004900430045004e00530045002e006d0064000000795881f43b1d7f48af2c825dc485276300000000a5ab0003000300000000000002}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\cs16\f1\fs20\ul\cf2\insrsid14057040\charrsid4675836 https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14057040\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9845156\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13643783 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid13643783\charrsid4675836 The MIT License (MIT) +\par +\par Copyright (c) 2007 James Newton-King +\par +\par Permission is hereby granted, free of charge, to any person obtaining a copy +\par of this software and associated documentation files (the "Software"), to deal +\par in the Software without restriction, including without limitation the rights +\par to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +\par copies of the Software, and to permit persons to whom the Software is +\par furnished to do so, subject to the following conditions: +\par +\par The above copyright notice and this permission notice shall be included in all +\par copies or substantial portions of the Software. +\par +\par THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +\par IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +\par FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +\par AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +\par LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +\par OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +\par SOFTWARE. +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\brdrb\brdrs\brdrw10\brsp20 +\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1120488 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\cf1\insrsid13643783\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9845156 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid3240521\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14367033 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid11363778 Html5-boilerplate}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 + HYPERLINK "https://github.com/h5bp/html5-boilerplate" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\lang1040\langfe1033\langnp1040\insrsid14685526\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6c000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f0068003500620070002f00680074006d006c0035002d0062006f0069006c006500720070006c00610074006500 +0000795881f43b1d7f48af2c825dc485276300000000a5ab0003000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid14367033\charrsid4675836 https://github.com/h5bp/html5-boilerplate}}}\sectd \ltrsect +\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 +\par License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 HYPERLINK "https://github.com/h5bp/html5-boilerplate/blob/master/LICENSE.txt" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14685526\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b9c000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f0068003500620070002f00680074006d006c0035002d0062006f0069006c006500720070006c00610074006500 +2f0062006c006f0062002f006d00610073007400650072002f004c004900430045004e00530045002e007400780074000000795881f43b1d7f48af2c825dc485276300000000a5ab00034f0000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\cs16\f1\fs20\ul\cf2\insrsid14367033\charrsid4675836 https://github.com/h5bp/html5-boilerplate/blob/master/LICENSE.txt}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14367033\charrsid4675836 +\par +\par }\pard\plain \ltrpar\s17\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14367033 +\rtlch\fcs1 \af2\afs20\alang1025 \ltrch\fcs0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\insrsid14367033\charrsid4675836 Copyright (c) HTML5 Boilerplate +\par +\par Permission is hereby granted, free of charge, to any person obtaining a copy of +\par this software and associated documentation files (the "Software"), to deal in +\par the Software without restriction, including without limitation the rights to +\par use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +\par of the Software, and to permit persons to whom the Software is furnished to do +\par so, subject to the following conditions: +\par +\par The above copyright notice and this permission notice shall be included in all +\par copies or substantial portions of the Software. +\par +\par THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +\par IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +\par FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +\par AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +\par LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +\par OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +\par SOFTWARE. +\par }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\brdrb\brdrs\brdrw10\brsp20 +\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14367033 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid14367033\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9845156 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid14367033\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid9845156\charrsid4675836 MahApps.Metro}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9845156\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid9845156\charrsid4675836 HYPERLINK "https://github.com/MahApps/MahApps.Metro" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\lang1040\langfe1033\langnp1040\insrsid16349761\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f004d006100680041007000700073002f004d006100680041007000700073002e004d006500740072006f000000 +795881f43b1d7f48af2c825dc485276300000000a5ab000300f0005400000a0000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid9845156\charrsid4675836 https://github.com/MahApps/MahApps.Metro}}}\sectd \ltrsect +\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9845156\charrsid4675836 +\par License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9845156\charrsid4675836 HYPERLINK "https://github.com/MahApps/MahApps.Metro/blob/develop/LICENSE" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid16349761\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b94000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f004d006100680041007000700073002f004d006100680041007000700073002e004d006500740072006f002f00 +62006c006f0062002f0064006500760065006c006f0070002f004c004900430045004e00530045000000795881f43b1d7f48af2c825dc485276300000000a5ab0003000000000000003000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid9845156\charrsid4675836 +https://github.com/MahApps/MahApps.Metro/blob/develop/LICENSE}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9845156\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid9845156\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9845156 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid9845156\charrsid4675836 MIT License +\par +\par Copyright (c) 2019 MahApps +\par +\par Permission is hereby granted, free of charge, to any person obtaining a copy +\par of this software and associated documentation files (the "Software"), to deal +\par in the Software without restriction, including without limitation the rights +\par to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +\par copies of the Software, and to permit persons to whom the Software is +\par furnished to do so, subject to the following conditions: +\par +\par The above copyright notice and this permission notice shall be included in all +\par copies or substantial portions of the Software. +\par +\par THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +\par IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +\par FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +\par AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +\par LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +\par OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9977545 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid7433477\charrsid4675836 SOFTWARE.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid7433477\charrsid9977545 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\brdrb\brdrs\brdrw10\brsp20 +\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14877467 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\cf1\insrsid14877467\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14877467 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid14877467\charrsid4675836 +\par Windows-API-Core-Pack}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14877467\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14877467\charrsid4675836 + HYPERLINK "https://github.com/aybe/Windows-API-Code-Pack-1.1" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14701935\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b7c000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f0061007900620065002f00570069006e0064006f00770073002d004100500049002d0043006f00640065002d00 +5000610063006b002d0031002e0031000000795881f43b1d7f48af2c825dc485276300000000a5ab0003000009000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\cf2\insrsid14877467\charrsid4675836 https://github.com/aybe/Windows-API-Code-Pack-1.1}}} +\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14877467\charrsid4675836 +\par License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14877467\charrsid4675836 HYPERLINK "https://github.com/aybe/Windows-API-Code-Pack-1.1/blob/master/LICENCE" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14701935\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90ba4000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f0061007900620065002f00570069006e0064006f00770073002d004100500049002d0043006f00640065002d00 +5000610063006b002d0031002e0031002f0062006c006f0062002f006d00610073007400650072002f004c004900430045004e00430045000000795881f43b1d7f48af2c825dc485276300000000a5ab000300000069006e}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\cs16\f1\fs20\cf2\insrsid14877467\charrsid4675836 https://github.com/aybe/Windows-API-Code-Pack-1.1/blob/master/LICENCE}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid14877467\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid14877467\charrsid4675836 +\par }\pard\plain \ltrpar\s17\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14877467 +\rtlch\fcs1 \af2\afs20\alang1025 \ltrch\fcs0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\insrsid14877467\charrsid4675836 License: Custom License +\par MICROSOFT SOFTWARE LICENSE TERMS +\par MICROSOFT WINDOWS API CODE PACK FOR MICROSOFT .NET FRAMEWORK +\par ___________________________________________________ +\par These license terms are an agreement betw +een Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, which includes the media on which you received it, if any. The terms also apply to any Microsoft +\par \bullet updates, +\par \bullet supplements, +\par \bullet Internet-based services, and +\par \bullet support services +\par for this software, unless other terms accompany those items. If so, those terms apply. +\par _______________________________________________________________________________________ +\par BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE. +\par If you comply with these license terms, you have the rights below. +\par 1. INSTALLATION AND USE RIGHTS. +\par \bullet You may use any number of copies of the software to design, develop and test your programs that run on a Microsoft Windows operating system. +\par \bullet This agreement gives you rights to the software only. Any rights to a Microsoft Windows operating system (such as testing pre-release versions of Windows in a live operating environment) are provided separately by the license terms for Windows. + +\par 2. ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS. +\par a. Distributable Code. You may modify, copy, and distribute the software, in source or compiled form, to run on a Microsoft Windows operating system. +\par ii. Distribution Requirements. If you distribute the software, you must +\par \bullet require distributors and external end users to agree to terms that protect it at least as much as this agreement; +\par \bullet if you modify the software and distribute such modified files, include prominent notices in such modified files so that recipients know that they are not receiving the original software; +\par \bullet display your valid copyright notice on your programs; and +\par \bullet indemnify, defend, and hold harmless Microsoft from any claims, including attorneys\rquote fees, related to the distribution or use of your programs or to your modifications to the software. +\par iii. Distribution Restrictions. You may not +\par \bullet alter any copyright, trademark or patent notice in the software; +\par \bullet use Microsoft\rquote s trademarks in your programs\rquote names or in a way that suggests your programs come from or are endorsed by Microsoft; +\par \bullet include the software in malicious, deceptive or unlawful programs; or +\par \bullet modify or distribute the source code of the software so that any part of it becomes subject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that +\par \bullet the code be disclosed or distributed in source code form; or +\par \bullet others have the right to modify it. +\par 3. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves + all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. +\par 4. EXPORT RESTRICTIONS. The software is subject to United States export laws and regulations. Yo +u must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see . +\par 5. SUPPORT SERVICES. Because this software is \'93as is,\'94 we may not provide support services for it. +\par 6. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services. +\par 7. APPLICABLE LAW. +\par a. United States. If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of l +aws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort. +\par b. Outside the United States. If you acquired the software in any other country, the laws of that country apply. +\par 8. LEGAL EFFECT. This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement doe +s not change your rights under the laws of your country if the laws of your country do not permit it to do so. +\par 9. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED \'93AS-IS.\'94 YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR +CONDITIONS. YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NON-INFRINGEMENT. +\par 10. LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT + OR INCIDENTAL DAMAGES. +\par This limitation applies to +\par \bullet anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and +\par \bullet claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. +\par It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your +country may not allow the exclusion or limitation of incidental, consequential or other damages. +\par Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French. +\par Remarque : Ce logiciel \'e9tant distribu\'e9 au Qu\'e9bec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en fran\'e7ais. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\lang1040\langfe1033\langnp1040\insrsid14877467\charrsid4675836 EXON\'c9RATION DE GARANTIE. Le logiciel vis\'e9 par une licence est offert \'ab tel quel \'bb. Toute utilisation de ce logiciel est \'e0 + votre seule risque et p\'e9ril. Microsoft n\rquote accorde aucune autre garantie expresse. Vous pouvez b\'e9n\'e9ficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. }{\rtlch\fcs1 +\af1 \ltrch\fcs0 \f1\cf1\insrsid14877467\charrsid4675836 La ou elles sont permises par le droit locale, les garanties implicites de qualit\'e9 marchande, d\rquote ad\'e9quation \'e0 un usage particulier et d\rquote absence de contrefa\'e7on sont exclues. + +\par LIMITATION DES DOMMAGES-INT\'c9R\'caTS ET EXCLUSION DE RESPONSABILIT\'c9 POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement \'e0 hauteur de 5,00 $ US. Vous ne pouvez pr\'e9 +tendre \'e0 aucune indemnisation pour les autres dommages, y compris les dommages sp\'e9ciaux, indirects ou accessoires et pertes de b\'e9n\'e9fices. +\par Cette limitation concerne : +\par \bullet tout ce qui est reli\'e9 au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\lang1040\langfe1033\langnp1040\insrsid14877467\charrsid4675836 \bullet les r\'e9clamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit\'e9 stricte, de n\'e9gligence ou d\rquote +une autre faute dans la limite autoris\'e9e par la loi en vigueur. +\par Elle s\rquote applique \'e9galement, m\'eame si Microsoft connaissait ou devrait conna\'eetre l\rquote \'e9ventualit\'e9 d\rquote un tel dommage. Si votre pays n\rquote autorise pas l\rquote exclusion ou la limitation de responsabilit\'e9 + pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l\rquote exclusion ci-dessus ne s\rquote appliquera pas \'e0 votre \'e9gard. +\par }{\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\insrsid14877467\charrsid4675836 EFFET JURIDIQUE. Le pr\'e9sent contrat d\'e9crit certains droits juridiques. Vous pourriez avoir d\rquote autres droits pr\'e9vus par les lois de votre pays. Le pr\'e9 +sent contrat ne modifie pas les droits que vous conf\'e8rent les lois de votre pays si celles-ci ne le permettent pas. +\par }\pard\plain \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7433477 \rtlch\fcs1 +\af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid7433477\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\brdrb\brdrs\brdrw10\brsp20 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8931313 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8931313\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8931313 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\insrsid8931313\charrsid4675836 NLog}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8931313\charrsid4675836 : }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8931313\charrsid4675836 + HYPERLINK "https://github.com/NLog/NLog" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b52000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f004e004c006f0067002f004e004c006f0067000000795881f43b1d7f48af2c825dc485276300000000a5ab0003 +80f07600}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid8931313\charrsid4675836 https://github.com/NLog/NLog}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid8931313\charrsid4675836 +\par License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8931313\charrsid4675836 HYPERLINK "https://github.com/NLog/NLog/blob/dev/LICENSE.txt" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 +{\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b7c000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f004e004c006f0067002f004e004c006f0067002f0062006c006f0062002f006400650076002f004c0049004300 +45004e00530045002e007400780074000000795881f43b1d7f48af2c825dc485276300000000a5ab000300000000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid8931313\charrsid4675836 https://github.com/NLog/NLog/blob/dev/LICENSE.txt}}} +\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8931313\charrsid4675836 +\par }\pard\plain \ltrpar\s17\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8931313 \rtlch\fcs1 +\af2\afs20\alang1025 \ltrch\fcs0 \f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1 \ltrch\fcs0 \f1\cf1\insrsid8931313\charrsid4675836 +\par Copyright (c) 2004-2019 Jaroslaw Kowalski , Kim Christensen, Julian Verdurmen +\par +\par All rights reserved. +\par +\par Redistribution and use in source and binary forms, with or without +\par modification, are permitted provided that the following conditions +\par are met: +\par +\par * Redistributions of source code must retain the above copyright notice, +\par this list of conditions and the following disclaimer. +\par +\par * Redistributions in binary form must reproduce the above copyright notice, +\par this list of conditions and the following disclaimer in the documentation +\par and/or other materials provided with the distribution. +\par +\par * Neither the name of Jaroslaw Kowalski nor the names of its +\par contributors may be used to endorse or promote products derived from this +\par software without specific prior written permission. +\par +\par THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +\par AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +\par IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +\par ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +\par LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +\par CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +\par SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +\par INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +\par CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +\par ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +\par THE POSSIBILITY OF SUCH DAMAGE. +\par }\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\brdrb\brdrs\brdrw10\brsp20 \wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2831276 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2831276\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2831276 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\ul\lang1040\langfe1033\langnp1040\insrsid810069\charrsid4675836 DotNetZip}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\lang1040\langfe1033\langnp1040\insrsid2831276\charrsid4675836 : }{\field\fldedit{\*\fldinst { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\lang1040\langfe1033\langnp1040\insrsid2831276\charrsid4675836 HYPERLINK "https://github.com/haf/DotNetZip.Semverd" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f006800610066002f0044006f0074004e00650074005a00690070002e00530065006d0076006500720064000000 +795881f43b1d7f48af2c825dc485276300000000a5ab000300000069}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\lang1040\langfe1033\langnp1040\insrsid2831276\charrsid4675836 https://github.com/haf/DotNetZip.Semverd}}}\sectd \ltrsect +\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\lang1040\langfe1033\langnp1040\insrsid2831276\charrsid4675836 +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2831276\charrsid4675836 License: }{\field\fldedit{\*\fldinst {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2831276\charrsid4675836 + HYPERLINK "https://github.com/haf/DotNetZip.Semverd/blob/master/LICENSE" }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid14367033\charrsid4675836 {\*\datafield +00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b92000000680074007400700073003a002f002f006700690074006800750062002e0063006f006d002f006800610066002f0044006f0074004e00650074005a00690070002e00530065006d0076006500720064002f00 +62006c006f0062002f006d00610073007400650072002f004c004900430045004e00530045000000795881f43b1d7f48af2c825dc485276300000000a5ab000300010000}}}{\fldrslt {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \cs16\f1\fs20\ul\cf2\insrsid2831276\charrsid4675836 +https://github.com/haf/DotNetZip.Semverd/blob/master/LICENSE}}}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2831276\charrsid4675836 +\par +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid2831276\charrsid4675836 Software Licenses that apply to the DotNetZip library and tools +\par +\par As DotNetZip includes work derived from other projects, you are required to comply with the terms and conditions for each of them. These licenses include BSD, Apache, and zlib. +\par +\par To use the software, you must accept the licenses. If you do not accept the licenses, do not use the software. +\par +\par Original intellectual property in DotNetZip is provided under the Ms-PL: +\par +\par Copyright (c) 2006 - 2011 Dino Chiesa +\par Copyright (c) 2006, 2007, 2008, 2009 Dino Chiesa and Microsoft Corporation. +\par +\par Microsoft Public License (Ms-PL) +\par +\par This license governs use of the accompanying software, the DotNetZip library ("the software"). If you use the software, you accept this license. If you do not accept the license, do not use the software. +\par +\par 1. Definitions +\par +\par The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. +\par +\par A "contribution" is the original software, or any additions or changes to the software. +\par +\par A "contributor" is any person that distributes its contribution under this license. +\par +\par "Licensed patents" are a contributor's patent claims that read directly on its contribution. +\par +\par 2. Grant of Rights +\par +\par (A) Copyright Grant- Subject +to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution +, and distribute its contribution or any derivative works that you create. +\par +\par (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide +, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. +\par +\par 3. Conditions and Limitations +\par +\par (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. +\par +\par (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. +\par +\par (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. +\par +\par ( +D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, + you may only do so under a license that complies with this license. +\par +\par (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights + under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. +\par +\par -------------------------------------------------------------- +\par +\par The managed ZLIB code included in Ionic.Zlib.dll and Ionic.Zip.dll is derived from jzlib. +\par +\par jzlib ( https://github.com/ymnk/jzlib ) is provided under a BSD-style (3 clause) +\par +\par Copyright (c) 2000,2001,2002,2003 ymnk, JCraft, Inc. +\par +\par Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +\par 1.\tab Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +\par 2.\tab Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +\par 3.\tab The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. +\par THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WAR +RANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPEC +I +AL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABIL +ITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\par +\par -------------------------------------------------------------- +\par +\par The jzlib library, itself, is a re-implementation of ZLIB v1.1.3 in pure Java. +\par +\par zlib is provided under the zlib license: +\par +\par Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler +\par The ZLIB software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. +\par Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: +\par 1.\tab The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + +\par 2.\tab Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +\par 3.\tab This notice may not be removed or altered from any source distribution. +\par Jean-loup Gailly jloup@gzip.org}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20\cf1\insrsid2831276\charrsid4675836 \u8232\'3f}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid2831276\charrsid4675836 Mark A +dler madler@alumni.caltech.edu +\par +\par -------------------------------------------------------------- +\par +\par The managed BZIP2 code included in Ionic.BZip2.dll and Ionic.Zip.dll is modified code, based on Java code in the Apache commons compress library. +\par +\par Apache Commons Compress ( http://commons.apache.org/proper/commons-compress/ ) is provided under the Apache 2 license: +\par Apache Commons Compress +\par Copyright 2002-2014 The Apache Software Foundation +\par +\par Licensed to the Apache Software Foundation (ASF) +under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may n +ot use this file except in compliance with the License. You may obtain a copy of the License at +\par http://www.apache.org/licenses/LICENSE-2.0 +\par Unless required by applicable law or agreed to in writing, software distributed under the License is distribu +ted on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +\par +\par Many thanks to Julian Seward for the original C implementation of BZip2 ( http://www.bzip.org/ ). +\par +\par +\par +\par +\par }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid2831276\charrsid4675836 +\par }\pard \ltrpar\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7433477 {\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\cf1\insrsid8931313\charrsid4675836 +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100aa5225dfc60600008b1a0000160000007468656d652f7468656d652f +7468656d65312e786d6cec595d8bdb46147d2ff43f08bd3bfe92fcb1c41b6cd9ceb6d94d42eca4e4716c8fadc98e344633de8d0981923c160aa569e943037deb +43691b48a02fe9afd936a54d217fa17746b63c638fbb9b2585a5640d8b343af7ce997bafce1d4997afdc8fa87384134e58dc708b970aae83e3211b9178d2706f +f7bbb99aeb7081e211a22cc60d778eb97b65f7c30f2ea31d11e2083b601ff31dd4704321a63bf93c1fc230e297d814c7706dcc920809384d26f951828ec16f44 +f3a542a1928f10895d274611b8bd311e932176fad2a5bbbb74dea1701a0b2e078634e949d7d8b050d8d1615122f89c0734718e106db830cf881df7f17de13a14 +7101171a6e41fdb9f9ddcb79b4b330a2628bad66d7557f0bbb85c1e8b0a4e64c26836c52cff3bd4a33f3af00546ce23ad54ea553c9fc29001a0e61a52917dda7 +dfaab7dafe02ab81d2438bef76b55d2e1a78cd7f798373d3973f03af40a97f6f03dfed06104503af4029dedfc07b5eb51478065e81527c65035f2d34db5ed5c0 +2b5048497cb8812ef89572b05c6d061933ba6785d77daf5b2d2d9caf50500d5975c929c62c16db6a2d42f758d2058004522448ec88f9148fd110aa3840940c12 +e2ec93490885374531e3305c2815ba8532fc973f4f1da988a01d8c346bc90b98f08d21c9c7e1c3844c45c3fd18bcba1ae4cdcb1fdfbc7cee9c3c7a71f2e89793 +c78f4f1efd9c3a32acf6503cd1ad5e7fffc5df4f3f75fe7afeddeb275fd9f15cc7fffed367bffdfaa51d082b5d85e0d5d7cffe78f1ecd5379ffff9c3130bbc99 +a0810eef930873e73a3e766eb10816a6426032c783e4ed2cfa2122ba45339e701423398bc57f478406fafa1c5164c1b5b019c13b09488c0d787576cf20dc0b93 +9920168fd7c2c8001e30465b2cb146e19a9c4b0b737f164fec9327331d770ba123dbdc018a8dfc766653d05662731984d8a07993a258a0098eb170e4357688b1 +6575770931e27a408609e36c2c9cbbc46921620d499f0c8c6a5a19ed9108f232b711847c1bb139b8e3b418b5adba8d8f4c24dc15885ac8f73135c27815cd048a +6c2efb28a27ac0f791086d247bf364a8e33a5c40a6279832a733c29cdb6c6e24b05e2de9d7405eec693fa0f3c84426821cda7cee23c674649b1d06218aa6366c +8fc4a18efd881f428922e7261336f80133ef10790e7940f1d674df21d848f7e96a701b9455a7b42a107965965872791533a37e7b733a4658490d08bfa1e71189 +4f15f73559f7ff5b5907217df5ed53cbaa2eaaa0371362bda3f6d6647c1b6e5dbc03968cc8c5d7ee369ac53731dc2e9b0decbd74bf976ef77f2fdddbeee7772f +d82b8d06f9965bc574abae36eed1d67dfb9850da13738af7b9daba73e84ca32e0c4a3bf5cc8ab3e7b8690887f24e86090cdc2441cac64998f88488b017a229ec +ef8bae7432e10bd713ee4c19876dbf1ab6fa96783a8b0ed8287d5c2d16e5a3692a1e1c89d578c1cfc6e15143a4e84a75f50896b9576c27ea51794940dabe0d09 +6d329344d942a2ba1c9441520fe610340b09b5b277c2a26e615193ee97a9da6001d4b2acc0d6c9810d57c3f53d30012378a242148f649ed2542fb3ab92f92e33 +bd2d984605c03e625901ab4cd725d7adcb93ab4b4bed0c99364868e566925091513d8c87688417d52947cf42e36d735d5fa5d4a02743a1e683d25ad1a8d6fe8d +c579730d76ebda40635d2968ec1c37dc4ad9879219a269c31dc3633f1c4653a81d2eb7bc884ee0ddd95024e90d7f1e6599265cb4110fd3802bd149d520220227 +0e2551c395cbcfd24063a5218a5bb104827061c9d541562e1a3948ba99643c1ee3a1d0d3ae8dc848a7a7a0f0a95658af2af3f383a5259b41ba7be1e8d819d059 +720b4189f9d5a20ce0887078fb534ca33922f03a3313b255fdad35a685eceaef13550da5e3884e43b4e828ba98a77025e5191d7596c5403b5bac1902aa8564d1 +080713d960f5a01add34eb1a2987ad5df7742319394d34573dd35015d935ed2a66ccb06c036bb13c5f93d7582d430c9aa677f854bad725b7bed4bab57d42d625 +20e059fc2c5df70c0d41a3b69acca026196fcab0d4ecc5a8d93b960b3c85da599a84a6fa95a5dbb5b8653dc23a1d0c9eabf383dd7ad5c2d078b9af549156df3d +f44f136c700fc4a30d2f81675470954af8f09020d810f5d49e24950db845ee8bc5ad0147ce2c210df741c16f7a41c90f72859adfc97965af90abf9cd72aee9fb +e562c72f16daadd243682c228c8a7efacda50bafa2e87cf1e5458d6f7c7d89966fdb2e0d599467eaeb4a5e11575f5f8aa5ed5f5f1c02a2f3a052ead6cbf55625 +572f37bb39afddaae5ea41a5956b57826abbdb0efc5abdfbd0758e14d86b9603afd2a9e52ac520c8799582a45fabe7aa5ea9d4f4aacd5ac76b3e5c6c6360e5a9 +7c2c6201e155bc76ff010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f +7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be +9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980 +ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5b +babac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000000000005b436f6e74656e +745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f +2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468656d652f7468656d652f74 +68656d654d616e616765722e786d6c504b01022d0014000600080000002100aa5225dfc60600008b1a00001600000000000000000000000000d6020000746865 +6d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000d00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000cb0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; +\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; +\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid; +\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1; +\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; +\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; +\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; +\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; +\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; +\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; +\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; +\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; +\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; +\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; +\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; +\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; +\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e50000000000000000000000008042 +227f589ed501feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/src/livelywpf/livelywpf/icons/icon_close.png b/src/livelywpf/livelywpf/icons/icon_close.png new file mode 100644 index 00000000..a3860b44 Binary files /dev/null and b/src/livelywpf/livelywpf/icons/icon_close.png differ diff --git a/src/livelywpf/livelywpf/icons/icon_erase.png b/src/livelywpf/livelywpf/icons/icon_erase.png new file mode 100644 index 00000000..f0a1e42a Binary files /dev/null and b/src/livelywpf/livelywpf/icons/icon_erase.png differ diff --git a/src/livelywpf/livelywpf/icons/icon_monitor.png b/src/livelywpf/livelywpf/icons/icon_monitor.png new file mode 100644 index 00000000..d083eeaf Binary files /dev/null and b/src/livelywpf/livelywpf/icons/icon_monitor.png differ diff --git a/src/livelywpf/livelywpf/icons/icon_update.png b/src/livelywpf/livelywpf/icons/icon_update.png new file mode 100644 index 00000000..768d7fa7 Binary files /dev/null and b/src/livelywpf/livelywpf/icons/icon_update.png differ diff --git a/src/livelywpf/livelywpf/icons/icons8-seed-of-life-96-normal.ico b/src/livelywpf/livelywpf/icons/icons8-seed-of-life-96-normal.ico new file mode 100644 index 00000000..2617b43d Binary files /dev/null and b/src/livelywpf/livelywpf/icons/icons8-seed-of-life-96-normal.ico differ diff --git a/src/livelywpf/livelywpf/icons/icons8-seed-of-life-96-pause.ico b/src/livelywpf/livelywpf/icons/icons8-seed-of-life-96-pause.ico new file mode 100644 index 00000000..adb7d539 Binary files /dev/null and b/src/livelywpf/livelywpf/icons/icons8-seed-of-life-96-pause.ico differ diff --git a/src/livelywpf/livelywpf/icons8-seed-of-life-96.ico b/src/livelywpf/livelywpf/icons8-seed-of-life-96.ico new file mode 100644 index 00000000..2617b43d Binary files /dev/null and b/src/livelywpf/livelywpf/icons8-seed-of-life-96.ico differ diff --git a/src/livelywpf/livelywpf/images/audio-wave1.png b/src/livelywpf/livelywpf/images/audio-wave1.png new file mode 100644 index 00000000..28980d55 Binary files /dev/null and b/src/livelywpf/livelywpf/images/audio-wave1.png differ diff --git a/src/livelywpf/livelywpf/images/broom.png b/src/livelywpf/livelywpf/images/broom.png new file mode 100644 index 00000000..4d50fdb8 Binary files /dev/null and b/src/livelywpf/livelywpf/images/broom.png differ diff --git a/src/livelywpf/livelywpf/images/emulator.png b/src/livelywpf/livelywpf/images/emulator.png new file mode 100644 index 00000000..4cce7b62 Binary files /dev/null and b/src/livelywpf/livelywpf/images/emulator.png differ diff --git a/src/livelywpf/livelywpf/images/icon html.png b/src/livelywpf/livelywpf/images/icon html.png new file mode 100644 index 00000000..e3fa2d69 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icon html.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-bot-50.png b/src/livelywpf/livelywpf/images/icons8-bot-50.png new file mode 100644 index 00000000..0b71f89a Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-bot-50.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-create-26.png b/src/livelywpf/livelywpf/images/icons8-create-26.png new file mode 100644 index 00000000..390845b4 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-create-26.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-heart-outline-24.png b/src/livelywpf/livelywpf/images/icons8-heart-outline-24.png new file mode 100644 index 00000000..b92a05f5 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-heart-outline-24.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-help-24.png b/src/livelywpf/livelywpf/images/icons8-help-24.png new file mode 100644 index 00000000..2709f74c Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-help-24.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-insert-30.png b/src/livelywpf/livelywpf/images/icons8-insert-30.png new file mode 100644 index 00000000..1159fd0a Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-insert-30.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-language-30.png b/src/livelywpf/livelywpf/images/icons8-language-30.png new file mode 100644 index 00000000..38b560f6 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-language-30.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-language-32.png b/src/livelywpf/livelywpf/images/icons8-language-32.png new file mode 100644 index 00000000..276f26cc Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-language-32.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-language-48.png b/src/livelywpf/livelywpf/images/icons8-language-48.png new file mode 100644 index 00000000..8e1eb656 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-language-48.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-language-60.png b/src/livelywpf/livelywpf/images/icons8-language-60.png new file mode 100644 index 00000000..4fdb4f6e Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-language-60.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-monitor-64.png b/src/livelywpf/livelywpf/images/icons8-monitor-64.png new file mode 100644 index 00000000..f44d6209 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-monitor-64.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-orthogonal-view-50.png b/src/livelywpf/livelywpf/images/icons8-orthogonal-view-50.png new file mode 100644 index 00000000..628384ad Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-orthogonal-view-50.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-pictureframe-icons-80.png b/src/livelywpf/livelywpf/images/icons8-pictureframe-icons-80.png new file mode 100644 index 00000000..48e02283 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-pictureframe-icons-80.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-seed-of-life-64.png b/src/livelywpf/livelywpf/images/icons8-seed-of-life-64.png new file mode 100644 index 00000000..c3b013e7 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-seed-of-life-64.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-seed-of-life-96.png b/src/livelywpf/livelywpf/images/icons8-seed-of-life-96.png new file mode 100644 index 00000000..13a53267 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-seed-of-life-96.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-video-50.png b/src/livelywpf/livelywpf/images/icons8-video-50.png new file mode 100644 index 00000000..fe3e54d4 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-video-50.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-wallpaper-24.png b/src/livelywpf/livelywpf/images/icons8-wallpaper-24.png new file mode 100644 index 00000000..0ec075a0 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-wallpaper-24.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-webpage-50.png b/src/livelywpf/livelywpf/images/icons8-webpage-50.png new file mode 100644 index 00000000..e57ab887 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-webpage-50.png differ diff --git a/src/livelywpf/livelywpf/images/icons8-window-other-50.png b/src/livelywpf/livelywpf/images/icons8-window-other-50.png new file mode 100644 index 00000000..090f4ee8 Binary files /dev/null and b/src/livelywpf/livelywpf/images/icons8-window-other-50.png differ diff --git a/src/livelywpf/livelywpf/images/monitor-480xw.png b/src/livelywpf/livelywpf/images/monitor-480xw.png new file mode 100644 index 00000000..92f1d5f8 Binary files /dev/null and b/src/livelywpf/livelywpf/images/monitor-480xw.png differ diff --git a/src/livelywpf/livelywpf/images/monitor-50xw.png b/src/livelywpf/livelywpf/images/monitor-50xw.png new file mode 100644 index 00000000..2a0b2d3c Binary files /dev/null and b/src/livelywpf/livelywpf/images/monitor-50xw.png differ diff --git a/src/livelywpf/livelywpf/images/vlc_less_bold.png b/src/livelywpf/livelywpf/images/vlc_less_bold.png new file mode 100644 index 00000000..37b1502c Binary files /dev/null and b/src/livelywpf/livelywpf/images/vlc_less_bold.png differ diff --git a/src/livelywpf/livelywpf/livelywpf.csproj b/src/livelywpf/livelywpf/livelywpf.csproj new file mode 100644 index 00000000..cf757982 --- /dev/null +++ b/src/livelywpf/livelywpf/livelywpf.csproj @@ -0,0 +1,442 @@ + + + + + + + + + + Debug + AnyCPU + {A71FC3FA-C514-4F6A-97F4-BC43F9403F88} + WinExe + livelywpf + livelywpf + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + false + C:\Users\rocks\Documents\installer lively\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 1 + 1.0.0.%2a + false + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + bin\x86\Debug\ + TRACE;DEBUG + x86 + + + bin\x86\Release\ + x86 + + + + + icons8-seed-of-life-96.ico + + + + false + + + 017C4B290A5507135374BFA449A5890D9470D37F + + + livelywpf_TemporaryKey.pfx + + + false + + + false + + + app.manifest + + + LocalIntranet + + + + ..\packages\ControlzEx.3.0.2.4\lib\net462\ControlzEx.dll + + + ..\packages\DotNetZip.1.13.4\lib\net40\DotNetZip.dll + + + ..\packages\MahApps.Metro.1.6.5\lib\net47\MahApps.Metro.dll + + + ..\packages\WindowsAPICodePack-Core.1.1.2\lib\Microsoft.WindowsAPICodePack.dll + + + ..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll + + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\NLog.4.6.8\lib\net45\NLog.dll + + + ..\packages\Octokit.0.36.0\lib\net46\Octokit.dll + + + + + + + ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll + True + True + + + + ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll + True + True + + + + + + + + ..\packages\ControlzEx.3.0.2.4\lib\net462\System.Windows.Interactivity.dll + + + + + + + + + 4.0 + + + + + + + ..\packages\WPFMediaKit.2.2.0\lib\WPFMediaKit.dll + + + ..\packages\XamlAnimatedGif.1.2.2\lib\net45\XamlAnimatedGif.dll + + + + + MSBuild:Compile + Designer + + + ApplicationRuleDialogWindow.xaml + + + CreateWallpaper.xaml + + + CreateWallpaperAddedFiles.xaml + + + DisplayID.xaml + + + DisplayLayoutWindow.xaml + + + DisplaySelectWindow.xaml + + + + + True + True + Icons.resx + + + Resources.zh.resx + True + True + + + True + True + Resources.resx + + + + GifWindow.xaml + + + HelpWindow.xaml + + + Mediakit.xaml + + + MediaPlayer.xaml + + + + Page_Ext.xaml + + + + + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Code + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Icons.Designer.cs + + + + + + PublicResXFileCodeGenerator + Resources.zh.Designer.cs + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + PreserveNewest + Designer + + + Always + + + Designer + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B} + 1 + 0 + 0 + tlbimp + False + True + + + + + False + Microsoft .NET Framework 4.7.2 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/packages.config b/src/livelywpf/livelywpf/packages.config new file mode 100644 index 00000000..cac0e499 --- /dev/null +++ b/src/livelywpf/livelywpf/packages.config @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/livelywpf/livelywpf/save/NullConverterXaml.cs b/src/livelywpf/livelywpf/save/NullConverterXaml.cs new file mode 100644 index 00000000..801fb3a5 --- /dev/null +++ b/src/livelywpf/livelywpf/save/NullConverterXaml.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace livelywpf +{ + class NullConverterXaml : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null) + return DependencyProperty.UnsetValue; + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + // According to https://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.convertback(v=vs.110).aspx#Anchor_1 + // (kudos Scott Chamberlain), if you do not support a conversion + // back you should return a Binding.DoNothing or a + // DependencyProperty.UnsetValue + return Binding.DoNothing; + // Original code: + // throw new NotImplementedException(); + } + } +} diff --git a/src/livelywpf/livelywpf/save/SaveData.cs b/src/livelywpf/livelywpf/save/SaveData.cs new file mode 100644 index 00000000..5298290e --- /dev/null +++ b/src/livelywpf/livelywpf/save/SaveData.cs @@ -0,0 +1,941 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; +using System.Diagnostics; +using System.ComponentModel; +using System.Linq.Expressions; +using System.Windows.Media.Imaging; +using System.Globalization; + +namespace livelywpf +{ + public static partial class SaveData + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + /// + /// Returns data stored in class object file. + /// + /// + /// + public static string PropertyList(this object obj) + { + try + { + var props = obj.GetType().GetProperties(); + var sb = new StringBuilder(); + foreach (var p in props) + { + sb.AppendLine(p.Name + ": " + p.GetValue(obj, null)); + } + return sb.ToString(); + } + catch + { + return "Failed to retrive properties of config file."; + } + } + + #region apprule + public enum AppRulesEnum + { + [Description("Pause")] + pause, + [Description("Ignore")] + ignore, + [Description("Kill(Free Memory)")] + kill + } + + [Serializable] + public class ApplicationRules : INotifyPropertyChanged + { + private string appName; + private AppRulesEnum rule; + public string LocalisedRule { get; set; } + public string AppName + { + get + { + return appName; + } + set + { + appName = value; + OnPropertyChanged("AppName"); + } + } + public AppRulesEnum Rule + { + get + { + return rule; + } + set + { + rule = value; + if(value == AppRulesEnum.pause) + { + LocalisedRule = Properties.Resources.cmbBoxPause; + } + else if(value == AppRulesEnum.ignore) + { + LocalisedRule = Properties.Resources.txtIgnore; + } + else + { + LocalisedRule = Properties.Resources.cmbBoxKill; + } + OnPropertyChanged("Rule"); + OnPropertyChanged("LocalisedRule"); + } + } + public ApplicationRules() + { + AppName = null; + Rule = AppRulesEnum.ignore; + + } + + private void OnPropertyChanged(string property) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + + public event PropertyChangedEventHandler PropertyChanged; + } + public static List appRules = new List(); + public class ApplicationRulesList + { + public string AppVersion { get; set; } + public List App { get; set; } + public ApplicationRulesList() + { + AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + + public static void SaveApplicationRules() + { + ApplicationRulesList tmp = new ApplicationRulesList + { + App = appRules + }; + + JsonSerializer serializer = new JsonSerializer(); + serializer.Formatting = Formatting.Indented; + + //serializer.Converters.Add(new JavaScriptDateTimeConverter()); + serializer.NullValueHandling = NullValueHandling.Include; + /* + if (String.IsNullOrWhiteSpace(tmp.AppVersion)) + tmp.AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + */ + try + { + using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\application_rules.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, tmp); + } + } + catch(Exception e) + { + Logger.Error(e.ToString()); + } + } + + public static void LoadApplicationRules() + { + //default rules. + if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\application_rules.json")) + { + appRules.Add(new ApplicationRules { AppName = "Photoshop", Rule = AppRulesEnum.pause }); + appRules.Add(new ApplicationRules { AppName = "Discord", Rule = AppRulesEnum.ignore }); + SaveApplicationRules(); + return; + } + + try + { + // deserialize JSON directly from a file + using (StreamReader file = File.OpenText(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\application_rules.json")) + { + JsonSerializer serializer = new JsonSerializer(); + ApplicationRulesList tmp = (ApplicationRulesList)serializer.Deserialize(file, typeof(ApplicationRulesList)); + appRules = tmp.App; + } + + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + } + + #endregion apprule + + #region livelyinfo + + [Serializable] + public class LivelyInfo //wallpaper metadata + { + public string AppVersion { get; set; } + public string Title { get; set; } + public string Thumbnail { get; set; } + public string Preview { get; set; } //preview clip + public string Desc { get; set; } + public string Author { get; set; } + public string License { get; set; } + public string Contact { get; set; } + public SetupDesktop.WallpaperType Type { get; set; } + public string FileName { get; set; } + public string Arguments { get; set; } //start commandline args + public LivelyInfo() + { + AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + Title = null; + Thumbnail = null; + Preview = null; + Type = SetupDesktop.WallpaperType.web_audio; + FileName = null; + Desc = null; + Author = null; + License = null; + Contact = null; + Arguments = null; + } + + public LivelyInfo(LivelyInfo info) + { + AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + Title = info.Title; + Thumbnail = info.Thumbnail; + Preview = info.Preview; + Type = info.Type; + FileName = info.FileName; + Desc = info.Desc; + Author = info.Author; + Contact = info.Contact; + License = info.License; + Arguments = info.Arguments; + } + } + + public static LivelyInfo info = new LivelyInfo(); + public static void SaveWallpaperMetaData(LivelyInfo info, string path) //used to create livelyinfo.json file + { + //return; + JsonSerializer serializer = new JsonSerializer + { + Formatting = Formatting.Indented, + NullValueHandling = NullValueHandling.Include + }; + /* + if (String.IsNullOrWhiteSpace(info.AppVersion)) + info.AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + */ + try + { + using (StreamWriter sw = new StreamWriter(path + "\\LivelyInfo.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, info); + } + } + catch(Exception e) + { + Logger.Error(e.ToString()); + } + } + + /// + /// Load Livelinfo.json file. + /// + /// + /// true - success, false - failure + public static bool LoadWallpaperMetaData(string path) + { + try + { + using (StreamReader file = File.OpenText(path + "\\LivelyInfo.json")) + { + JsonSerializer serializer = new JsonSerializer(); + info = (LivelyInfo)serializer.Deserialize(file, typeof(LivelyInfo)); + } + return true; + } + catch (IOException e1) + { + Logger.Error("Error trying to read livelyinfo file from disc:- " + path + "\n" + e1.ToString() ); + return false; + } + catch(Exception e2) + { + Logger.Error("Corrupted livelinfo file, skipping wallpaper:- " + path + "\n" + e2.ToString()); + return false; + } + } + #endregion + + #region monitor_layout + + [Serializable] + public class WallpaperLayout + { + public string DeviceName { get; set; } + public SetupDesktop.WallpaperType Type { get; set; } //unsure + public string FilePath { get; set; } + public string Arguments { get; set; } + + public WallpaperLayout() + { + //displayID = 1; + Type = SetupDesktop.WallpaperType.video; + FilePath = null; + DeviceName = null; + Arguments = ""; + } + } + + public class WallpaperLayoutList + { + public string AppVersion { get; set; } + public List Layouts { get; set; } + + public WallpaperLayoutList() + { + AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + //public static List wallpapers = new List(); + + public static void SaveWallpaperLayout() + { + WallpaperLayoutList tmp = new WallpaperLayoutList + { + Layouts = SetupDesktop.wallpapers + }; + + JsonSerializer serializer = new JsonSerializer + { + Formatting = Formatting.Indented, + //serializer.Converters.Add(new JavaScriptDateTimeConverter()); + NullValueHandling = NullValueHandling.Include + }; + /* + if (String.IsNullOrWhiteSpace(tmp.AppVersion)) + tmp.AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + */ + try + { + using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\lively_layout.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, tmp); + } + } + catch(Exception e) + { + Logger.Error(e.ToString()); + } + } + + + public static void LoadWallpaperLayout() + { + if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\lively_layout.json")) + { + //SaveWallpaperLayout() + return; + } + + try + { + // deserialize JSON directly from a file + using (StreamReader file = File.OpenText(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\lively_layout.json")) + { + JsonSerializer serializer = new JsonSerializer(); + WallpaperLayoutList tmp = (WallpaperLayoutList)serializer.Deserialize(file, typeof(WallpaperLayoutList)); + SetupDesktop.wallpapers = tmp.Layouts; + } + + } + catch (Exception e) + { + SetupDesktop.wallpapers.Clear(); + Logger.Error(e.ToString()); + } + } + #endregion + + #region configuration_file + + public enum VideoPlayer + { + windowsmp, //0 + mediakit, //1 + } + + public enum GIFPlayer + { + xaml, + mediakit, + cef + } + + public enum DisplayPauseEnum + { + perdisplay, + all + } + + public enum ProcessMonitorAlgorithm + { + foreground, + all + } + + public enum WallpaperArrangement + { + [Description("Per Display")] + per, + [Description("Span Across All Display(s)")] + span + } + + public enum WallpaperRenderingMode + { + [Description("Behind desktop icons")] + behind_icons, + [Description("Make the window bottom-most, infront of icons")] + bottom_most + } + + [Serializable] + public class SupportedLanguages + { + public string Language { get; set; } + public string[] Codes { get; set; } + + public SupportedLanguages(string language, string[] codes) + { + this.Language = language; + this.Codes = codes; + } + } + //codes: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c + public static SupportedLanguages[] supportedLanguages = new SupportedLanguages[] { + new SupportedLanguages("English(en-US)", new string[]{"en-US"}), //technically not US english, sue me.. + new SupportedLanguages("中文(zh-CN)", new string[]{"zh", "zh-Hans","zh-CN","zh-SG"}), //are they same? + new SupportedLanguages("日本人(ja-JP)", new string[]{"ja", "ja-JP"}), + new SupportedLanguages("русский(ru)", new string[]{"ru", "ru-BY", "ru-KZ", "ru-KG", "ru-MD", "ru-RU","ru-UA"}), //are they same? + new SupportedLanguages("हिन्दी(hi-IN)", new string[]{"hi", "hi-IN"}) + }; + [Serializable] + public class ConfigFile + { + private string language; + public string AppVersion { get; set; } + public string Language + { + get { + return language; + } + + set + { + if (value == null) + { + value = "en-US"; + } + bool detectedLang = false; + //todo: make this more elegant? + foreach (var item in supportedLanguages) + { + if(Array.Exists(item.Codes, x => x.Equals(value, StringComparison.OrdinalIgnoreCase) )) + { + language = value; + detectedLang = true; + break; + } + } + + if(!detectedLang) + language = "en-US"; + } + } + + public bool Startup { get; set; } + public bool AppTransparency { get; set; } + public bool IsFirstRun { get; set; } + public AppRulesEnum AppFocusPause { get; set; } + public AppRulesEnum AppFullscreenPause { get; set; } + public DisplayPauseEnum DisplayPauseSettings { get; set; } + public ProcessMonitorAlgorithm ProcessMonitorAlgorithm { get; set; } + public bool MuteVideo { get; set; } + public bool MuteCef { get; set; } //unused, need to get processid of subprocess of cef. + public bool MuteCefAudioIn { get; set; } + public bool MuteMic { get; set; } + public bool LiveTile { get; set; } + public System.Windows.Media.Stretch VideoScaler { get; set; } + public System.Windows.Media.Stretch GifScaler { get; set; } + + public WallpaperArrangement WallpaperArrangement { get; set; } // 0 -per monitor, 1-span + public bool DXVA { get; set; } //hw acceleration videoplayback, currently unused. + public bool MouseHook { get; set; } //unused currently. + public bool KeyHook { get; set; } //only bizhawk. + public bool RunOnlyDesktop { get; set; } //run only when on desktop focus. + public VideoPlayer VidPlayer { get; set; } + public GIFPlayer GifPlayer { get; set; } + + public string DefaultURL { get; set; } + public string BizHawkPath { get; set; } + public string MPVPath { get; set; } //mpv external video player, unused + public bool Ui120FPS { get; set; } + public bool UiDisableHW { get; set; } + + /// + /// Timer interval(in milliseconds), used to monitor running apps to determine pause/play of wp's. + /// + public int ProcessTimerInterval { get; set; } + public WallpaperRenderingMode WallpaperRendering { get; set; } + /// + /// Timeout for application wallpaper startup (in milliseconds), lively will kill wp if gui is not ready within this timeframe. + /// + public int WallpaperWaitTime { get; set; } + + // warning user of risk, count. + public int WarningUnity { get; set; } + public int WarningGodot { get; set; } + public int WarningURL { get; set; } + public int WarningApp { get; set; } + public bool SafeShutdown { get; set; } + + public bool IsRestart { get; set; } + public bool InstallUpdate { get; set; } //future use. + + //default values + public ConfigFile() + { + DefaultURL = "https://www.shadertoy.com/view/MsKcRh"; + MuteCef = false; + MuteMic = false; + MuteCefAudioIn = false; + MuteVideo = false; + ProcessMonitorAlgorithm = ProcessMonitorAlgorithm.foreground; + WallpaperArrangement = WallpaperArrangement.per; + AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + Startup = false; + IsFirstRun = true; + AppFocusPause = AppRulesEnum.ignore; + AppFullscreenPause = AppRulesEnum.pause; + DXVA = true; + MouseHook = true; + KeyHook = false; + BizHawkPath = null; + //WallpaperType = SetupDesktop.WallpaperType.app; + VidPlayer = VideoPlayer.windowsmp; + //CurrWallpaperPath = null; + MPVPath = null; + RunOnlyDesktop = false; + AppTransparency = false; + GifPlayer = GIFPlayer.xaml; + Ui120FPS = false; + UiDisableHW = false; + WallpaperRendering = WallpaperRenderingMode.behind_icons; + WallpaperWaitTime = 30000; // 30sec + ProcessTimerInterval = 500; //reduce to 250 for quicker response. + Language = CultureInfo.CurrentCulture.Name;//"en"; + + //media scaling + VideoScaler = System.Windows.Media.Stretch.UniformToFill; //3 + GifScaler = System.Windows.Media.Stretch.UniformToFill; + + WarningApp = 0; + WarningUnity = 0; + WarningGodot = 0; + WarningURL = 0; + + SafeShutdown = true; + IsRestart = false; + InstallUpdate = false; + } + } + public static ConfigFile config = new ConfigFile(); + /// + /// Loads settigns file from disk if found, else creates settings files with default constructor values. + /// + public static void LoadConfig() + { + if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\lively_config.json")) + { + //writing default savefile to storage. + SaveConfig(); + return; + } + + try + { + // deserialize JSON directly from a file + using (StreamReader file = File.OpenText(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\lively_config.json")) + { + JsonSerializer serializer = new JsonSerializer(); + config = (ConfigFile)serializer.Deserialize(file, typeof(ConfigFile)); + } + + //config = JsonConvert.DeserializeObject(AppDomain.CurrentDomain.BaseDirectory + "\\lively_config.json"); + } + catch(Exception e) + { + Logger.Error(e.ToString()); + } + } + + public static void SaveConfig() + { + JsonSerializer serializer = new JsonSerializer + { + Formatting = Formatting.Indented, + //serializer.Converters.Add(new JavaScriptDateTimeConverter()); + NullValueHandling = NullValueHandling.Include + }; + /* + if (String.IsNullOrWhiteSpace(config.AppVersion)) + config.AppVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); + */ + try + { + using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\SaveData\\lively_config.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, config); + } + } + catch(Exception e) + { + Logger.Error(e.ToString()); + } + } + #endregion + + #region background_monitor_process + + [Serializable] + public class RunningProgram + { + public string ProcessName { get; set; } + public int Pid { get; set; } + public RunningProgram() + { + Pid = 0; + ProcessName = null; + } + } + public static List runningPrograms = new List(); + + public class RunningProgramsList + { + public List Item { get; set; } + } + + + public static void SaveRunningPrograms() + { + RunningProgramsList tmp = new RunningProgramsList + { + Item = runningPrograms + }; + + JsonSerializer serializer = new JsonSerializer + { + Formatting = Formatting.Indented, + + NullValueHandling = NullValueHandling.Include + }; + + try + { + using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\lively_running_pgms.json")) + using (JsonWriter writer = new JsonTextWriter(sw)) + { + serializer.Serialize(writer, tmp); + } + } + catch(Exception e) + { + Logger.Error(e.ToString()); + } + } + + public static void LoadRunningPrograms() + { + if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\lively_running_pgms.json")) + { + return; + } + + try + { + // deserialize JSON directly from a file + using (StreamReader file = File.OpenText(AppDomain.CurrentDomain.BaseDirectory + "\\lively_running_pgms.json")) + { + JsonSerializer serializer = new JsonSerializer(); + RunningProgramsList tmp = (RunningProgramsList)serializer.Deserialize(file, typeof(RunningProgramsList)); + runningPrograms = tmp.Item; + } + + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + } + + #endregion background_monitor_process + + #region library_tile + public class TileData : INotifyPropertyChanged + { + private BitmapImage img; + private string tilePreview; + public BitmapImage Img + { + get + { + /* + if (img == null) + return DependencyProperty.UnsetValue; + */ + return img; + } + set + { + img = value; + OnPropertyChanged("Img"); + } + } + public string TilePreview + { + get + { + /* + if (string.IsNullOrEmpty(tilePreview)) + return DependencyProperty.UnsetValue; + */ + return tilePreview; + } + set + { + tilePreview = value; + OnPropertyChanged("TilePreview"); + } + } + + public Uri UriContact { get; set; } + public string Type { get; set; } + public SaveData.LivelyInfo LivelyInfo { get; set; } + + public TileData(SaveData.LivelyInfo info) + { + TilePreview = null; //otherwise everything gets loaded at once! + if (!SaveData.config.LiveTile) + { + //Img = LoadImage(info.Thumbnail); + Img = LoadConvertImage(info.Thumbnail); + } + else + { + Img = null; + } + UriContact = GetUri(info.Contact, "https"); + Type = LibraryInfoTypeText(info); + LivelyInfo = info; + } + + private void OnPropertyChanged(string property) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + public event PropertyChangedEventHandler PropertyChanged; + + private string LibraryInfoTypeText(SaveData.LivelyInfo info) + { + if (info.Type == SetupDesktop.WallpaperType.video) + { + var dimension = MainWindow.GetVideoSize(info.FileName); + //return info.Type.ToString().ToUpper() + ", " + dimension.Width + "x" + dimension.Height; + return Properties.Resources.txtLivelyWallpaperTypeVideo + ", " + dimension.Width + "x" + dimension.Height; + } + else if(info.Type == SetupDesktop.WallpaperType.app) + { + return Properties.Resources.txtLivelyWallpaperTypeApp; + //return info.Type.ToString().ToUpper(); + } + else if(info.Type == SetupDesktop.WallpaperType.godot) + { + return Properties.Resources.txtLivelyWallpaperTypeGodot; + } + else if (info.Type == SetupDesktop.WallpaperType.unity) + { + return Properties.Resources.txtLivelyWallpaperTypeUnity; + } + else if (info.Type == SetupDesktop.WallpaperType.unity_audio) + { + return Properties.Resources.txtLivelyWallpaperTypeUnityAudio; + } + else if (info.Type == SetupDesktop.WallpaperType.web) + { + return Properties.Resources.txtLivelyWallpaperTypeWeb; + } + else if (info.Type == SetupDesktop.WallpaperType.web_audio) + { + return Properties.Resources.txtLivelyWallpaperTypeWebAudio; + } + else if (info.Type == SetupDesktop.WallpaperType.gif) + { + return Properties.Resources.txtLivelyWallpaperTypeGIF; + } + else + { + return info.Type.ToString(); + } + } + + public BitmapImage LoadImage(string filename) + { + //return new BitmapImage(new Uri(filename)); // file gets locked, can't delete folder. + try + { + using (var stream = File.OpenRead(filename)) + { + var bmp = new BitmapImage(); + bmp.BeginInit(); + bmp.StreamSource = stream; + bmp.CacheOption = BitmapCacheOption.OnLoad;//allow deletion of file on disk. + bmp.EndInit(); + return bmp; + } + } + catch (Exception) + { + return null; + } + } + + /// + /// Reduces imagesize to 100x100 + /// + private BitmapImage LoadConvertImage(string filename) + { + BitmapImage bi = new BitmapImage(); + bi.BeginInit(); + bi.DecodePixelWidth = 100; + bi.CacheOption = BitmapCacheOption.OnLoad; //allow deletion of file on disk. + bi.UriSource = new Uri(filename); + bi.EndInit(); + return bi; + } + + private Uri GetUri(string s, string scheme) + { + try + { + return new UriBuilder(s) + { + Scheme = scheme, + Port = -1, + }.Uri; + } + catch (ArgumentNullException) + { + return null; + } + catch (UriFormatException) + { + return null; + } + } + } + + #endregion + + #region displayID_dialogue_data + public class DisplayListBox : INotifyPropertyChanged + { + private string displayDevice; + private string fileName; + private string filePath; + public string DisplayDevice + { + get + { + return displayDevice; + } + set + { + displayDevice = value; + OnPropertyChanged("DisplayID"); + } + } + public string FileName + { + get + { + return fileName; + } + set + { + fileName = value; + OnPropertyChanged("FileName"); + } + } + public string FilePath + { + get + { + return filePath; + } + set + { + filePath = value; + OnPropertyChanged("FilePath"); + } + } + + public DisplayListBox(string scr, string filePath) + { + DisplayDevice = scr; + FilePath = filePath; + if (filePath != null) + { + try + { + FileName = System.IO.Path.GetFileName(filePath); + } + catch (ArgumentException) + { + FileName = "Error"; + } + + if (String.IsNullOrWhiteSpace(FileName)) + { + FileName = filePath; + } + } + } + private void OnPropertyChanged(string property) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + public event PropertyChangedEventHandler PropertyChanged; + } + #endregion + + } +} diff --git a/src/livelywpf/livelywpf/save/SystemInfo.cs b/src/livelywpf/livelywpf/save/SystemInfo.cs new file mode 100644 index 00000000..bea9211d --- /dev/null +++ b/src/livelywpf/livelywpf/save/SystemInfo.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Management; +using System.Globalization; + +namespace livelywpf +{ + /// + /// Retrieve system information:- operating system version, cpu & gpu name. + /// + public static class SystemInfo + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public static void LogHardwareInfo() + { + Logger.Info("Lively v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() + " " + CultureInfo.CurrentCulture.Name + " 64Bit:" + Environment.Is64BitProcess); + GetOSInfo(); + GetCPUInfo(); + GetGPUInfo(); + } + + private static void GetGPUInfo() + { + try + { + using (ManagementObjectSearcher myVideoObject = new ManagementObjectSearcher("select * from Win32_VideoController")) + { + foreach (ManagementObject obj in myVideoObject.Get()) + { + Logger.Info("GPU: " + obj["Name"]); + } + } + } + catch(Exception e) + { + Logger.Info("GPU: " + e.Message); + } + } + + private static void GetCPUInfo() + { + try + { + using (ManagementObjectSearcher myProcessorObject = new ManagementObjectSearcher("select * from Win32_Processor")) + { + foreach (ManagementObject obj in myProcessorObject.Get()) + { + Logger.Info("CPU: " + obj["Name"]); + } + } + } + catch(Exception e) + { + Logger.Info("CPU: " + e.Message); + } + } + + private static void GetOSInfo() + { + try + { + using (ManagementObjectSearcher myOperativeSystemObject = new ManagementObjectSearcher("select * from Win32_OperatingSystem")) + { + foreach (ManagementObject obj in myOperativeSystemObject.Get()) + { + Logger.Info("OS: " + obj["Caption"] + " " + obj["Version"]); + } + } + } + catch(Exception e) + { + Logger.Info("OS: " + e.Message); + } + } + } +} diff --git a/src/livelywpf/livelywpf/wp_lib/NativeMethods.cs b/src/livelywpf/livelywpf/wp_lib/NativeMethods.cs new file mode 100644 index 00000000..22f5e26a --- /dev/null +++ b/src/livelywpf/livelywpf/wp_lib/NativeMethods.cs @@ -0,0 +1,656 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace livelywpf +{ +#pragma warning disable CA1707, CA1401, CA1712 + public static class NativeMethods + { + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindow(IntPtr hWnd); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern int GetWindowTextLength(IntPtr hWnd); + + [DllImport("kernel32.dll")] + public static extern bool SetProcessWorkingSetSize(IntPtr hProcess, int + dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize); + + #region Window_Style + [DllImport("user32.dll")] + public static extern IntPtr GetMenu(IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern int GetMenuItemCount(IntPtr hMenu); + + [DllImport("user32.dll")] + public static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags); + + [DllImport("user32.dll")] + public static extern bool DrawMenuBar(IntPtr hWnd); + + public static uint MF_BYPOSITION = 0x400; + public static uint MF_REMOVE = 0x1000; + + // This helper static method is required because the 32-bit version of user32.dll does not contain this API + // (on any versions of Windows), so linking the method will fail at run-time. The bridge dispatches the request + // to the correct function (GetWindowLong in 32-bit mode and GetWindowLongPtr in 64-bit mode) + public static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong) + { + + if (IntPtr.Size == 8) + return SetWindowLongPtr64(hWnd, nIndex, dwNewLong); + else + return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32())); + + } + + [DllImport("user32.dll", EntryPoint = "SetWindowLong")] + public static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong); + + [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")] + public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong); + + #endregion + //ref: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error?view=netframework-4.8 + //[DllImportAttribute("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + //public static extern int MessageBox(IntPtr hwnd, String text, String caption, uint type); + + #region SetupDesktop.cs + [Flags] + public enum SendMessageTimeoutFlags : uint + { + SMTO_NORMAL = 0x0, + SMTO_BLOCK = 0x1, + SMTO_ABORTIFHUNG = 0x2, + SMTO_NOTIMEOUTIFNOTHUNG = 0x8, + SMTO_ERRORONEXIT = 0x20 + } + + [DllImport("user32.dll")] + public static extern IntPtr GetShellWindow(); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr FindWindow(string lpWindowClass, string lpWindowName); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out IntPtr lpdwResult); + + [DllImport("user32.dll")] + public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); + public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle); + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle); + + [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] + public static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr SetParent(IntPtr child, IntPtr parent); + + #region sendmsg + [DllImport("User32.dll", EntryPoint = "SendMessage")] + public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + public const int WM_KEYDOWN = 0x0100; + public const int WM_KEYUP = 0x0101; + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("user32.dll", SetLastError = true)] + public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam); + #endregion + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode); + + /* + [DllImport("user32.dll")] + public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); + [DllImport("user32.dll")] + public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, long dwNewLong); + */ + + [DllImport("user32.dll", EntryPoint = "GetWindowLong")] + private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")] + private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex); + + // This static method is required because Win32 does not support + // GetWindowLongPtr directly + public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex) + { + if (IntPtr.Size == 8) + return GetWindowLongPtr64(hWnd, nIndex); + else + return GetWindowLongPtr32(hWnd, nIndex); + } + + public enum GWL + { + GWL_WNDPROC = (-4), + GWL_HINSTANCE = (-6), + GWL_HWNDPARENT = (-8), + GWL_STYLE = (-16), + GWL_EXSTYLE = (-20), + GWL_USERDATA = (-21), + GWL_ID = (-12) + } + + public abstract class WindowStyles + { + public const uint WS_OVERLAPPED = 0x00000000; + public const uint WS_POPUP = 0x80000000; + public const uint WS_CHILD = 0x40000000; + public const uint WS_MINIMIZE = 0x20000000; + public const uint WS_VISIBLE = 0x10000000; + public const uint WS_DISABLED = 0x08000000; + public const uint WS_CLIPSIBLINGS = 0x04000000; + public const uint WS_CLIPCHILDREN = 0x02000000; + public const uint WS_MAXIMIZE = 0x01000000; + public const uint WS_CAPTION = 0x00C00000; /* WS_BORDER | WS_DLGFRAME */ + public const uint WS_BORDER = 0x00800000; + public const uint WS_DLGFRAME = 0x00400000; + public const uint WS_VSCROLL = 0x00200000; + public const uint WS_HSCROLL = 0x00100000; + public const uint WS_SYSMENU = 0x00080000; + public const uint WS_THICKFRAME = 0x00040000; + public const uint WS_GROUP = 0x00020000; + public const uint WS_TABSTOP = 0x00010000; + + public const uint WS_MINIMIZEBOX = 0x00020000; + public const uint WS_MAXIMIZEBOX = 0x00010000; + + public const uint WS_TILED = WS_OVERLAPPED; + public const uint WS_ICONIC = WS_MINIMIZE; + public const uint WS_SIZEBOX = WS_THICKFRAME; + public const uint WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW; + + // Common Window Styles + + public const uint WS_OVERLAPPEDWINDOW = + (WS_OVERLAPPED | + WS_CAPTION | + WS_SYSMENU | + WS_THICKFRAME | + WS_MINIMIZEBOX | + WS_MAXIMIZEBOX); + + public const uint WS_POPUPWINDOW = + (WS_POPUP | + WS_BORDER | + WS_SYSMENU); + + public const uint WS_CHILDWINDOW = WS_CHILD; + + //Extended Window Styles + + public const uint WS_EX_DLGMODALFRAME = 0x00000001; + public const uint WS_EX_NOPARENTNOTIFY = 0x00000004; + public const uint WS_EX_TOPMOST = 0x00000008; + public const uint WS_EX_ACCEPTFILES = 0x00000010; + public const uint WS_EX_TRANSPARENT = 0x00000020; + + //#if(WINVER >= 0x0400) + public const uint WS_EX_MDICHILD = 0x00000040; + public const uint WS_EX_TOOLWINDOW = 0x00000080; + public const uint WS_EX_WINDOWEDGE = 0x00000100; + public const uint WS_EX_CLIENTEDGE = 0x00000200; + public const uint WS_EX_CONTEXTHELP = 0x00000400; + + public const uint WS_EX_RIGHT = 0x00001000; + public const uint WS_EX_LEFT = 0x00000000; + public const uint WS_EX_RTLREADING = 0x00002000; + public const uint WS_EX_LTRREADING = 0x00000000; + public const uint WS_EX_LEFTSCROLLBAR = 0x00004000; + public const uint WS_EX_RIGHTSCROLLBAR = 0x00000000; + + public const uint WS_EX_CONTROLPARENT = 0x00010000; + public const uint WS_EX_STATICEDGE = 0x00020000; + public const uint WS_EX_APPWINDOW = 0x00040000; + + public const uint WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); + public const uint WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST); + //#endif /* WINVER >= 0x0400 */ + + //#if(_WIN32_WINNT >= 0x0500) + public const uint WS_EX_LAYERED = 0x00080000; + //#endif /* _WIN32_WINNT >= 0x0500 */ + + //#if(WINVER >= 0x0500) + public const uint WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children + public const uint WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring + //#endif /* WINVER >= 0x0500 */ + + //#if(_WIN32_WINNT >= 0x0500) + public const uint WS_EX_COMPOSITED = 0x02000000; + public const uint WS_EX_NOACTIVATE = 0x08000000; + //#endif /* _WIN32_WINNT >= 0x0500 */ + } + + + [DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWindowPos(IntPtr hwnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags); + + [DllImport("user32.dll")] + public static extern IntPtr GetDesktopWindow(); + + [DllImport("Shell32.dll")] + public static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni); + + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern bool SystemParametersInfo( + int uAction, int uParam, [MarshalAs(UnmanagedType.I1)] bool lpvParam, + int flags); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern bool SystemParametersInfo( + int uAction, int uParam, ref int lpvParam, + int flags); + + + public static UInt32 SPI_SETDESKWALLPAPER = 20; + public static UInt32 SPIF_UPDATEINIFILE = 0x1; + public static UInt32 SPI_SETCLIENTAREAANIMATION = 0x1043; + + #endregion SetupDesktop.cs + + #region keyboard + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr SetFocus(IntPtr hWnd); + + [DllImport("User32.dll")] + public static extern int SetForegroundWindow(IntPtr point); + + #endregion keyboard + + + #region Pause + + + [DllImport("USER32.DLL")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindowVisible(IntPtr hWnd); + + //..Pause.c + [Flags] + public enum ThreadAccess : int + { + TERMINATE = (0x0001), + SUSPEND_RESUME = (0x0002), + GET_CONTEXT = (0x0008), + SET_CONTEXT = (0x0010), + SET_INFORMATION = (0x0020), + QUERY_INFORMATION = (0x0040), + SET_THREAD_TOKEN = (0x0080), + IMPERSONATE = (0x0100), + DIRECT_IMPERSONATION = (0x0200) + } + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + [DllImport("kernel32.dll")] + public static extern uint SuspendThread(IntPtr hThread); + [DllImport("kernel32.dll")] + public static extern int ResumeThread(IntPtr hThread); + + //..pause logic + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + + [DllImport("user32.dll")] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); + + [DllImport("coredll.dll", SetLastError = true)] + static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + [DllImport("coredll.dll", SetLastError = true)] + public static extern int GetModuleFileName(UIntPtr hModule, StringBuilder lpFilename, int nSize); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetWindowRect(IntPtr hwnd, out RECT rc); + + [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool CloseHandle(IntPtr handle); + + public const int APPCOMMAND_VOLUME_MUTE = 0x80000; + public const int WM_APPCOMMAND = 0x319; + + [DllImport("user32.dll")] + public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); + + #endregion pause + + #region ScreenResolution + + public const int MONITOR_DEFAULTTONULL = 0; + public const int MONITOR_DEFAULTTOPRIMARY = 1; + public const int MONITOR_DEFAULTTONEAREST = 2; + + [DllImport("user32.dll")] + public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags); + + [StructLayout(LayoutKind.Sequential)] + public struct POINT + { + public int X; + public int Y; + + public POINT(int x, int y) + { + this.X = x; + this.Y = y; + } + + public static implicit operator System.Drawing.Point(POINT p) + { + return new System.Drawing.Point(p.X, p.Y); + } + + public static implicit operator POINT(System.Drawing.Point p) + { + return new POINT(p.X, p.Y); + } + } + + [DllImport("user32.dll")] + public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint); + + [DllImport("user32", ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref RECT rect, [MarshalAs(UnmanagedType.U4)] int cPoints); + + [DllImport("user32", ExactSpelling = true, SetLastError = true)] + public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref System.Drawing.Point pt, [MarshalAs(UnmanagedType.U4)] int cPoints); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); + + [DllImport("User32.dll")] + public static extern IntPtr GetDC(IntPtr hwnd); + + [DllImport("User32.dll")] + public static extern int ReleaseDC(IntPtr hwnd, IntPtr dc); + + [DllImport("gdi32.dll")] + public static extern int GetDeviceCaps(IntPtr hdc, int nIndex); + + //..IsIconic = minimized. IsZoomed = maximixed + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsIconic(IntPtr hWnd); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsZoomed(IntPtr hWnd); + + [Flags] + public enum SetWindowPosFlags : int + { + // ReSharper disable InconsistentNaming + + /// + /// If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request. + /// + SWP_ASYNCWINDOWPOS = 0x4000, + + /// + /// Prevents generation of the WM_SYNCPAINT message. + /// + SWP_DEFERERASE = 0x2000, + + /// + /// Draws a frame (defined in the window's class description) around the window. + /// + SWP_DRAWFRAME = 0x0020, + + /// + /// Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed. + /// + SWP_FRAMECHANGED = 0x0020, + + /// + /// Hides the window. + /// + SWP_HIDEWINDOW = 0x0080, + + /// + /// Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter). + /// + SWP_NOACTIVATE = 0x0010, + + /// + /// Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned. + /// + SWP_NOCOPYBITS = 0x0100, + + /// + /// Retains the current position (ignores X and Y parameters). + /// + SWP_NOMOVE = 0x0002, + + /// + /// Does not change the owner window's position in the Z order. + /// + SWP_NOOWNERZORDER = 0x0200, + + /// + /// Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing. + /// + SWP_NOREDRAW = 0x0008, + + /// + /// Same as the SWP_NOOWNERZORDER flag. + /// + SWP_NOREPOSITION = 0x0200, + + /// + /// Prevents the window from receiving the WM_WINDOWPOSCHANGING message. + /// + SWP_NOSENDCHANGING = 0x0400, + + /// + /// Retains the current size (ignores the cx and cy parameters). + /// + SWP_NOSIZE = 0x0001, + + /// + /// Retains the current Z order (ignores the hWndInsertAfter parameter). + /// + SWP_NOZORDER = 0x0004, + + /// + /// Displays the window. + /// + SWP_SHOWWINDOW = 0x0040, + + // ReSharper restore InconsistentNaming + } + #endregion ScreenResolution + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MonitorInfoEx lpmi); + + // size of a device name string + public const int CCHDEVICENAME = 32; + /// + /// The MONITORINFOEX structure contains information about a display monitor. + /// The GetMonitorInfo function stores information into a MONITORINFOEX structure or a MONITORINFO structure. + /// The MONITORINFOEX structure is a superset of the MONITORINFO structure. The MONITORINFOEX structure adds a string member to contain a name + /// for the display monitor. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct MonitorInfoEx + { + /// + /// The size, in bytes, of the structure. Set this member to sizeof(MONITORINFOEX) (72) before calling the GetMonitorInfo function. + /// Doing so lets the function determine the type of structure you are passing to it. + /// + public int Size; + + /// + /// A RECT structure that specifies the display monitor rectangle, expressed in virtual-screen coordinates. + /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values. + /// + public RectStruct Monitor; + + /// + /// A RECT structure that specifies the work area rectangle of the display monitor that can be used by applications, + /// expressed in virtual-screen coordinates. Windows uses this rectangle to maximize an application on the monitor. + /// The rest of the area in rcMonitor contains system windows such as the task bar and side bars. + /// Note that if the monitor is not the primary display monitor, some of the rectangle's coordinates may be negative values. + /// + public RectStruct WorkArea; + + /// + /// The attributes of the display monitor. + /// + /// This member can be the following value: + /// 1 : MONITORINFOF_PRIMARY + /// + public uint Flags; + + /// + /// A string that specifies the device name of the monitor being used. Most applications have no use for a display monitor name, + /// and so can save some bytes by using a MONITORINFO structure. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)] + public string DeviceName; + + public void Init() + { + this.Size = 40 + 2 * CCHDEVICENAME; + this.DeviceName = string.Empty; + } + } + /// + /// The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle. + /// + /// + /// + /// By convention, the right and bottom edges of the rectangle are normally considered exclusive. + /// In other words, the pixel whose coordinates are ( right, bottom ) lies immediately outside of the the rectangle. + /// For example, when RECT is passed to the FillRect function, the rectangle is filled up to, but not including, + /// the right column and bottom row of pixels. This structure is identical to the RECTL structure. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RectStruct + { + /// + /// The x-coordinate of the upper-left corner of the rectangle. + /// + public int Left; + + /// + /// The y-coordinate of the upper-left corner of the rectangle. + /// + public int Top; + + /// + /// The x-coordinate of the lower-right corner of the rectangle. + /// + public int Right; + + /// + /// The y-coordinate of the lower-right corner of the rectangle. + /// + public int Bottom; + } + + #region parentprocess + /// + /// A utility class to determine a process parent. + /// + [StructLayout(LayoutKind.Sequential)] + public struct ParentProcessUtilities + { + // These members must match PROCESS_BASIC_INFORMATION + internal IntPtr Reserved1; + internal IntPtr PebBaseAddress; + internal IntPtr Reserved2_0; + internal IntPtr Reserved2_1; + internal IntPtr UniqueProcessId; + internal IntPtr InheritedFromUniqueProcessId; + + [DllImport("ntdll.dll")] + private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength); + + /// + /// Gets the parent process of the current process. + /// + /// An instance of the Process class. + public static Process GetParentProcess() + { + return GetParentProcess(Process.GetCurrentProcess().Handle); + } + + /// + /// Gets the parent process of specified process. + /// + /// The process id. + /// An instance of the Process class. + public static Process GetParentProcess(int id) + { + Process process = Process.GetProcessById(id); + return GetParentProcess(process.Handle); + } + + /// + /// Gets the parent process of a specified process. + /// + /// The process handle. + /// An instance of the Process class. + public static Process GetParentProcess(IntPtr handle) + { + ParentProcessUtilities pbi = new ParentProcessUtilities(); + int returnLength; + int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength); + if (status != 0) + throw new Win32Exception(status); + + try + { + return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32()); + } + catch (ArgumentException) + { + // not found + return null; + } + } + } + #endregion + } +#pragma warning restore CA1707, CA1401, CA1712 + +} diff --git a/src/livelywpf/livelywpf/wp_lib/Pause.cs b/src/livelywpf/livelywpf/wp_lib/Pause.cs new file mode 100644 index 00000000..6f798032 --- /dev/null +++ b/src/livelywpf/livelywpf/wp_lib/Pause.cs @@ -0,0 +1,397 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +//using CefSharp; + +namespace livelywpf +{ + //todo:- change confusing function names(wtf was I thinking) & beheavior for suspendwallpaper() & resumewallpaper() + public static class Pause + { + /// + /// PAUSE, UNPAUSE/MUTES-AUIDIO of all currently running wp's based input parameters. + /// If isFullScreen = true, pause everything; otherwise Resume playback. + /// + /// + /// is the running app(s) window fullscreen + /// if null, ignore displayDevice check:- applies to all screen. + public static void SuspendWallpaper(bool isFullScreen, string displayDeviceName = null ) + { + try + { + if (isFullScreen) //fullscreen app, pauses all wp's & mute audio. + { + MainWindow.SwitchTrayIcon(true); + foreach (var item in SetupDesktop.mediakitPlayers) + { + //item.mp.StopPlayer(); + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + item.MP.PausePlayer(); + } + + foreach (var item in SetupDesktop.wmPlayers) + { + + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + item.MP.PausePlayer(); + } + + foreach (var item in SetupDesktop.gifWallpapers) + { + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + item.Gif.PausePlayer(); + } + + foreach (var item in SetupDesktop.webProcesses) + { + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + { + NativeMethods.ShowWindow(item.Handle, 6); //minimize + //pausing audio thread causes some audio to remain playing?! todo: find a more elegant soln. + if (SaveData.config.MuteCefAudioIn) + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + else + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + } + } + + foreach (var item in SetupDesktop.extPrograms) + { + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + { + Pause.SuspendAllThreads(item); + //pausing audio thread causes some audio to remain playing?! + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + } + } + + } + else //non fullscreen application infocus, mostly mutes audio & resume playback of all wp's. + { + MainWindow.SwitchTrayIcon(false); + foreach (var item in SetupDesktop.mediakitPlayers) + { + item.MP.MutePlayer(true); + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + item.MP.PlayMedia(); + } + + foreach (var item in SetupDesktop.wmPlayers) + { + item.MP.MutePlayer(true); + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + item.MP.PlayMedia(); + } + + foreach (var item in SetupDesktop.gifWallpapers) + { + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + item.Gif.ResumePlayer(); + } + + foreach (var item in SetupDesktop.webProcesses) + { + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + { + NativeMethods.ShowWindow(item.Handle, 1); //normal + NativeMethods.ShowWindow(item.Handle, 5); //show + + if (SaveData.config.MuteCefAudioIn) + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + else + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + } + //Pause.ResumeAllThreads(item); + } + + foreach (var item in SetupDesktop.extPrograms) + { + if (item.DisplayID == displayDeviceName || displayDeviceName == null) + { + Pause.ResumeAllThreads(item); + //pausing audio thread causes some audio to remain playing?! + if (item.Type == SetupDesktop.WallpaperType.unity_audio) + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + else + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + } + } + + } + } + catch(InvalidOperationException) + { + //loop running on list when modification being done(rare), ignore since this fn is run continously every 500msec... everythings fine *nervous laughter* + //todo: could make a copy of it usin ToList(), will try later. + } + + } + + /// + /// UNPAUSE all currently running wp's based given conditions. + /// If isFullScreen = true, Resume everything; otherwise Resume playback. + /// + /// + /// is the window fullscreen + /// if null, ignore displayDevice check. + public static void ResumeWallpaper(bool isFullScreen, string display = null) + { + try + { + if (isFullScreen) //desktop(why else would u call resume for fullscreen app) etc, unmutes audio & resume wp's playback. + { + MainWindow.SwitchTrayIcon(false); + foreach (var item in SetupDesktop.mediakitPlayers) + { + if (SaveData.config.MuteVideo || display != null) // (user setting || multimonitor scenario) + item.MP.MutePlayer(true); + else + item.MP.MutePlayer(false); + + if (item.DisplayID == display || display == null) + { + item.MP.PlayMedia(); + } + } + + foreach (var item in SetupDesktop.wmPlayers) + { + if (SaveData.config.MuteVideo || display != null) // (user setting || multimonitor scenario) + item.MP.MutePlayer(true); + else + item.MP.MutePlayer(false); + + if (item.DisplayID == display || display == null) + { + item.MP.PlayMedia(); + } + } + + foreach (var item in SetupDesktop.gifWallpapers) + { + if (item.DisplayID == display || display == null) + item.Gif.ResumePlayer(); + } + + foreach (var item in SetupDesktop.webProcesses) + { + if (item.DisplayID == display || display == null) + { + NativeMethods.ShowWindow(item.Handle, 1); //normal + NativeMethods.ShowWindow(item.Handle, 5); //show + + if (SaveData.config.MuteCefAudioIn) + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + else + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + } + } + + foreach (var item in SetupDesktop.extPrograms) + { + if (item.DisplayID == display || display == null) + { + Pause.ResumeAllThreads(item); + //pausing audio thread causes some audio to remain playing?! + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + } + + } + } + else //non fullscreen application infocus, unmutes audio & resume wp's playback. + { + MainWindow.SwitchTrayIcon(false); + foreach (var item in SetupDesktop.mediakitPlayers) + { + if (SaveData.config.MuteVideo || display != null) // (user setting || multimonitor scenario) + item.MP.MutePlayer(true); + else + item.MP.MutePlayer(false); + if (item.DisplayID == display || display == null) + { + item.MP.PlayMedia(); + } + } + + foreach (var item in SetupDesktop.wmPlayers) + { + if (SaveData.config.MuteVideo || display != null) // (user setting || multimonitor scenario) + item.MP.MutePlayer(true); + else + item.MP.MutePlayer(false); + if (item.DisplayID == display || display == null) + { + item.MP.PlayMedia(); + } + } + + foreach (var item in SetupDesktop.gifWallpapers) + { + if (item.DisplayID == display || display == null) + item.Gif.ResumePlayer(); + } + + foreach (var item in SetupDesktop.webProcesses) + { + if (item.DisplayID == display || display == null) + { + NativeMethods.ShowWindow(item.Handle, 1); //normal + NativeMethods.ShowWindow(item.Handle, 5); //show + + if (SaveData.config.MuteCefAudioIn) + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + else + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + } + } + + foreach (var item in SetupDesktop.extPrograms) + { + if (item.DisplayID == display || display == null) + { + Pause.ResumeAllThreads(item); + //pausing audio thread causes some audio to remain playing?! + if (item.Type == SetupDesktop.WallpaperType.unity_audio) + VolumeMixer.SetApplicationMute(item.Proc.Id, false); + else + VolumeMixer.SetApplicationMute(item.Proc.Id, true); + } + } + } + } + catch(InvalidOperationException) + { + //ignore + } + } + + static void SuspendAllThreads(SetupDesktop.ExtProgram item) + { + try + { + foreach (ProcessThread thread in item.Proc.Threads) + { + var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + { + break; + // continue; + } + + /* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-suspendthread + * Each thread has a suspend count (with a maximum value of MAXIMUM_SUSPEND_COUNT). + * If the suspend count is greater than zero, the thread is suspended; otherwise, the thread is not suspended and is eligible for execution. + * Calling SuspendThread causes the target thread's suspend count to be incremented. + * Attempting to increment past the maximum suspend count causes an error without incrementing the count. + */ + if (item.SuspendCnt == 0) + item.SuspendCnt = NativeMethods.SuspendThread(pOpenThread); + + NativeMethods.CloseHandle(pOpenThread); + } + } + catch + { + //pgm unexpected ended etc, ignore; setupdesktop class will dispose it once ready. + } + } + + static void ResumeAllThreads(SetupDesktop.ExtProgram item) + { + try + { + foreach (ProcessThread thread in item.Proc.Threads) + { + var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + { + break; + // continue; + } + + /* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-resumethread + * The ResumeThread function checks the suspend count of the subject thread. If the suspend count is zero, the thread is not currently suspended. + * Otherwise, the subject thread's suspend count is decremented. If the resulting value is zero, then the execution of the subject thread is resumed. + * If the return value is zero, the specified thread was not suspended. If the return value is 1, the specified thread was suspended but was restarted. + * If the return value is greater than 1, the specified thread is still suspended. + */ + do + { + item.SuspendCnt = (uint)NativeMethods.ResumeThread(pOpenThread); + } while (item.SuspendCnt > 0); + + NativeMethods.CloseHandle(pOpenThread); + } + } + catch + { + //pgm unexpected ended etc, ignore; setupdesktop class will dispose it once ready. + } + } + + [Obsolete] + static void SuspendAllThreads(SetupDesktop.CefProcess item) + { + Process cefProcess = new Process(); + foreach (ProcessThread thread in cefProcess.Threads)//item.proc.Threads) + { + var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + { + break; + // continue; + } + //StaticPinvoke.SuspendThread(pOpenThread); + + if (item.SuspendCnt == 0) + item.SuspendCnt = NativeMethods.SuspendThread(pOpenThread); + + NativeMethods.CloseHandle(pOpenThread); + } + } + + [Obsolete] + static void ResumeAllThreads(SetupDesktop.CefProcess item) + { + foreach (ProcessThread thread in item.Proc.Threads) + { + var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); + if (pOpenThread == IntPtr.Zero) + { + break; + // continue; + } + //StaticPinvoke.ResumeThread(pOpenThread); + + //var suspendCount = 0; + do + { + item.SuspendCnt = (uint)NativeMethods.ResumeThread(pOpenThread); + } while (item.SuspendCnt > 0); + + NativeMethods.CloseHandle(pOpenThread); + } + } + + public enum Options + { + List, + Kill, + Suspend, + Resume + } + + + public class Param + { + public int PId { get; set; } + public string Expression { get; set; } + public Options Option { get; set; } + } + } +} diff --git a/src/livelywpf/livelywpf/wp_lib/SetupDesktop.cs b/src/livelywpf/livelywpf/wp_lib/SetupDesktop.cs new file mode 100644 index 00000000..614d63bb --- /dev/null +++ b/src/livelywpf/livelywpf/wp_lib/SetupDesktop.cs @@ -0,0 +1,2270 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Interop; +using System.Windows.Shapes; +using System.Windows.Threading; +using static livelywpf.SaveData; +using MessageBox = System.Windows.MessageBox; + +namespace livelywpf +{ + /// + /// Main static class that deals with adding & managing wallpaper's (wp). + /// + public static class SetupDesktop + { + //todo:- remove/reduce redundant/useless variables. + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + /// + /// List of currently running wallpapers, will NOT check for existing wp before adding new wp entry. + /// + public static List wallpapers = new List(); + private static DispatcherTimer dispatcherTimer = new DispatcherTimer(); + + private static IntPtr handle, workerWOrig, progman, desktopHandle, shellHandle; + private static int processID; + /// + /// Amount of time to wait(approx) for external application wp to launch(milliseconds) + /// + public static int wallpaperWaitTime = 30000; //~30sec + private static Task taskAppWait; + private static bool _isInitialized = false; + //private static bool _cefReady = true; + + public enum WallpaperType + { + [Description("Application")] + app, + [Description("Webpage")] + web, + [Description("Webpage Audio Visualiser")] + web_audio, + [Description("Webpage Link")] //"Type" tab only, not for "Library"! + url, + [Description("Bizhawk Emulator")] + bizhawk, + [Description("Unity Game")] + unity, + [Description("Godot Game")] + godot, + [Description("Video")] + video, + [Description("Animated Gif")] + gif, + [Description("Unity Audio Visualiser")] + unity_audio + } + + #region wp_internal_data + public class WPBaseClass + { + public IntPtr Handle { get; set; } //wp window handle. + public string DisplayID { get; set; } //Screen class displayDevice name. + + public WPBaseClass(IntPtr handle, string displayID) + { + this.Handle = handle; + this.DisplayID = displayID; + } + } + + public class WMPlayer : WPBaseClass //windows mediafoundation + { + public MediaPlayer MP { get; private set; } + + public WMPlayer(IntPtr handle, string displayID, MediaPlayer mp) : base(handle, displayID) + { + this.MP = mp; + } + } + + public class MediaKit : WPBaseClass //mediakit, external codec + { + public Mediakit MP { get; private set; } + public bool IsGif { get; private set; } //video & gif support. + + public MediaKit(IntPtr handle, string displayID, Mediakit mp, bool isGIF) : base(handle, displayID) + { + this.MP = mp; + this.IsGif = isGIF; + } + } + + public class GIFWallpaper : WPBaseClass //xamlanimatedgif + { + public GifWindow Gif { get; private set; } + + public GIFWallpaper(IntPtr handle, string displayID, GifWindow gifPlayer) : base(handle, displayID) + { + this.Gif = gifPlayer; + } + } + + public class ExtProgram : WPBaseClass //unity, godot, any apps. + { + public Process Proc { get; private set; } + public WallpaperType Type { get; private set; } + public UInt32 SuspendCnt { get; set; } + + public ExtProgram(IntPtr handle, string displayID, Process process, WallpaperType type, UInt32 suspendCnt) : base(handle, displayID) + { + this.Proc = process; + this.Type = type; + this.SuspendCnt = suspendCnt; + } + } + + public class CefProcess : WPBaseClass //external cefsharp. + { + public Process Proc { get; private set; } + public WallpaperType Type { get; private set; } + public UInt32 SuspendCnt { get; set; } //currently unused + + public CefProcess(IntPtr handle, string displayID, Process process, WallpaperType type, UInt32 suspendCnt) : base(handle, displayID) + { + this.Proc = process; + this.Type = type; + this.SuspendCnt = suspendCnt; + } + } + + public static List extPrograms = new List(); + public static List gifWallpapers = new List(); + public static List mediakitPlayers = new List(); + public static List wmPlayers = new List(); + public static List webProcesses = new List(); + public static Process bizhawkProc = null; + //private mpv mpvForm = null; + //public VideoWindow vlcForm = null; + #endregion wp_internal_data + + #region wp_core + private static IntPtr workerw; //spawned window for wp. + public static CancellationTokenSource ctsMonitor = new CancellationTokenSource(); + static CancellationTokenSource ctsProcessWait = null;// = new CancellationTokenSource(); + + //credit: https://www.codeproject.com/Articles/856020/Draw-Behind-Desktop-Icons-in-Windows-plus + /// + /// Setup wallpaper & start the process monitoring. + /// + /// + public static async void SetWallpaper(SaveData.WallpaperLayout layout) + { + if(MainWindow.highContrastFix) //todo:- last minute addition, should properly finish it later. + { + //_isInitialized = true; + } + else if ( SystemInformation.HighContrast ) + { + Logger.Error("Failed to setup, high contrast mode!"); + MessageBox.Show(Properties.Resources.msgHighContrastFailure, Properties.Resources.txtLivelyErrorMsgTitle); + return; + } + else if ( !_isInitialized) + { + // Fetch the Progman window + progman = NativeMethods.FindWindow("Progman", null); + + IntPtr result = IntPtr.Zero; + + // Send 0x052C to Progman. This message directs Progman to spawn a + // WorkerW behind the desktop icons. If it is already there, nothing + // happens. + NativeMethods.SendMessageTimeout(progman, + 0x052C, + new IntPtr(0), + IntPtr.Zero, + NativeMethods.SendMessageTimeoutFlags.SMTO_NORMAL, + 1000, + out result); + // Spy++ output + // ..... + // 0x00010190 "" WorkerW + // ... + // 0x000100EE "" SHELLDLL_DefView + // 0x000100F0 "FolderView" SysListView32 + // 0x00100B8A "" WorkerW <-- This is the WorkerW instance we are after! + // 0x000100EC "Program Manager" Progman + + workerw = IntPtr.Zero; + + // We enumerate all Windows, until we find one, that has the SHELLDLL_DefView + // as a child. + // If we found that window, we take its next sibling and assign it to workerw. + NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc((tophandle, topparamhandle) => + { + IntPtr p = NativeMethods.FindWindowEx(tophandle, + IntPtr.Zero, + "SHELLDLL_DefView", + IntPtr.Zero); + + if (p != IntPtr.Zero) + { + // Gets the WorkerW Window after the current one. + workerw = NativeMethods.FindWindowEx(IntPtr.Zero, + tophandle, + "WorkerW", + IntPtr.Zero); + } + + return true; + }), IntPtr.Zero); + + if ( IntPtr.Equals(workerw, IntPtr.Zero) || workerw == null ) + { + Logger.Error("Failed to setup, workerw handle null!"); + //todo: set the settings through code using SystemParametersInfo() - complication: microsoft uses registry to update the radio button UI in the Performance dialog, + //which DOES not reflect actual applied settings! o_O..will have to edit registry too. + MessageBox.Show(Properties.Resources.msgWorkerWFailure, Properties.Resources.txtLivelyErrorMsgTitle); + return; + } + else + { + _isInitialized = true; + } + } + + if(!_timerInitilaized) + { + InitializeTimer(); + } + dispatcherTimer.Stop(); + + if (layout.Type == WallpaperType.video) + { + #region mpv_ext_process_way + //external mpv video player. + //proc = Process.Start(System.AppDomain.CurrentDomain.BaseDirectory + @"\external\mpv\mpv.exe", "\"" + @path + "\"" + " --fullscreen --loop-file --keep-open"); + #endregion + + if (SaveData.config.VidPlayer == SaveData.VideoPlayer.mediakit) + { + Mediakit mediakitPlayer = new Mediakit(layout.FilePath); + mediakitPlayer.Show(); + handle = new WindowInteropHelper(mediakitPlayer).Handle; + + //mediakitPlayers.Add(new MediaKit { mp = mediakitPlayer, handle = this.handle, displayID = layout.displayName, isGIF = false }); + mediakitPlayers.Add(new MediaKit(handle, layout.DeviceName, mediakitPlayer, false)); + } + else if (SaveData.config.VidPlayer == SaveData.VideoPlayer.windowsmp) + { + MediaPlayer wmPlayer = new MediaPlayer(layout.FilePath); + wmPlayer.Show(); + handle = new WindowInteropHelper(wmPlayer).Handle; + + wmPlayers.Add(new WMPlayer(handle, layout.DeviceName, wmPlayer)); + } + + AddWallpaper(handle, layout.DeviceName); + } + else if (layout.Type == WallpaperType.gif) + { + if (SaveData.config.GifPlayer == SaveData.GIFPlayer.xaml) + { + GifWindow gifForm = new GifWindow(layout.FilePath); + gifForm.Show(); + handle = new WindowInteropHelper(gifForm).Handle; + + //gifWallpapers.Add(new GIFWallpaper { gif = gifForm, handle = this.handle, displayID = layout.displayName }); + gifWallpapers.Add(new GIFWallpaper(handle, layout.DeviceName, gifForm)); + } + else if (SaveData.config.GifPlayer == SaveData.GIFPlayer.mediakit) + { + Mediakit mediakitPlayer = new Mediakit(layout.FilePath); + mediakitPlayer.Show(); + handle = new WindowInteropHelper(mediakitPlayer).Handle; + + //mediakitPlayers.Add(new MediaKit { mp = mediakitPlayer, handle = this.handle, displayID = layout.displayName, isGIF = true }); + mediakitPlayers.Add(new MediaKit(handle, layout.DeviceName, mediakitPlayer, true)); + } + + AddWallpaper(handle, layout.DeviceName); + } + else if (layout.Type == WallpaperType.unity || layout.Type == WallpaperType.unity_audio) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = layout.FilePath, + UseShellExecute = false, + WorkingDirectory = System.IO.Path.GetDirectoryName(layout.FilePath), + //startInfo.Arguments = "-parentHWND " + workerw.ToString();// + " -popupwindow" + " -; //easier & hides the window on launch, for consistency avoiding this. todo: Problem #1:cant get process window handle directly. + Arguments = "-popupwindow -screen-fullscreen 0" //-popupwindow removes from taskbar, -fullscreen flag to disable fullscreen mode if set during compilation (lively is handling resizing). + }; + + Process proc = new Process(); + proc = Process.Start(startInfo); + try + { + ctsProcessWait = new CancellationTokenSource(); + taskAppWait = Task.Run(() => WaitForProcesWindow(layout.Type, proc), ctsProcessWait.Token); + await taskAppWait; + + } + catch (OperationCanceledException) + { + Logger.Info("app terminated early, user cancel/no-gui"); + Debug.WriteLine("app terminated early, user cancel"); + try + { + proc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + + dispatcherTimer.Start(); + return; + } + + handle = proc.MainWindowHandle; + if (handle == IntPtr.Zero) + { + Logger.Info("Error: could not get windowhandle after waiting.."); + try + { + proc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + //This usually happens if the app took too long then the timeout specified. (virus scan, too big a application, busy hdd? ). + MessageBox.Show(Properties.Resources.msgAppTimeout, Properties.Resources.txtLivelyErrorMsgTitle); + + dispatcherTimer.Start(); + return; + } + + extPrograms.Add(new ExtProgram(handle, layout.DeviceName, proc, layout.Type, 0)); + //removing from taskbar. + //StaticPinvoke.SetWindowLongPtr(new HandleRef(null,handle), (-20),(IntPtr)StaticPinvoke.WS_EX_TOOLWINDOW); + RemoveAppFromTaskbar(handle); + + AddWallpaper(handle, layout.DeviceName); + + //saving to list of pgms to kill in the event lively crashes. + SaveData.runningPrograms.Add(new SaveData.RunningProgram { ProcessName = proc.ProcessName, Pid = proc.Id }); + SaveData.SaveRunningPrograms(); + } + else if (layout.Type == WallpaperType.app) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = layout.FilePath, + UseShellExecute = false, + WorkingDirectory = System.IO.Path.GetDirectoryName(layout.FilePath), + Arguments = layout.Arguments + }; + + Process proc = new Process(); //this compiler disposable object warning should be a mistake, the referenced object is disposed when wp is closed. + proc = Process.Start(startInfo); + try + { + ctsProcessWait = new CancellationTokenSource(); + taskAppWait = Task.Run(() => WaitForProcesWindow(layout.Type, proc), ctsProcessWait.Token); + await taskAppWait; + } + catch (OperationCanceledException) + { + Logger.Info("app terminated early, user cancel"); + Debug.WriteLine("app terminated early, user cancel"); + try + { + proc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + + dispatcherTimer.Start(); + return; + } + + handle = proc.MainWindowHandle; + if (handle == IntPtr.Zero) + { + Logger.Info("Error: could not get windowhandle after waiting.."); + try + { + proc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + //This usually happens if the app took too long then the timeout specified. (virus scan, too big a application, busy hdd? ). + MessageBox.Show(Properties.Resources.msgAppTimeout, Properties.Resources.txtLivelyErrorMsgTitle); + + dispatcherTimer.Start(); + return; + } + + extPrograms.Add(new ExtProgram(handle, layout.DeviceName, proc, layout.Type, 0)); + + BorderlessWinStyle(handle); + RemoveAppFromTaskbar(handle); + + AddWallpaper(handle, layout.DeviceName); + + SaveData.runningPrograms.Add(new SaveData.RunningProgram { ProcessName = proc.ProcessName, Pid = proc.Id }); + SaveData.SaveRunningPrograms(); + + } + else if (layout.Type == WallpaperType.web || layout.Type == WallpaperType.url || layout.Type == WallpaperType.web_audio) + { + //multiple instace. todo:- make it spawn a new browser window instead. + ProcessStartInfo start1 = new ProcessStartInfo(); + if (layout.Type == WallpaperType.web) + { + //start1.Arguments = "\"" + layout.filePath + "\"" + @" local" + @" audio"; + start1.Arguments = "\"" + layout.FilePath + "\"" + @" local"; + } + else if (layout.Type == WallpaperType.web_audio) + { + start1.Arguments = "\"" + layout.FilePath + "\"" + @" local" + @" audio"; + } + else + { + //start1.Arguments = "\"" + layout.filePath + "\"" + " " + "\"" + "online" + "\""; + start1.Arguments = layout.FilePath + @" online"; + } + start1.FileName = AppDomain.CurrentDomain.BaseDirectory + @"\external\cef\LivelyCefSharp.exe"; + start1.RedirectStandardInput = true; + start1.RedirectStandardOutput = true; + start1.UseShellExecute = false; + + Process webProcess = new Process(); + webProcess = Process.Start(start1); + webProcess.EnableRaisingEvents = true; + webProcess.OutputDataReceived += WebProcess_OutputDataReceived; + //webProcess.Exited += WebProcess_Exited; //todo: see closeallwallpapers() + webProcess.BeginOutputReadLine(); + + //webProcesses.Add(new CefProcess { proc = webProcess, displayID = layout.displayName, type = layout.type, handle = IntPtr.Zero, suspendCnt = 0 }); + webProcesses.Add(new CefProcess(handle, layout.DeviceName, webProcess, layout.Type, 0)); + + SaveData.runningPrograms.Add(new SaveData.RunningProgram { ProcessName = webProcess.ProcessName, Pid = webProcess.Id }); + SaveData.SaveRunningPrograms(); + } + else if (layout.Type == WallpaperType.godot) + { + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = layout.FilePath, + UseShellExecute = false, + WorkingDirectory = System.IO.Path.GetDirectoryName(layout.FilePath), + //Arguments = "--fullscreen" + }; + Process proc = new Process(); + proc = Process.Start(startInfo); + + //await WaitForProcesWindow(); + try + { + ctsProcessWait = new CancellationTokenSource(); + taskAppWait = Task.Run(() => WaitForProcesWindow(layout.Type, proc), ctsProcessWait.Token); + await taskAppWait; + } + catch (OperationCanceledException) + { + Logger.Info("app terminated early, user cancel/no-gui"); + Debug.WriteLine("app terminated early, user cancel"); + try + { + proc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + + dispatcherTimer.Start(); + return; + } + //handle = proc.MainWindowHandle; + if (handle == IntPtr.Zero) + { + Logger.Info("Error: could not get windowhandle after waiting.."); + try + { + proc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + //This usually happens if the app took too long then the timeout specified. (virus scan, too big a application, busy hdd? ). + MessageBox.Show(Properties.Resources.msgAppTimeout, Properties.Resources.txtLivelyErrorMsgTitle); + + dispatcherTimer.Start(); + return; + } + + extPrograms.Add(new ExtProgram(handle, layout.DeviceName, proc, layout.Type, 0)); + BorderlessWinStyle(handle); + RemoveAppFromTaskbar(handle); + + AddWallpaper(handle, layout.DeviceName); + + SaveData.runningPrograms.Add(new SaveData.RunningProgram { ProcessName = proc.ProcessName, Pid = proc.Id }); + SaveData.SaveRunningPrograms(); + } + else if (layout.Type == WallpaperType.bizhawk) + { + //loaded with custom configfile: global inputhooks, fullscreen, run in background. + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = layout.FilePath, + UseShellExecute = false, + WorkingDirectory = System.IO.Path.GetDirectoryName(layout.FilePath), + Arguments = "--config=" + AppDomain.CurrentDomain.BaseDirectory + @"\BizhawkConfig.ini" + }; + + //Process proc = new Process(); + if (bizhawkProc == null) + { + bizhawkProc = new Process(); + bizhawkProc = Process.Start(startInfo); + } + + try + { + ctsProcessWait = new CancellationTokenSource(); + taskAppWait = Task.Run(() => WaitForProcesWindow(layout.Type, bizhawkProc), ctsProcessWait.Token); + await taskAppWait; + } + catch (OperationCanceledException) + { + Debug.WriteLine("bizhawk terminated early, user cancel"); + + dispatcherTimer.Start(); + return; + } + + handle = bizhawkProc.MainWindowHandle; + if (IntPtr.Equals(handle, IntPtr.Zero)) + { + Logger.Info("Error: could not get windowhandle after waiting.."); + try + { + bizhawkProc.Kill(); + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + MessageBox.Show(Properties.Resources.msgAppTimeout, Properties.Resources.txtLivelyErrorMsgTitle); + + dispatcherTimer.Start(); + return; + } + + //BorderlessWinStyle(handle); + RemoveAppFromTaskbar(handle); + + AddWallpaper(handle, layout.DeviceName); + //StaticPinvoke.ShowWindow(handle, 3); //maximise + + SaveData.runningPrograms.Add(new SaveData.RunningProgram { ProcessName = bizhawkProc.ProcessName, Pid = bizhawkProc.Id }); + SaveData.SaveRunningPrograms(); + } + else + { + Logger.Error("Unkown wallpapertype:" + layout.Type); + + dispatcherTimer.Start(); + return; + } + + wallpapers.Add(layout); + SaveData.SaveWallpaperLayout(); + + dispatcherTimer.Start(); + } + #endregion wp_core + + #region wp_add + /// + /// Calculates the position of window w.r.t parent workerw handle & sets it as child window to it. + /// + /// window handle of process to add as wallpaper + /// displaystring of display to sent wp to. + private static void AddWallpaper(IntPtr handle, string display = null) + { + + if(SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + SpanWallpaper(handle); + return; + } + + //bottom-most window instead of behind-icon + if (MainWindow.highContrastFix) + { + foreach (var displayItem in Screen.AllScreens) + { + if( display == displayItem.DeviceName) + { + SetWindowBottomMost(handle); + if (!NativeMethods.SetWindowPos(handle, 1, displayItem.Bounds.X, displayItem.Bounds.Y, (displayItem.WorkingArea.Width), (displayItem.WorkingArea.Height), 0 | 0x0010)) + { + LogWin32Error("setwindowpos(1) fail addwallpaper(),"); + } + } + } + } + else + { + foreach (var displayItem in Screen.AllScreens) + { + if (display == displayItem.DeviceName) + { + NativeMethods.RECT prct = new NativeMethods.RECT(); + NativeMethods.POINT topLeft; + //StaticPinvoke.POINT bottomRight; + + Logger.Info("Sending WP -> " + displayItem); + if (!NativeMethods.SetWindowPos(handle, 1, displayItem.Bounds.X, displayItem.Bounds.Y, (displayItem.Bounds.Width), (displayItem.Bounds.Height), 0 | 0x0010)) + { + LogWin32Error("setwindowpos(2) fail AddWallpaper(),"); + } + + //ScreentoClient is no longer used, this supports windows mirrored mode also, calculate new relative position of window w.r.t parent. + NativeMethods.MapWindowPoints(handle, workerw, ref prct, 2); + //LogWin32Error("MapWindowPts addwallpaper(),"); + + SetParentWorkerW(handle); + //Position the wp window relative to the new parent window(workerw). + if (!NativeMethods.SetWindowPos(handle, 1, prct.Left, prct.Top, (displayItem.Bounds.Width), (displayItem.Bounds.Height), 0 | 0x0010)) + { + LogWin32Error("setwindowpos(3) fail addwallpaper(),"); + } + + #region logging + NativeMethods.GetWindowRect(handle, out prct); + //Debug.WriteLine("current Window Coordinates: " + prct.Left + " " + prct.Right + " " + displayItem.Bounds.Width + " " + displayItem.Bounds.Height); + Logger.Info("Relative Coordinates of WP -> " + prct.Left + " " + prct.Right + " " + displayItem.Bounds.Width + " " + displayItem.Bounds.Height); + topLeft.X = prct.Left; + topLeft.Y = prct.Top; + NativeMethods.ScreenToClient(workerw, ref topLeft); + //Debug.WriteLine("current Window Coordinates(corrected): " + topLeft.X + " " + topLeft.Y + " " + displayItem.Bounds.Width + " " + displayItem.Bounds.Height); + Logger.Info("Coordinate wrt to screen ->" + topLeft.X + " " + topLeft.Y + " " + displayItem.Bounds.Width + " " + displayItem.Bounds.Height); + #endregion logging. + break; + } + } + } + SetFocus(true); + RefreshDesktop(); + } + + /// + /// Spans wp across all screens. + /// + private static void SpanWallpaper(IntPtr handle) + { + NativeMethods.RECT prct = new NativeMethods.RECT(); + NativeMethods.GetWindowRect(workerw, out prct); //get spawned workerw rectangle data. + SetParentWorkerW(handle); + + if(!NativeMethods.SetWindowPos(handle, 1, 0, 0, prct.Right - prct.Left, prct.Bottom - prct.Top, 0 | 0x0010)) //fill wp into the whole workerw area. + { + LogWin32Error("setwindowpos fail SpanWallpaper(),"); + } + + SetFocus(true); + RefreshDesktop(); + } + #endregion wp_add + + #region wp_refresh + /// + /// Refresh wp span dimension. + /// + /// + private static void SpanUpdate(IntPtr handle) + { + Logger.Info("Span wp rect Updating!"); + NativeMethods.RECT prct = new NativeMethods.RECT(); + NativeMethods.GetWindowRect(workerw, out prct); //get spawned workerw rectangle data. + NativeMethods.SetWindowPos(handle, 1, 0, 0, prct.Right - prct.Left, prct.Bottom - prct.Top, 0 | 0x0010); //fill wp into the whole workerw area. + } + + /// + /// Update/Refresh all currently running wp's size & position. + /// + public static void UpdateAllWallpaperRect() + { + if(MainWindow.multiscreen || MainWindow.highContrastFix) //bug:wp disappearing, probably overlapping one another. todo:- fix, I think its due to the new setwindowpos introduced for displayID window. + { + Logger.Debug("wp rect adjustment disabled for multiscreen/highcontrast due to bug/incomplete, skipping!"); + return; + } + + NativeMethods.RECT prct = new NativeMethods.RECT(); + int i = 0; + //todo:- very lazy code.. + foreach (var item in Screen.AllScreens) + { + if( (i = extPrograms.FindIndex(x => x.DisplayID == item.DeviceName)) != -1) + { + if (SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + SpanUpdate(extPrograms[i].Handle); + break; + } + + DisplayID displayID = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + Opacity = 0 + }; + displayID.Show(); + NativeMethods.MapWindowPoints(new WindowInteropHelper(displayID).Handle, workerw, ref prct, 2); + displayID.Close(); + NativeMethods.SetWindowPos(extPrograms[i].Handle, 1, prct.Left, prct.Top, (item.Bounds.Width), (item.Bounds.Height), 0 | 0x0010); + continue; + } + + if ((i = gifWallpapers.FindIndex(x => x.DisplayID == item.DeviceName)) != -1) + { + if (SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + SpanUpdate(gifWallpapers[i].Handle); + break; + } + + DisplayID displayID = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + Opacity = 0 + }; + displayID.Show(); + NativeMethods.MapWindowPoints(new WindowInteropHelper(displayID).Handle, workerw, ref prct, 2); + displayID.Close(); + + NativeMethods.SetWindowPos(gifWallpapers[i].Handle, 1, prct.Left, prct.Top, (item.Bounds.Width), (item.Bounds.Height), 0 | 0x0010); + continue; + } + + if ((i = mediakitPlayers.FindIndex(x => x.DisplayID == item.DeviceName)) != -1) + { + if (SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + SpanUpdate(mediakitPlayers[i].Handle); + break; + } + + DisplayID displayID = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + Opacity = 0 + }; + displayID.Show(); + NativeMethods.MapWindowPoints(new WindowInteropHelper(displayID).Handle, workerw, ref prct, 2); + displayID.Close(); + + NativeMethods.SetWindowPos(mediakitPlayers[i].Handle, 1, prct.Left, prct.Top, (item.Bounds.Width), (item.Bounds.Height), 0 | 0x0010); + continue; + } + + if ((i = wmPlayers.FindIndex(x => x.DisplayID == item.DeviceName)) != -1) + { + if (SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + SpanUpdate(wmPlayers[i].Handle); + break; + } + + DisplayID displayID = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + Opacity = 0 + }; + displayID.Show(); + NativeMethods.MapWindowPoints(new WindowInteropHelper(displayID).Handle, workerw, ref prct, 2); + displayID.Close(); + //StaticPinvoke.MapWindowPoints(wmPlayers[i].handle, workerw, ref prct, 2); + NativeMethods.SetWindowPos(wmPlayers[i].Handle, 1, prct.Left, prct.Top, (item.Bounds.Width), (item.Bounds.Height), 0 | 0x0010); + continue; + } + + if ((i = webProcesses.FindIndex(x => x.DisplayID == item.DeviceName)) != -1) + { + if (SaveData.config.WallpaperArrangement == WallpaperArrangement.span) + { + SpanUpdate(webProcesses[i].Handle); + break; + } + + DisplayID displayID = new DisplayID(item.DeviceName, item.Bounds.X, item.Bounds.Y) + { + Opacity = 0 + }; + displayID.Show(); + NativeMethods.MapWindowPoints(new WindowInteropHelper(displayID).Handle, workerw, ref prct, 2); + displayID.Close(); + + NativeMethods.SetWindowPos(webProcesses[i].Handle, 1, prct.Left, prct.Top, (item.Bounds.Width), (item.Bounds.Height), 0 | 0x0010); + continue; + } + } + RefreshDesktop(); + } + #endregion wp_refreh + + #region cefsharp_events + //public static IntPtr cefIntermediate; + //public static IntPtr cefRenderWidget; + /// + /// STDOUT redirect message event of cefsharp browser process. + /// + private static void WebProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + try + { + //Retrieves the windowhandle of cefsubprocess, cefsharp is launching cef as a separate proces..if you add the full pgm as child of workerw then there are problems (prob related sharing input queue) + //Instead hiding the pgm window & adding cefrender window instead. + Logger.Info("Cefsharp Handle:- " + e.Data); + if (e.Data.Contains("HWND")) + { + var currProcess = webProcesses.Find(x => x.Proc == sender); + + handle = new IntPtr(Convert.ToInt32(e.Data.Substring(4), 10)); + //note-handle: WindowsForms10.Window.8.app.0.141b42a_r9_ad1 + + //hidin other windows, no longer required since I'm doing it in cefsharp pgm itself. + NativeMethods.ShowWindow(currProcess.Proc.MainWindowHandle, 0); + + //WARNING:- If you put the whole cefsharp window, workerw crashes and refuses to start again on next startup!!, this is a workaround. + handle = NativeMethods.FindWindowEx(handle, IntPtr.Zero, "Chrome_WidgetWin_0", null); + //cefRenderWidget = StaticPinvoke.FindWindowEx(handle, IntPtr.Zero, "Chrome_RenderWidgetHostHWND", null); + //cefIntermediate = StaticPinvoke.FindWindowEx(handle, IntPtr.Zero, "Intermediate D3D Window", null); + + if (IntPtr.Equals(handle, IntPtr.Zero))//unlikely. + { + try + { + currProcess.Proc.Kill(); + } + catch (Exception ex) + { + Logger.Error("Error getting webview handle:- " + ex.ToString()); + Debug.WriteLine("web handle 0:- " + ex.Message + " " + ex.StackTrace); + } + + return; + } + + //webViewHandle = handle; + currProcess.Handle = handle; + + AddWallpaper(handle, currProcess.DisplayID); + } + } + catch (Exception) + { + //todo + } + + } + + /// + /// cefsharp browser exit event. + /// + /// + /// + private static void WebProcess_Exited(object sender, EventArgs e) + { + dispatcherTimer.Stop(); + + int i; + if ((i = webProcesses.FindIndex(x => x.Proc.HasExited == true)) != -1) + { + try + { + webProcesses[i].Proc.Close(); + } + catch(NullReferenceException ex) + { + Logger.Info("browser proc already closed:-" + ex.ToString()); + } + webProcesses.RemoveAt(i); + } + + dispatcherTimer.Start(); + RefreshDesktop(); + } + #endregion cefsharp_events + + #region wp_wait + /// + /// Check if started pgm wp is ready(GUI window started). + /// + /// true: process ready/halted, false: process still starting. + public static int IsProcessWaitDone() + { + var task = taskAppWait; + if (task != null) + { + if ((task.IsCompleted == false + || task.Status == TaskStatus.Running + || task.Status == TaskStatus.WaitingToRun + || task.Status == TaskStatus.WaitingForActivation + )) + { + return 0; + } + return 1; + } + return 1; + } + + /// + /// Cancel waiting for pgm wp window to be ready. + /// + public static void TaskProcessWaitCancel() + { + ctsProcessWait.Cancel(); + while (!taskAppWait.IsCanceled && !taskAppWait.IsCompleted) + { + + } + ctsProcessWait.Dispose(); + ctsProcessWait = null; + } + + private const int BM_CLICK = 0x00F5; //left-click + /// + /// Logic to search for window-handle of spawned pgm wp process. + /// + /// + /// + /// + private static async Task WaitForProcesWindow(WallpaperType type, Process proc) + { + if (proc == null) + { + return false; + } + + IntPtr configW = IntPtr.Zero; + int i = 0; + try + { + while (proc.WaitForInputIdle(-1) != true) //waiting for msgloop to be ready, gui not guaranteed to be ready. + { + ctsProcessWait.Token.ThrowIfCancellationRequested(); + } + } + catch(InvalidOperationException) //no gui, failed to enter idle state. + { + _ = Task.Run(() => (MessageBox.Show(Properties.Resources.msgAppGUIFailure, Properties.Resources.txtLivelyErrorMsgTitle))); + throw new OperationCanceledException(); + } + + if (type == WallpaperType.godot) + { + while (i < wallpaperWaitTime && proc.HasExited == false) //15sec + { + ctsProcessWait.Token.ThrowIfCancellationRequested(); + + //Debug.WriteLine(type + " waiting for handle(godot): " + i / 2f + "(s)" + " mainhandle: " + proc.MainWindowHandle + " is maximised" + NativeMethods.IsZoomed(proc.MainWindowHandle)); + i++; + configW = NativeMethods.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Engine", null); + if (!IntPtr.Equals(configW, IntPtr.Zero)) + break; + //Task.Delay(500).Wait(); // 500x20 ~10sec + await Task.Delay(1); + } + handle = configW; + return true; + } + else if (type == WallpaperType.unity || type == WallpaperType.unity_audio) + { + /* + IntPtr tmpProc = IntPtr.Zero; + i = 0; + while(i < 15 && proc.HasExited == false) + { + tmpProc = StaticPinvoke.FindWindowEx(workerw, IntPtr.Zero, "UnityWndClass", proc.ProcessName); + Debug.WriteLine("process name:- " + proc.ProcessName); + if (!IntPtr.Equals(tmpProc, IntPtr.Zero)) + { + + int id; + StaticPinvoke.GetWindowThreadProcessId(tmpProc, out id); + if (proc == Process.GetProcessById(id)) + { + proc.Refresh(); + return; + } + else + { + tmpProc = StaticPinvoke.FindWindowEx(workerw, tmpProc, "UnityWndClass", proc.ProcessName); + } + return; + } + await Task.Delay(500); + } + */ + + //Player settings dialog of Unity, simulating play button click or search workerw if paramter given in argument. + i = 0; + while (i < wallpaperWaitTime && proc.HasExited == false) //~30sec + { + ctsProcessWait.Token.ThrowIfCancellationRequested(); + Debug.WriteLine(type + " waiting for config-handle(unity): " + i + "(s)" + " mainhandle: " + proc.MainWindowHandle + " is maximised" + NativeMethods.IsZoomed(proc.MainWindowHandle)); + i++; + + if (!IntPtr.Equals(proc.MainWindowHandle, IntPtr.Zero)) + break; + //Task.Delay(500).Wait(); // 10sec + await Task.Delay(1); + } + configW = NativeMethods.FindWindowEx(proc.MainWindowHandle, IntPtr.Zero, "Button", "Play!"); + if (!IntPtr.Equals(configW, IntPtr.Zero)) + NativeMethods.SendMessage(configW, BM_CLICK, IntPtr.Zero, IntPtr.Zero); //simulate Play! button click. (Unity config window) + + await Task.Delay(1); + } + proc.Refresh(); //update window-handle of unity config + + //there does not seem to be a "proper" way to check whether mainwindow is ready. + i = 0; + while (i < wallpaperWaitTime && proc.HasExited == false) + { + ctsProcessWait.Token.ThrowIfCancellationRequested(); + /* + if (ctsProcessWait.IsCancellationRequested) + { + return false; + } + */ + + Debug.WriteLine(type + " waiting for handle(app): " + i / 2f + "(s)" + " mainhandle: " + proc.MainWindowHandle + " is maximised" + NativeMethods.IsZoomed(proc.MainWindowHandle) + " cancelation: " + ctsProcessWait.IsCancellationRequested); + i++; + if (!IntPtr.Equals(proc.MainWindowHandle, IntPtr.Zero)) + { + //moving the window out of screen. + //StaticPinvoke.SetWindowPos(proc.MainWindowHandle, 1, -20000, 0, 0, 0, 0x0010 | 0x0001); + break; + } + //Task.Delay(500).Wait(); // 500x20 ~10sec + await Task.Delay(1); + } + + Debug.WriteLine(type + " waiting for handle:(app outside) " + i / 2f + "(s)" + " mainhandle: " + proc.MainWindowHandle + " is maximised" + NativeMethods.IsZoomed(proc.MainWindowHandle)); + proc.Refresh(); + if (proc.MainWindowHandle == IntPtr.Zero) + { + Logger.Info("Error: could not get windowhandle after waiting.."); + //MessageBox.Show("Error: could not get windowhandle after waiting.."); + return false; + } + else + return true; + } + #endregion wp_wait + + #region thread_monitor_pause/play + //todo:- remove/reduce redundant/useless variables. + static IntPtr hWnd, shell_tray; + static Process currProcess; + //static string currProcessName; + static System.Drawing.Rectangle screenBounds; + static NativeMethods.RECT appBounds; + static string currDisplay; + + /// + /// Timer event, checks for running pgm & determine wp playback behavior. + /// + /// + /// + private static void ProcessMonitor(object sender, EventArgs e) + { + if (!_isInitialized) + { + dispatcherTimer.Stop(); + return; + } + + if(SaveData.config.ProcessMonitorAlgorithm == SaveData.ProcessMonitorAlgorithm.foreground) + { + //light, reliable & quick; have some limitations when smaller foreground window opened on top of already maximised window, this will fail detection. + ForegroundPauseFn(); + } + else if (SaveData.config.ProcessMonitorAlgorithm == SaveData.ProcessMonitorAlgorithm.all) //TODO:- rewrite with EnumWindowsProc instead of going through all running Processes, might eliminate the issue's I'm having.(ps: i was wrong, nvrmind xD) + { + //todo:- this algorithm is incomplete for multiple-screen, have to finish it. (I dont like what I'm doing here). + if(MainWindow.multiscreen) + { + /* + //IntPtr shellWindow = NativeMethods.GetShellWindow(); + visibleWindows.Clear(); + NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc(UpdateVisibleWindowsAllScreens), IntPtr.Zero); + foreach (var item in visibleWindows) + { + if (screens.Exists(x => x.DeviceName == MapWindowToMonitor(item))) + { + try + { + NativeMethods.GetWindowThreadProcessId(item, out processID); + currProcess = Process.GetProcessById(processID); + currProcessName = currProcess.ProcessName; + } + catch + { + //ignore, admin process etc + continue; + } + + AllAppPauseFn(currProcess, screens.Find(x => x.DeviceName == MapWindowToMonitor(item)).DeviceName); + screens.Remove(screens.Find(x => x.DeviceName == MapWindowToMonitor(item))); + } + } + */ + + List screens = Screen.AllScreens.ToList(); + //lots of hack, many unwanted windows keep detecting even with all these checks (my Check_EX_Style() method might be wrong). + //problem is isZoomed fixes all the problems, except some games are not detected as maximised(eg: dota 2 windowed mode), so I have to check the windowsize using isZoomedCustom I made which also picks up unwanted windows. + //I decided to fix that issue by checking the window style which created limited success? + foreach (var item in Process.GetProcesses()) + { + if (NativeMethods.IsWindowVisible(item.MainWindowHandle)) + { + if ( !IntPtr.Equals(shellHandle,item.MainWindowHandle) && !NativeMethods.IsIconic(item.MainWindowHandle) && NativeMethods.GetWindowTextLength(item.MainWindowHandle) != 0 && + !String.IsNullOrEmpty(item.ProcessName) && !IntPtr.Equals(item.MainWindowHandle, IntPtr.Zero) && !Check_EX_Style(item.MainWindowHandle, 0x08000000L) && !Check_EX_Style(item.MainWindowHandle, 0x00200000L) + && NativeMethods.IsZoomed(item.MainWindowHandle) || IsZoomedCustom(item.MainWindowHandle, null))//IsZoomedCustomAllDisplays(item.MainWindowHandle)) + { + //things that popup when checking windowsize close to screensize, rip x_x + if (item.ProcessName.Equals("ApplicationFrameHost", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("explorer", StringComparison.OrdinalIgnoreCase) + || item.ProcessName.Equals("SystemSettings", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("MicrosoftEdgeCP", StringComparison.OrdinalIgnoreCase) + || item.ProcessName.Equals("video.ui", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("NVIDIA Share", StringComparison.OrdinalIgnoreCase) + || item.ProcessName.Equals("MicrosoftEdge", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("WindowsInternal.ComposableShell.Experiences.TextInput.InputApp", StringComparison.OrdinalIgnoreCase) + ) + { + continue; + } + + try + { + if (screens.Exists(x => x.DeviceName == MapWindowToMonitor(item.MainWindowHandle))) + { + AllAppPauseFn(item, screens.Find(x => x.DeviceName == MapWindowToMonitor(item.MainWindowHandle)).DeviceName); + screens.Remove(screens.Find(x => x.DeviceName == MapWindowToMonitor(item.MainWindowHandle))); + } + } + catch (ArgumentNullException) + { + continue; + } + } + } + } + /* + hWnd = workerWOrig; + try + { + NativeMethods.GetWindowThreadProcessId(hWnd, out processID); + currProcess = Process.GetProcessById(processID); + } + catch (Exception) + { + Debug.WriteLine("getting processname failure"); + //ignore, admin process etc + return; + } + */ + foreach (var item in screens) + { + Pause.ResumeWallpaper(false, item.DeviceName); + //AllAppPauseFn(currProcess, item.DeviceName); + } + + } + else //single screen, all-process pause. + { + //interate through all the running processes, skipping unwanted ones based on condition ( all trial and error, needs a lot of further testing). + foreach (var item in Process.GetProcesses()) + { + if (NativeMethods.IsWindowVisible(item.MainWindowHandle)) + { + if (!String.IsNullOrEmpty(item.ProcessName) && !IntPtr.Equals(item.MainWindowHandle, IntPtr.Zero) && !Check_EX_Style(item.MainWindowHandle, 0x08000000L) && !Check_EX_Style(item.MainWindowHandle, 0x00200000L) + && IsZoomedCustom(item.MainWindowHandle, Screen.PrimaryScreen.DeviceName) || NativeMethods.IsZoomed(item.MainWindowHandle)) + { + //dirty fix, different explorer process being detected on desktop click wtf?! + if (item.ProcessName.Equals("ApplicationFrameHost", StringComparison.OrdinalIgnoreCase) //|| item.ProcessName.Equals("explorer", StringComparison.OrdinalIgnoreCase) + || item.ProcessName.Equals("SystemSettings", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("MicrosoftEdgeCP", StringComparison.OrdinalIgnoreCase) + || item.ProcessName.Equals("video.ui", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("NVIDIA Share", StringComparison.OrdinalIgnoreCase) + || item.ProcessName.Equals("MicrosoftEdge", StringComparison.OrdinalIgnoreCase) || item.ProcessName.Equals("WindowsInternal.ComposableShell.Experiences.TextInput.InputApp", StringComparison.OrdinalIgnoreCase) + ) + continue; + + AllAppPauseFn(item); + //once a maximised/fullscreen window is found, exit(since only one screen, the only thing left to do is pause the wallpaper.) + return; + } + } + } + /* + visibleWindows.Clear(); + NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc(UpdateVisibleWindows), IntPtr.Zero); + foreach (var item in visibleWindows) + { + try + { + NativeMethods.GetWindowThreadProcessId(item, out processID); + currProcess = Process.GetProcessById(processID); + currProcessName = currProcess.ProcessName; + } + catch + { + //ignore, admin process etc + continue; + } + AllAppPauseFn(currProcess); + //once a maximised/fullscreen window is found, exit(since only one screen, the only thing left to do is pause the wallpaper.) + return; + } + */ + + //if no fullscreen/maximised window is found, then check the foreground window for wallpaper unpausing, muting audio etc. + ForegroundPauseFn(); + } + } + } + + #region pause_all + private static void AllAppPauseFn(Process proc, string display = null) + { + #region Exceptions & Fixes + ProcessMonitorFixes(); + try + { + hWnd = proc.MainWindowHandle; + + if (proc.ProcessName.Equals("emuhawk", StringComparison.OrdinalIgnoreCase) || proc.ProcessName.Equals("livelywpf", StringComparison.OrdinalIgnoreCase) || + proc.ProcessName.Equals("devenv", StringComparison.OrdinalIgnoreCase) || proc.ProcessName.Equals("shellexperiencehost", StringComparison.OrdinalIgnoreCase) || //visual studio, notification tray etc + (proc.ProcessName.Equals("searchui", StringComparison.OrdinalIgnoreCase)) ) //startmenu search.. + + { + hWnd = workerWOrig; + } + + //application rule. + for (int i = 0; i < SaveData.appRules.Count; i++) + { + if (currProcess.ProcessName.Equals(SaveData.appRules[i].AppName, StringComparison.OrdinalIgnoreCase)) + { + if (SaveData.appRules[i].Rule == SaveData.AppRulesEnum.ignore) //always run when this process is foreground window, even when maximized + { + hWnd = workerWOrig; //assume desktop, to force unpause/wakeup of rePaper. + //Pause.SuspendWallpaper(false); //resume with audio disabled etc + //return; + } + else if (SaveData.appRules[i].Rule == SaveData.AppRulesEnum.pause) //sleep + { + Pause.SuspendWallpaper(true); + return; + } + else if (SaveData.appRules[i].Rule == SaveData.AppRulesEnum.kill) + { + throw new NotImplementedException(); + } + break; + } + } + + } + catch + { + //Debug.WriteLine(ex.Message + " " + ex.StackTrace); + return; + } + #endregion + + if (hWnd != null && !hWnd.Equals(IntPtr.Zero)) + { + desktopHandle = NativeMethods.GetDesktopWindow(); + shellHandle = NativeMethods.GetShellWindow(); + //Check we haven't picked up the desktop or the shell + if (!(hWnd.Equals(desktopHandle) || hWnd.Equals(shellHandle))) + { + if (MainWindow.multiscreen == false || SaveData.config.DisplayPauseSettings == SaveData.DisplayPauseEnum.all) + { + if (IntPtr.Equals(hWnd, workerWOrig)) //win10 + { + Pause.ResumeWallpaper(true); + } + else if (IntPtr.Equals(hWnd, progman)) //win7 + { + Pause.ResumeWallpaper(true); + } + else if (IntPtr.Equals(shell_tray, IntPtr.Zero) != true && IntPtr.Equals(hWnd, shell_tray) == true) //systrayhandle + { + Pause.ResumeWallpaper(false); + } + else if (NativeMethods.IsZoomed(hWnd)) // if window is maximised. + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false); //resume with audio disabled etc + } + else + Pause.SuspendWallpaper(true); + //Pause.SuspendWallpaper(true); + } + else if (IsZoomedCustom(hWnd, Screen.PrimaryScreen.DeviceName)) // isZoomed fails for games etc + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false); //resume with audio disabled etc + } + else + Pause.SuspendWallpaper(true); + //Pause.SuspendWallpaper(true); + } + else //window is not greater >90% + { + if (SaveData.config.AppFocusPause == SaveData.AppRulesEnum.pause) + { + Pause.SuspendWallpaper(true); + } + else + { + Pause.SuspendWallpaper(false); //resume with audio disabled etc + } + } + } + else + { + currDisplay = display; + if (IntPtr.Equals(hWnd, workerWOrig)) //win10 + { + Pause.ResumeWallpaper(true, currDisplay); + } + else if (IntPtr.Equals(hWnd, progman)) //win7 + { + Pause.ResumeWallpaper( true, currDisplay); + } + else if (IntPtr.Equals(shell_tray, IntPtr.Zero) != true && IntPtr.Equals(hWnd, shell_tray) == true) //systrayhandle + { + Pause.ResumeWallpaper( false, currDisplay); + } + else if (NativeMethods.IsZoomed(hWnd)) // if window is maximised. + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false, currDisplay); //resume with audio disabled etc + } + else + Pause.SuspendWallpaper(true, currDisplay); + //Pause.SuspendWallpaper(true, currDisplay); + } + else if (IsZoomedCustom(hWnd, currDisplay)) // isZoomed fails for games etc + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false, currDisplay); //resume with audio disabled etc + } + else + Pause.SuspendWallpaper(true, currDisplay); + //Pause.SuspendWallpaper(true, currDisplay); + } + else //window is not greater >90% + { + if (SaveData.config.AppFocusPause == SaveData.AppRulesEnum.pause) + { + //Debug.WriteLine("ALLAPPFN:" + ">90%, appfocus = pause"); + Pause.SuspendWallpaper(true, currDisplay); + } + else + { + //Debug.WriteLine("ALLAPPFN:" + ">90%, appfocus != pause"); + Pause.SuspendWallpaper(false, currDisplay); //resume with audio disabled etc + } + } + } + } + } + } + #endregion pause_all + + #region pause_foreground + private static void ForegroundPauseFn()//(IntPtr hWnd, string currProcessName) + { + + hWnd = NativeMethods.GetForegroundWindow(); + try + { + NativeMethods.GetWindowThreadProcessId(hWnd, out processID); + currProcess = Process.GetProcessById(processID); + //currProcessName = currProcess.ProcessName; + } + catch + { + Debug.WriteLine("getting processname failure, ignoring"); + //ignore, admin process etc + return; + } + //Debug.WriteLine("FOREGROUND PROCESS:- " + currProcess.ProcessName); + + #region Exceptions & Fixes + ProcessMonitorFixes(); + try + { + if (String.IsNullOrEmpty(currProcess.ProcessName)) + { + return; + } + + for (int i = 0; i < SaveData.appRules.Count; i++) + { + if (currProcess.ProcessName.Equals(SaveData.appRules[i].AppName, StringComparison.OrdinalIgnoreCase)) + { + if (SaveData.appRules[i].Rule == SaveData.AppRulesEnum.ignore) //always run when this process is foreground window, even when maximized + { + hWnd = workerWOrig; //assume desktop, to force unpause/wakeup of rePaper. + //Pause.SuspendWallpaper(false); //resume with audio disabled etc + //return; + } + else if (SaveData.appRules[i].Rule == SaveData.AppRulesEnum.pause) //sleep + { + Pause.SuspendWallpaper(true); + return; + } + else if (SaveData.appRules[i].Rule == SaveData.AppRulesEnum.kill) + { + throw new NotImplementedException(); + } + break; + } + } + + if (currProcess.ProcessName.Equals("emuhawk", StringComparison.OrdinalIgnoreCase) || currProcess.ProcessName.Equals("livelywpf", StringComparison.OrdinalIgnoreCase) || + currProcess.ProcessName.Equals("devenv", StringComparison.OrdinalIgnoreCase) || currProcess.ProcessName.Equals("shellexperiencehost", StringComparison.OrdinalIgnoreCase) || //visual studio, notification tray etc + (currProcess.ProcessName.Equals("searchui", StringComparison.OrdinalIgnoreCase)) || currProcess.ProcessName.Equals("livelycefsharp", StringComparison.OrdinalIgnoreCase)) //startmenu search.. + { + + hWnd = workerWOrig; + } + + } + catch + { + //Debug.WriteLine(ex.Message + " " + ex.StackTrace); + return; + } + + #endregion Exceptions & Fixes + + if (hWnd != null && !hWnd.Equals(IntPtr.Zero)) + { + desktopHandle = NativeMethods.GetDesktopWindow(); + shellHandle = NativeMethods.GetShellWindow(); + //Check we haven't picked up the desktop or the shell + if (!(hWnd.Equals(desktopHandle) || hWnd.Equals(shellHandle))) + { + if (MainWindow.multiscreen == false || SaveData.config.DisplayPauseSettings == SaveData.DisplayPauseEnum.all //pause all wp's when any window is maximised. + || (MainWindow.multiscreen && SaveData.config.WallpaperArrangement == WallpaperArrangement.span) )//assuming single wp for span, so just pause "everything" + { + if (IntPtr.Equals(hWnd, workerWOrig)) //win10 + { + Pause.ResumeWallpaper(true); + } + else if (IntPtr.Equals(hWnd, progman)) //win7 + { + Pause.ResumeWallpaper(true); + } + else if (IntPtr.Equals(shell_tray, IntPtr.Zero) != true && IntPtr.Equals(hWnd, shell_tray) == true) //systrayhandle + { + Pause.ResumeWallpaper(false); + } + else if (NativeMethods.IsZoomed(hWnd)) // if window is maximised. + { + if(SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false); //resume with audio disabled etc + } + else + Pause.SuspendWallpaper(true); + } + else if (IsZoomedCustom(hWnd, Screen.PrimaryScreen.DeviceName) )//&& !StaticPinvoke.IsIconic(hWnd)) // isZoomed fails for games etc + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false); //resume with audio disabled etc + } + else + Pause.SuspendWallpaper(true); + } + else //window is not greater >90% + { + if (SaveData.config.AppFocusPause == SaveData.AppRulesEnum.pause) + { + Pause.SuspendWallpaper(true); + } + else + { + Pause.SuspendWallpaper(false); //resume with audio disabled etc + } + } + } + else //multiscreen wp pause algorithm, for per-monitor pause rule. + { + if ((currDisplay = MapWindowToMonitor(hWnd)) != null) + { + //unpausing the rest of wp's, fix for limitation for this algorithm. + foreach (var item in Screen.AllScreens) + { + if(item.DeviceName != currDisplay) + Pause.ResumeWallpaper(true, item.DeviceName); + } + } + else + { + //can happen if no display connected?! + return; + } + + if (IntPtr.Equals(hWnd, workerWOrig)) //win10 + { + Pause.ResumeWallpaper(true, currDisplay); + } + else if (IntPtr.Equals(hWnd, progman)) //win7 + { + Pause.ResumeWallpaper(true, currDisplay); + } + else if (IntPtr.Equals(shell_tray, IntPtr.Zero) != true && IntPtr.Equals(hWnd, shell_tray) == true) //systrayhandle + { + Pause.ResumeWallpaper(false, currDisplay); + } + else if (NativeMethods.IsZoomed(hWnd)) // if window is maximised. + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false, currDisplay); + } + else + Pause.SuspendWallpaper(true, currDisplay); + + } + else if (IsZoomedCustom(hWnd, currDisplay)) // isZoomed fails for games etc which does not set the maximised flag? ( dota2 in windowed mode etc) + { + if (SaveData.config.AppFullscreenPause == SaveData.AppRulesEnum.ignore) + { + Pause.SuspendWallpaper(false, currDisplay); + } + else + Pause.SuspendWallpaper(true, currDisplay); + + } + else //window is not greater >90% + { + if (SaveData.config.AppFocusPause == SaveData.AppRulesEnum.pause) + { + Pause.SuspendWallpaper(true, currDisplay); + } + else + { + Pause.SuspendWallpaper(false, currDisplay); //resume with audio disabled etc + } + } + } + } + } + } + #endregion pause_foreground + + //private const int GWL_EXSTYLE = -0x14; + private static bool Check_EX_Style(IntPtr hw, long ex_style)//todo:- I think this is wrong, fix it. + { + var style = NativeMethods.GetWindowLongPtr(hw, (int)NativeMethods.GWL.GWL_EXSTYLE); + if (((long)style & ex_style) >= 1) + return true; + else + return false; + } + + /// + /// This fn checks if hWnd window size is >95% for the given display. + /// + /// + /// + /// True if windowsize is greater. + private static bool IsZoomedCustom(IntPtr hWnd, string display) + { + try + { + NativeMethods.GetWindowThreadProcessId(hWnd, out processID); + currProcess = Process.GetProcessById(processID); + } + catch + { + + Debug.WriteLine("getting processname failure, skipping isZoomedCustom()"); + //ignore, admin process etc + return false; + } + + NativeMethods.GetWindowRect(hWnd, out appBounds); + screenBounds = System.Windows.Forms.Screen.FromHandle(hWnd).Bounds; + if ((appBounds.Bottom - appBounds.Top) >= screenBounds.Height * .95f && (appBounds.Right - appBounds.Left) >= screenBounds.Width * .95f) // > if foreground app 95% working-area( - taskbar of monitor) + return true; + else + return false; + /* + if (MainWindow.multiscreen) + { + + NativeMethods.GetWindowRect(hWnd, out appBounds); + try + { + screenBounds = Array.Find(Screen.AllScreens, x => x.DeviceName == display).Bounds; + } + catch (ArgumentNullException e) + { + Logger.Error("Array.Find() returned null" + e.ToString()); + return false; + } + + if ((appBounds.Bottom - appBounds.Top) >= screenBounds.Height * .95f && (appBounds.Right - appBounds.Left) >= screenBounds.Width * .95f) // > if foreground app 95% working-area( - taskbar of monitor) + return true; + else + return false; + + } + else + { + NativeMethods.GetWindowRect(hWnd, out appBounds); + screenBounds = System.Windows.Forms.Screen.FromHandle(hWnd).Bounds; + if ((appBounds.Bottom - appBounds.Top) >= screenBounds.Height * .95f && (appBounds.Right - appBounds.Left) >= screenBounds.Width * .95f) // > if foreground app 95% working-area( - taskbar of monitor) + return true; + else + return false; + } + */ + } + + /// + /// Finds out which displaydevice the given application is residing. + /// + /// + /// + private static string MapWindowToMonitor(IntPtr handle) + { + try + { + var screen = System.Windows.Forms.Screen.FromHandle(handle); + return screen.DeviceName; + } + catch + { + //what if there is no display connected? docs not listing anything weird. + return null; + } + /* + NativeMethods.MonitorInfoEx monitor = new NativeMethods.MonitorInfoEx(); + monitor.Init(); + //monitor + IntPtr id = NativeMethods.MonitorFromWindow(handle, NativeMethods.MONITOR_DEFAULTTONULL); + + NativeMethods.GetMonitorInfo(id, ref monitor); + //Debug.WriteLine("monitor:- " + monitor.DeviceName); + return monitor.DeviceName; + */ + } + + private static void ProcessMonitorFixes() + { + //todo: use hooks to check if the handles are closed, ie WM_CLOSE, WM_DESTROY msg ( cannot use NativeMethods.IsWindow() as it is unsafe/unreliable). + + if (IntPtr.Equals(workerWOrig, IntPtr.Zero)) + { + Logger.Info("searching workerWOrig.."); + var folderView = NativeMethods.FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", null); + if (folderView == IntPtr.Zero) + { + //If the desktop isn't under Progman, cycle through the WorkerW handles and find the correct one + do + { + workerWOrig = NativeMethods.FindWindowEx(NativeMethods.GetDesktopWindow(), workerWOrig, "WorkerW", null); + folderView = NativeMethods.FindWindowEx(workerWOrig, IntPtr.Zero, "SHELLDLL_DefView", null); + } while (folderView == IntPtr.Zero && workerWOrig != IntPtr.Zero); + } + } + + if (IntPtr.Equals(shell_tray, IntPtr.Zero)) //start + { + Logger.Info("searching again shell_tray.."); + shell_tray = NativeMethods.FindWindow("Shell_TrayWnd", null); + } + } + + #region obsolete + private static List visibleWindows = new List(); + [Obsolete("Using managed code instead, not EnumWindowProc")] + private static bool IsWindowVisible(IntPtr hWnd, IntPtr lParam) + { + // Check if window is active/visible. + if (NativeMethods.IsWindowVisible(hWnd)) + { + if (!IntPtr.Equals(shellHandle, hWnd) && !NativeMethods.IsIconic(hWnd) && NativeMethods.GetWindowTextLength(hWnd) != 0 + && !IntPtr.Equals(hWnd, IntPtr.Zero) && NativeMethods.IsZoomed(hWnd) || IsZoomedCustomAllDisplays(hWnd)) + { + visibleWindows.Add(hWnd); + } + } + return true; + } + + [Obsolete("using managed code instead, call IsZoomedCustom()")] + /// + /// Checks if window is >95% in any of all the displays connected. + /// + /// + /// + private static bool IsZoomedCustomAllDisplays(IntPtr hWnd) + { + foreach (var item in Screen.AllScreens) + { + if (IsZoomedCustom(hWnd, item.DeviceName)) + return true; + } + return false; + } + + [Obsolete("Don't remember when/why this was made lol")] + private static IntPtr[] GetProcessWindows(int process) + { + IntPtr[] apRet = (new IntPtr[256]); + int iCount = 0; + IntPtr pLast = IntPtr.Zero; + do + { + pLast = NativeMethods.FindWindowEx(IntPtr.Zero, pLast, null, null); + int iProcess_; + NativeMethods.GetWindowThreadProcessId(pLast, out iProcess_); + if (iProcess_ == process) apRet[iCount++] = pLast; + } while (pLast != IntPtr.Zero); + System.Array.Resize(ref apRet, iCount); + return apRet; + } + + #endregion obsolete + + #endregion thread_monitor_pause/play + + #region wp_close_funtions + /// + /// Close wallpaper running on given monitor devicename. + /// + /// + public static void CloseWallpaper(string diplayDevice) + { + dispatcherTimer.Stop(); + + int i = 0; + if ((i = SetupDesktop.wallpapers.FindIndex(x => x.DeviceName == diplayDevice)) != -1) + { + wallpapers.RemoveAt(i); + SaveData.SaveWallpaperLayout(); + } + + if ( (i = mediakitPlayers.FindIndex( x => x.DisplayID == diplayDevice)) != -1) + { + mediakitPlayers[i].MP.StopPlayer(); + mediakitPlayers[i].MP.Close(); + //mediakitPlayers[i].mp = null; + mediakitPlayers.RemoveAt(i); + //return; + } + + if ((i = wmPlayers.FindIndex(x => x.DisplayID == diplayDevice)) != -1) + { + wmPlayers[i].MP.StopPlayer(); + wmPlayers[i].MP.Close(); + //wmPlayers[i].mp = null; + wmPlayers.RemoveAt(i); + //return; + } + + if ((i = gifWallpapers.FindIndex(x => x.DisplayID == diplayDevice)) != -1) + { + gifWallpapers[i].Gif.Close(); + //gifWallpapers[i].gif = null; + gifWallpapers.RemoveAt(i); + //return; + } + + try + { + if ((i = extPrograms.FindIndex(x => x.DisplayID == diplayDevice)) != -1) + { + if (extPrograms[i].Proc != null) + { + if (extPrograms[i].Proc.HasExited == false) + { + extPrograms[i].Proc.Kill(); + extPrograms[i].Proc.Close(); + //setup.proc.Dispose(); + //extPrograms[i].proc = null; + } + } + extPrograms.RemoveAt(i); + } + //return; + } + catch (Exception e) + { + Logger.Error(e.ToString()); + } + + try + { + if ((i = webProcesses.FindIndex(x => x.DisplayID == diplayDevice)) != -1) + { + webProcesses[i].Proc.OutputDataReceived -= WebProcess_OutputDataReceived; + //webProcesses[i].Proc.StandardInput.WriteLine("Terminate"); + //webProcesses[i].Proc.Close(); //exit event is disposing it. + + webProcesses[i].Proc.Refresh(); + if (webProcesses[i].Proc != null) + { + if (webProcesses[i].Proc.HasExited == false) + { + webProcesses[i].Proc.Kill(); + webProcesses[i].Proc.Close(); + } + } + //MessageBox.Show(webProcesses[i].ToString()); + webProcesses.RemoveAt(i); + //webProcesses.RemoveAt(i); //exit event is removing it. + //return; + } + } + catch (Exception ex) + { + Debug.WriteLine("web handle 0:- " + ex.Message + " " + ex.StackTrace); + } + + dispatcherTimer.Start(); + RefreshDesktop(); + } + + /// + /// Close all wp's of a particular type. + /// + /// wallpaper type. + public static void CloseAllWallpapers(WallpaperType type) + { + dispatcherTimer.Stop(); + wallpapers.RemoveAll(x => x.Type == type); + SaveData.SaveWallpaperLayout(); + + if (type == WallpaperType.video) + { + var result = mediakitPlayers.FindAll(x => x.IsGif == false); + foreach (var item in result) + { + item.MP.StopPlayer(); + item.MP.Close(); + //item.mp = null; + } + //mediakitPlayers.Clear(); + mediakitPlayers.RemoveAll(x => x.IsGif == false); + + foreach (var item in wmPlayers) + { + //Debug.WriteLine("Disposing windowsmediaplayer:- " + item.handle + " " + item.displayID); + item.MP.StopPlayer(); + item.MP.Close(); + } + wmPlayers.Clear(); + } + else if (type == WallpaperType.web || type == WallpaperType.url || type == WallpaperType.web_audio) + { + try + { + foreach (var item in webProcesses) + { + item.Proc.OutputDataReceived -= WebProcess_OutputDataReceived; + //item.Proc.Exited -= WebProcess_Exited; + item.Proc.Refresh(); + if (item.Proc != null) + { + if (item.Proc.HasExited == false) + { + item.Proc.Kill(); + item.Proc.Close(); + } + } + } + webProcesses.Clear(); + } + catch (Exception ex) + { + //Debug.WriteLine(ex.ToString()); + Logger.Info(ex.ToString()); + } + /* + var result = webProcesses.FindAll(x => x.Type == type); + foreach (var item in result) + { + try + { + item.Proc.OutputDataReceived -= WebProcess_OutputDataReceived; + //item.Proc.StandardInput.WriteLine("Terminate"); + //item.Proc.Close(); //exit event is disposing it. + //webProcess = null; + + } + catch (Exception ex) + { + Debug.WriteLine("web handle 0:- " + ex.Message + " " + ex.StackTrace); + } + } + //webProcesses.RemoveAll(x => x.Type == SetupDesktop.WallpaperType.web); //exit event is removing it. + */ + } + else if (type == WallpaperType.godot || type == WallpaperType.unity || type == WallpaperType.unity_audio || type == WallpaperType.app) + { + var result = extPrograms.FindAll(x => x.Type == type); + + try + { + foreach (var item in extPrograms) + { + if (item.Proc != null) + { + //Debug.WriteLine("currProces" + proc.ProcessName); + if (item.Proc.HasExited == false) + { + item.Proc.Kill(); + item.Proc.Close(); //calls dispose also. + //setup.proc.Dispose(); + //item.proc = null; + } + } + } + extPrograms.RemoveAll(x => x.Type == type); + } + catch (Exception e) + { + Logger.Info("Disposeerror:- "+ e.ToString()); + } + } + else if(type == WallpaperType.gif) + { + var result = mediakitPlayers.FindAll(x => x.IsGif == true); + foreach (var item in result) + { + item.MP.StopPlayer(); + item.MP.Close(); + //item.mp = null; + } + //mediakitPlayers.Clear(); + mediakitPlayers.RemoveAll(x => x.IsGif == true); + + foreach (var item in gifWallpapers) + { + item.Gif.Close(); + //item.gif = null; + } + gifWallpapers.Clear(); + } + + dispatcherTimer.Start(); + + RefreshDesktop(); + } + + /// + /// Closes all open wp's + /// + /// if false, clear disk savedata for wp layout + public static void CloseAllWallpapers(bool applicationExit = false) + { + var _timerStatus = dispatcherTimer.IsEnabled; + if (_timerStatus) + dispatcherTimer.Stop(); + + if (!applicationExit) + { + wallpapers.Clear(); + SaveData.SaveWallpaperLayout(); + } + + if (bizhawkProc != null) + { + bizhawkProc.Kill(); + } + + try + { + foreach (var item in webProcesses) + { + //Things exploded *_* ...threads man. todo:- Close the browser properly goddamit. + /* + item.Proc.OutputDataReceived -= WebProcess_OutputDataReceived; + item.Proc.StandardInput.WriteLine("Terminate"); + if (applicationExit) + { + item.Proc.Exited -= WebProcess_Exited; + item.Proc.WaitForExit(5000); //blocking thread. + if (!item.Proc.HasExited) + item.Proc.Kill(); + item.Proc.Close(); + } + */ + item.Proc.OutputDataReceived -= WebProcess_OutputDataReceived; + //item.Proc.Exited -= WebProcess_Exited; + item.Proc.Refresh(); + if (item.Proc != null) + { + if (item.Proc.HasExited == false) + { + item.Proc.Kill(); + item.Proc.Close(); + } + } + } + webProcesses.Clear(); + } + catch (Exception ex) + { + //Debug.WriteLine(ex.ToString()); + Logger.Info(ex.ToString()); + } + + try + { + foreach (var item in extPrograms) + { + item.Proc.Refresh(); + if (item.Proc != null) + { + if (item.Proc.HasExited == false) + { + item.Proc.Kill(); + item.Proc.Close(); + //setup.proc.Dispose(); + //item.proc = null; + } + } + } + extPrograms.Clear(); + } + catch(Exception e) + { + Logger.Info("Disposeerror:- " + e.ToString()); + } + + foreach (var item in mediakitPlayers) + { + item.MP.StopPlayer(); + item.MP.Close(); + //item.mp = null; + } + mediakitPlayers.Clear(); + + foreach (var item in wmPlayers) + { + item.MP.StopPlayer(); + item.MP.Close(); + } + wmPlayers.Clear(); + + foreach (var item in gifWallpapers) + { + item.Gif.Close(); + //item.gif = null; + } + gifWallpapers.Clear(); + + + //ext programs running + SaveData.runningPrograms.Clear(); + SaveData.SaveRunningPrograms(); + + if (_timerStatus && !applicationExit) + dispatcherTimer.Start(); + + RefreshDesktop(); + } + #endregion + + #region everything_else + + private static bool _timerInitilaized = false; + /// + /// Setup running Process monitor timer fn. + /// + public static void InitializeTimer() + { + if (!_timerInitilaized) + { + _timerInitilaized = true; + dispatcherTimer.Tick += new EventHandler(ProcessMonitor); + dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, SaveData.config.ProcessTimerInterval); + } + } + + private static void RemoveAppFromTaskbar(IntPtr handle) + { + NativeMethods.SetWindowLongPtr(new HandleRef(null, handle), (int)NativeMethods.GWL.GWL_EXSTYLE, (IntPtr)NativeMethods.WindowStyles.WS_EX_NOACTIVATE); + } + + /// + /// Removes window border & some menuitems. Won't remove everything in apps with custom UI system. + /// Flags Credit: https://github.com/Codeusa/Borderless-Gaming + /// If there is an issue with me using the flags just let me know I will remove it. + /// + /// + private static void BorderlessWinStyle(IntPtr handle) + { + // Get window styles + var styleCurrentWindowStandard = NativeMethods.GetWindowLongPtr(handle, (-16)); + var styleCurrentWindowExtended = NativeMethods.GetWindowLongPtr(handle, (-20)); + + // Compute new styles (XOR of the inverse of all the bits to filter) + var styleNewWindowStandard = + styleCurrentWindowStandard.ToInt64() + & ~( + (Int64)NativeMethods.WindowStyles.WS_CAPTION // composite of Border and DialogFrame + | (Int64)NativeMethods.WindowStyles.WS_THICKFRAME + | (Int64)NativeMethods.WindowStyles.WS_SYSMENU + | (Int64)NativeMethods.WindowStyles.WS_MAXIMIZEBOX // same as TabStop + | (Int64)NativeMethods.WindowStyles.WS_MINIMIZEBOX // same as Group + ); + + + var styleNewWindowExtended = + styleCurrentWindowExtended.ToInt64() + & ~( + (Int64)NativeMethods.WindowStyles.WS_EX_DLGMODALFRAME + | (Int64)NativeMethods.WindowStyles.WS_EX_COMPOSITED + | (Int64)NativeMethods.WindowStyles.WS_EX_WINDOWEDGE + | (Int64)NativeMethods.WindowStyles.WS_EX_CLIENTEDGE + | (Int64)NativeMethods.WindowStyles.WS_EX_LAYERED + | (Int64)NativeMethods.WindowStyles.WS_EX_STATICEDGE + | (Int64)NativeMethods.WindowStyles.WS_EX_TOOLWINDOW + | (Int64)NativeMethods.WindowStyles.WS_EX_APPWINDOW + ); + + // update window styles + NativeMethods.SetWindowLongPtr(new HandleRef(null, handle), (-16), (IntPtr)styleNewWindowStandard); + NativeMethods.SetWindowLongPtr(new HandleRef(null, handle), (-20), (IntPtr)styleNewWindowExtended); + + // remove the menu and menuitems and force a redraw + var menuHandle = NativeMethods.GetMenu(handle); + if (menuHandle != IntPtr.Zero) + { + var menuItemCount = NativeMethods.GetMenuItemCount(menuHandle); + + for (var i = 0; i < menuItemCount; i++) + { + NativeMethods.RemoveMenu(menuHandle, 0, NativeMethods.MF_BYPOSITION | NativeMethods.MF_REMOVE); + } + NativeMethods.DrawMenuBar(handle); + } + } + /// + /// Force redraw desktop, clears wp persisting on screen even after close. + /// + public static void RefreshDesktop() + { + //todo:- right now I'm just telling windows to change wallpaper with a null value of zero size, there has to be a PROPER way to do this. + NativeMethods.SystemParametersInfo(NativeMethods.SPI_SETDESKWALLPAPER, 0, null, NativeMethods.SPIF_UPDATEINIFILE); + } + + /// + /// Adds the wp as child of spawned desktop-workerw window. + /// + /// handle of wp + private static void SetParentWorkerW(IntPtr windowHandle) + { + //return; + if (System.Environment.OSVersion.Version.Major == 6 && System.Environment.OSVersion.Version.Minor == 1) //windows 7 + { + NativeMethods.ShowWindow(workerw, (uint)0); //hide worker handle. + IntPtr ret = NativeMethods.SetParent(windowHandle, progman); + if(ret.Equals(IntPtr.Zero)) + { + LogWin32Error("failed to set parent(win7),"); + } + workerw = progman;//worker handle is progman in win7, this is untested with all fn's: addwallpaper(), wp pause, resize events.. (I don't have win7 system with me). + } + else + { + IntPtr ret = NativeMethods.SetParent(windowHandle, workerw); + if (ret.Equals(IntPtr.Zero)) + { + LogWin32Error("failed to set parent,"); + } + } + } + + /// + /// Sets the window as bottom-most, no-activate window. + /// + /// + private static void SetWindowBottomMost(IntPtr windowHandle) + { + NativeMethods.SetWindowPos(windowHandle, 1, 0, 0, 0, 0, 0x0002 | 0x0010 | 0x0001); // SWP_NOMOVE ,SWP_NOACTIVATE,SWP_NOSIZE & Bottom most. + } + + /// + /// Focus fix, otherwise when new applicaitons launch fullscreen wont giveup window handle once SetParent() is called. + /// + public static void SetFocus(bool focusLively = true) + { + //IntPtr progman = NativeMethods.FindWindow("Progman", null); + NativeMethods.SetForegroundWindow(progman); //change focus from the started window//application. + NativeMethods.SetFocus(progman); + + IntPtr livelyWindow = new WindowInteropHelper(System.Windows.Application.Current.MainWindow).Handle; + if (!livelyWindow.Equals(IntPtr.Zero) && NativeMethods.IsWindowVisible(livelyWindow) && focusLively) //todo:- not working for cefsharp wp launch, why? + { + NativeMethods.SetForegroundWindow(livelyWindow); + NativeMethods.SetFocus(livelyWindow); + } + + } + + public static void RestartWallpapers() + { + dispatcherTimer.Stop(); + var bcp = wallpapers.ToList(); + wallpapers.Clear(); + CloseAllWallpapers(); + + foreach (var item in bcp) + { + SetupDesktop.SetWallpaper(new WallpaperLayout() { Arguments = item.Arguments, DeviceName = item.DeviceName, FilePath = item.FilePath, Type = item.Type }); + } + + dispatcherTimer.Start(); + } + + private static void LogWin32Error(string msg = null) + { + //todo: throw win32 exception. + int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); + if (err != 0) + { + Logger.Error(msg + " HRESULT:" + err); + } + } + + #endregion everything_else + } +} diff --git a/src/livelywpf/livelywpf/wp_lib/VolumeMixer.cs b/src/livelywpf/livelywpf/wp_lib/VolumeMixer.cs new file mode 100644 index 00000000..06d4fb35 --- /dev/null +++ b/src/livelywpf/livelywpf/wp_lib/VolumeMixer.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace livelywpf +{ + //credit: https://stackoverflow.com/questions/14306048/controlling-volume-mixer + public class VolumeMixer + { + public static float? GetApplicationVolume(int pid) + { + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + return null; + + float level; + volume.GetMasterVolume(out level); + Marshal.ReleaseComObject(volume); + return level * 100; + } + + public static bool? GetApplicationMute(int pid) + { + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + return null; + + bool mute; + volume.GetMute(out mute); + Marshal.ReleaseComObject(volume); + return mute; + } + + public static void SetApplicationVolume(int pid, float level) + { + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + return; + + Guid guid = Guid.Empty; + volume.SetMasterVolume(level / 100, ref guid); + Marshal.ReleaseComObject(volume); + } + + public static void SetApplicationMute(int pid, bool mute) + { + ISimpleAudioVolume volume = GetVolumeObject(pid); + if (volume == null) + return; + + Guid guid = Guid.Empty; + volume.SetMute(mute, ref guid); + Marshal.ReleaseComObject(volume); + } + + private static ISimpleAudioVolume GetVolumeObject(int pid) + { + // get the speakers (1st render + multimedia) device + IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator()); + IMMDevice speakers; + deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers); + + // activate the session manager. we need the enumerator + Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID; + object o; + speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o); + IAudioSessionManager2 mgr = (IAudioSessionManager2)o; + + // enumerate sessions for on this device + IAudioSessionEnumerator sessionEnumerator; + mgr.GetSessionEnumerator(out sessionEnumerator); + int count; + sessionEnumerator.GetCount(out count); + + // search for an audio session with the required name + // NOTE: we could also use the process id instead of the app name (with IAudioSessionControl2) + ISimpleAudioVolume volumeControl = null; + for (int i = 0; i < count; i++) + { + IAudioSessionControl2 ctl; + sessionEnumerator.GetSession(i, out ctl); + int cpid; + ctl.GetProcessId(out cpid); + + if (cpid == pid) + { + volumeControl = ctl as ISimpleAudioVolume; + break; + } + Marshal.ReleaseComObject(ctl); + } + Marshal.ReleaseComObject(sessionEnumerator); + Marshal.ReleaseComObject(mgr); + Marshal.ReleaseComObject(speakers); + Marshal.ReleaseComObject(deviceEnumerator); + return volumeControl; + } + } + + [ComImport] + [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] + internal class MMDeviceEnumerator + { + } + + internal enum EDataFlow + { + eRender, + eCapture, + eAll, + EDataFlow_enum_count + } + + internal enum ERole + { + eConsole, + eMultimedia, + eCommunications, + ERole_enum_count + } + + [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IMMDeviceEnumerator + { + int NotImpl1(); + + [PreserveSig] + int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice); + + // the rest is not implemented + } + + [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IMMDevice + { + [PreserveSig] + int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface); + + // the rest is not implemented + } + + [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IAudioSessionManager2 + { + int NotImpl1(); + int NotImpl2(); + + [PreserveSig] + int GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum); + + // the rest is not implemented + } + + [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IAudioSessionEnumerator + { + [PreserveSig] + int GetCount(out int SessionCount); + + [PreserveSig] + int GetSession(int SessionCount, out IAudioSessionControl2 Session); + } + + [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface ISimpleAudioVolume + { + [PreserveSig] + int SetMasterVolume(float fLevel, ref Guid EventContext); + + [PreserveSig] + int GetMasterVolume(out float pfLevel); + + [PreserveSig] + int SetMute(bool bMute, ref Guid EventContext); + + [PreserveSig] + int GetMute(out bool pbMute); + } + + [Guid("bfb7ff88-7239-4fc9-8fa2-07c950be9c6d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IAudioSessionControl2 + { + // IAudioSessionControl + [PreserveSig] + int NotImpl0(); + + [PreserveSig] + int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int SetDisplayName([MarshalAs(UnmanagedType.LPWStr)]string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext); + + [PreserveSig] + int GetIconPath([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int SetIconPath([MarshalAs(UnmanagedType.LPWStr)] string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext); + + [PreserveSig] + int GetGroupingParam(out Guid pRetVal); + + [PreserveSig] + int SetGroupingParam([MarshalAs(UnmanagedType.LPStruct)] Guid Override, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext); + + [PreserveSig] + int NotImpl1(); + + [PreserveSig] + int NotImpl2(); + + // IAudioSessionControl2 + [PreserveSig] + int GetSessionIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int GetSessionInstanceIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal); + + [PreserveSig] + int GetProcessId(out int pRetVal); + + [PreserveSig] + int IsSystemSoundsSession(); + + [PreserveSig] + int SetDuckingPreference(bool optOut); + } + +} diff --git a/src/livelywpf/livelywpf/wp_windows/GifWindow.xaml b/src/livelywpf/livelywpf/wp_windows/GifWindow.xaml new file mode 100644 index 00000000..5b440133 --- /dev/null +++ b/src/livelywpf/livelywpf/wp_windows/GifWindow.xaml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/src/livelywpf/livelywpf/wp_windows/GifWindow.xaml.cs b/src/livelywpf/livelywpf/wp_windows/GifWindow.xaml.cs new file mode 100644 index 00000000..2b7a653a --- /dev/null +++ b/src/livelywpf/livelywpf/wp_windows/GifWindow.xaml.cs @@ -0,0 +1,100 @@ +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.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using XamlAnimatedGif; + +namespace livelywpf +{ + /// + /// Interaction logic for GifWindow.xaml + /// + public partial class GifWindow : Window + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + Animator animator; + public GifWindow(string path) + { + InitializeComponent(); + + gifImg.Stretch = SaveData.config.GifScaler; + AnimationBehavior.AddErrorHandler(gifImg, ErrorEvent); + AnimationBehavior.AddLoadedHandler(gifImg, AnimationBehavior_OnLoaded); + AnimationBehavior.SetSourceUri(gifImg, new Uri(path)); + AnimationBehavior.SetRepeatBehavior(gifImg, System.Windows.Media.Animation.RepeatBehavior.Forever); + } + + private void ErrorEvent(object s, AnimationErrorEventArgs e) + { + Logger.Error("GIF:" + e.ToString()); + MessageBox.Show(Properties.Resources.msgGIFfailure, Properties.Resources.txtLivelyErrorMsgTitle); + } + + private void AnimationBehavior_OnLoaded(object sender, RoutedEventArgs e) + { + try + { + animator = AnimationBehavior.GetAnimator(gifImg); + animator.Play(); + } + catch //prevents playback(crash otherwise), error gets logged in ErrorEvent() + { } + } + + public void PausePlayer() + { + if(animator != null) + { + if(animator.IsPaused == false) + animator.Pause(); + } + } + + public void ResumePlayer() + { + if (animator != null) + { + if (animator.IsPaused == true) + animator.Play(); + } + } + + private void GifImg_Loaded(object sender, RoutedEventArgs e) + { + + } + + //prevent mouseclick focus steal(bottom-most wp rendering mode). + protected override void OnSourceInitialized(EventArgs e) + { + base.OnSourceInitialized(e); + var source = PresentationSource.FromVisual(this) as HwndSource; + source.AddHook(WndProc); + } + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); + } + else + { + return IntPtr.Zero; + } + } + private const int WM_MOUSEACTIVATE = 0x0021; + private const int MA_NOACTIVATE = 0x0003; + } +} diff --git a/src/livelywpf/livelywpf/wp_windows/MediaPlayer.xaml b/src/livelywpf/livelywpf/wp_windows/MediaPlayer.xaml new file mode 100644 index 00000000..fa33bc1c --- /dev/null +++ b/src/livelywpf/livelywpf/wp_windows/MediaPlayer.xaml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/src/livelywpf/livelywpf/wp_windows/MediaPlayer.xaml.cs b/src/livelywpf/livelywpf/wp_windows/MediaPlayer.xaml.cs new file mode 100644 index 00000000..bbd38028 --- /dev/null +++ b/src/livelywpf/livelywpf/wp_windows/MediaPlayer.xaml.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +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.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace livelywpf +{ + /// + /// Interaction logic for MediaPlayer.xaml + /// + public partial class MediaPlayer : Window + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + public MediaPlayer(string path) + { + InitializeComponent(); + + mePlayer.LoadedBehavior = MediaState.Manual; + mePlayer.Source = new Uri(path); + mePlayer.Stretch = SaveData.config.VideoScaler; + mePlayer.MediaOpened += MePlayer_MediaOpened; + mePlayer.MediaEnded += MePlayer_MediaEnded; + mePlayer.MediaFailed += MePlayer_MediaFailed; + if (SaveData.config.MuteVideo || MainWindow.multiscreen) + mePlayer.Volume = 0; + else + mePlayer.Volume = 1; + + mePlayer.Play(); + } + + private void MePlayer_MediaOpened(object sender, RoutedEventArgs e) + { + + } + private void MePlayer_MediaFailed(object sender, ExceptionRoutedEventArgs e) + { + //todo proper error handling. + Logger.Error("MediaFoundation Playback Failure:-" + e.ErrorException); + MessageBox.Show(Properties.Resources.msgMediaFoundationFailure, Properties.Resources.txtLivelyErrorMsgTitle); + } + + public void MutePlayer( bool isMute) + { + if (isMute) + mePlayer.Volume = 0; + else + mePlayer.Volume = 1; + } + + public void PausePlayer() + { + mePlayer.Pause(); + } + + public void PlayMedia() + { + mePlayer.Play(); + } + + public void StopPlayer() + { + mePlayer.Stop(); + } + + //credit: https://stackoverflow.com/questions/4338951/how-do-i-determine-if-mediaelement-is-playing/4341285 + private static MediaState GetMediaState(MediaElement myMedia) + { + FieldInfo hlp = typeof(MediaElement).GetField("_helper", BindingFlags.NonPublic | BindingFlags.Instance); + object helperObject = hlp.GetValue(myMedia); + FieldInfo stateField = helperObject.GetType().GetField("_currentState", BindingFlags.NonPublic | BindingFlags.Instance); + MediaState state = (MediaState)stateField.GetValue(helperObject); + return state; + } + + private void MePlayer_MediaEnded(object sender, RoutedEventArgs e) + { + //mePlayer.Stop(); //fix for GetMediaState() + mePlayer.Position = TimeSpan.Zero;//new TimeSpan(0, 0, 0, 1); + mePlayer.Play(); + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + mePlayer.MediaOpened -= MePlayer_MediaOpened; + mePlayer.MediaEnded -= MePlayer_MediaEnded; + mePlayer.MediaFailed -= MePlayer_MediaFailed; + + mePlayer.Stop(); + mePlayer.Source = null; + mePlayer.Close(); + } + + //prevent mouseclick focus steal(bottom-most wp rendering mode). + protected override void OnSourceInitialized(EventArgs e) + { + base.OnSourceInitialized(e); + var source = PresentationSource.FromVisual(this) as HwndSource; + source.AddHook(WndProc); + } + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); + } + else + { + return IntPtr.Zero; + } + } + private const int WM_MOUSEACTIVATE = 0x0021; + private const int MA_NOACTIVATE = 0x0003; + } +} diff --git a/src/livelywpf/livelywpf/wp_windows/Mediakit.xaml b/src/livelywpf/livelywpf/wp_windows/Mediakit.xaml new file mode 100644 index 00000000..7f8b3bde --- /dev/null +++ b/src/livelywpf/livelywpf/wp_windows/Mediakit.xaml @@ -0,0 +1,18 @@ + + + + + diff --git a/src/livelywpf/livelywpf/wp_windows/Mediakit.xaml.cs b/src/livelywpf/livelywpf/wp_windows/Mediakit.xaml.cs new file mode 100644 index 00000000..15a0bb17 --- /dev/null +++ b/src/livelywpf/livelywpf/wp_windows/Mediakit.xaml.cs @@ -0,0 +1,123 @@ +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.Forms; +using System.Windows.Input; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using WPFMediaKit.DirectShow.Controls; + +namespace livelywpf +{ + + /// + /// Interaction logic for Mediakit.xaml + /// + public partial class Mediakit : Window + { + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public Mediakit(string path) + { + InitializeComponent(); + + mePlayer.LoadedBehavior = WPFMediaKit.DirectShow.MediaPlayers.MediaState.Manual; + mePlayer.Source = new Uri(path); + mePlayer.Stretch = SaveData.config.VideoScaler; + mePlayer.MediaFailed += MePlayer_MediaFailed; + mePlayer.MediaEnded += MePlayer_MediaEnded; + mePlayer.MediaOpened += MePlayer_MediaOpened; + mePlayer.Loop = true; //convenient! + if (SaveData.config.MuteVideo || MainWindow.multiscreen) + mePlayer.Volume = 0; + else + mePlayer.Volume = 1; + + mePlayer.Play(); + } + + private void MePlayer_MediaOpened(object sender, RoutedEventArgs e) + { + + } + + public void MutePlayer(bool val) + { + if (val) + mePlayer.Volume = 0; + else + mePlayer.Volume = 1; + } + + public void PausePlayer() + { + mePlayer.Pause(); + } + + public void PlayMedia() + { + mePlayer.Play(); + } + + public void StopPlayer() + { + mePlayer.Stop(); + } + + private void MePlayer_MediaFailed(object sender, WPFMediaKit.DirectShow.MediaPlayers.MediaFailedEventArgs e) + { + Logger.Error("Mediakit Playback Failure: " + e.Exception.ToString()); + if (e.Exception.HResult != -2147467261) //nullreference error(when mediaload fails), otherwise double error message!. + { + System.Windows.MessageBox.Show(Properties.Resources.msgMediakitFailure + "\n\nError:\n" + e.Message, Properties.Resources.txtLivelyErrorMsgTitle); + } + + } + + private void MePlayer_MediaEnded(object sender, RoutedEventArgs e) + { + //mePlayer.MediaPosition = 0; + //mePlayer.Play(); + } + + private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + mePlayer.MediaFailed -= MePlayer_MediaFailed; + mePlayer.MediaEnded -= MePlayer_MediaEnded; + mePlayer.MediaOpened -= MePlayer_MediaOpened; + + mePlayer.Stop(); + mePlayer.Source = null; + mePlayer.Close(); + } + + //prevent mouseclick focus steal(bottom-most wp rendering mode. + protected override void OnSourceInitialized(EventArgs e) + { + base.OnSourceInitialized(e); + var source = PresentationSource.FromVisual(this) as HwndSource; + source.AddHook(WndProc); + } + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); + } + else + { + return IntPtr.Zero; + } + } + private const int WM_MOUSEACTIVATE = 0x0021; + private const int MA_NOACTIVATE = 0x0003; + } +}