├── .gitignore ├── LICENSE ├── README.md ├── doc ├── Package.xmp ├── design-ideas.xmind ├── media │ ├── memes.zip │ └── stackoverflow.png └── wow-such-mindmap.xmind ├── etc ├── deploy │ ├── bin │ │ ├── etc │ │ │ ├── common.sh │ │ │ └── config.sh │ │ ├── wow │ │ ├── wow-debug │ │ ├── wow.cmd │ │ └── wow.vbs │ └── media │ │ └── Doge.png ├── get-nuget └── make_build.py └── src └── csharp └── Wow ├── Common ├── Common.csproj ├── DSP │ ├── Complex.cs │ ├── HackRFSignal.cs │ └── ISignal.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Controls ├── Basic │ ├── ChooseOrEnterValue.Designer.cs │ ├── ChooseOrEnterValue.cs │ ├── ChooseOrEnterValue.resx │ ├── DoubleBufferedPanel.Designer.cs │ ├── DoubleBufferedPanel.cs │ ├── DoubleBufferedUserControl.Designer.cs │ ├── DoubleBufferedUserControl.cs │ ├── GradientPanel.Designer.cs │ └── GradientPanel.cs ├── BasicGL │ ├── GLView.Designer.cs │ └── GLView.cs ├── Controls.csproj ├── Properties │ └── AssemblyInfo.cs ├── Visualization │ ├── Spectrogram.Designer.cs │ ├── Spectrogram.cs │ └── Spectrogram.resx └── packages.config ├── Tools ├── nuget └── nuget.exe ├── Utility ├── Properties │ └── AssemblyInfo.cs ├── Util.cs └── Utility.csproj ├── Visualizer ├── App.config ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Visualizer.csproj └── packages.config └── Wow.sln /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # ignore the build dir. 3 | # 4 | /build/ 5 | 6 | # 7 | # ignore Visual Studio user prefs and build files. 8 | # 9 | *.suo 10 | *.userprefs 11 | /src/**/obj/ 12 | /src/**/[Bb]in 13 | /src/**/[Dd]ebug*/ 14 | /src/**/[Rr]elease*/ 15 | /src/**/Packages/ 16 | 17 | # 18 | # ignore some binary files. 19 | # 20 | /doc/images/ 21 | /doc/media/memes/ 22 | /doc/wow.png 23 | 24 | 25 | # 26 | # ignore packaging tempfiles. 27 | # 28 | /temp.c 29 | /temp.s 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 strayptr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ### [git.io/wow](https://git.io/wow) - signal visualizer 3 | 4 | `wow` (pronounced "[![Doge](https://git.io/Doge)](//git.io/memes)") is 5 | a tool for viewing and analyzing radio signals captured by SDR platforms such as 6 | the [HackRF](https://github.com/mossmann/hackrf) via 7 | `hackrf_transfer`. 8 | 9 | A secondary objective of the project is to serve as a learning tool. 10 | If you're into SDR, or you're curious about how to write a 11 | cross-platform GUI app, hopefully something in here might be useful 12 | to you. 13 | 14 | 15 | ### license 16 | 17 | MIT. Use the code however you want. Take it and build at least n - 1 18 | companies with it. 19 | [![BloodTrail](https://git.io/BloodTrail)](//git.io/memes) 20 | 21 | ### okay 22 | 23 | Currently the software is in pre-alpha. In fact, it does nothing 24 | whatsoever except display a blank form. (Though if you happen to live 25 | in a faraday cage, this visualization might not be entirely 26 | inaccurate.) 27 | 28 | Eventually you'll be able to analyze signal files by running `wow 29 | some-signal-recording.iq`, where `some-signal-recording.iq` is filled 30 | with quadrature samples from `hackrf_transfer`. Someday it might be 31 | able to analyze most types of signal files including wav files, etc, 32 | but the first goal is to produce something minimally useful for the 33 | HackRF community. 34 | 35 | `wow` is cross-platform. It was designed from the ground up to run 36 | pretty much anywhere that runs `mono` or Windows. I'm very interested 37 | in getting it working on BSD, but I have no experience with BSD# yet. 38 | It'd be pretty sweet if anyone could help me figure out this part, but 39 | unfortunately I have nothing to reward you with except some dry humor, 40 | an honorary mention in an exclusive "Credits" section (so exclusive it 41 | doesn't even exist yet), and my eternal gratitude (which sadly isn't 42 | edible.) 43 | 44 | **I'd be very grateful** if you'd try out `wow` and verify it runs on 45 | your platform, in spite of the fact that it doesn't do anything useful 46 | yet. If there are any pain points during the install process, please 47 | let me know. (See 'installation' section below.) Also let me know if 48 | it's not completely painless to build it from source. (See 'build' 49 | section below.) 50 | 51 | I've often noticed that some software projects can be extremely tricky 52 | to build from source, depending on your platform, so I'm trying to 53 | make "it's a pleasure to build this from source!" a first-class 54 | feature from the very beginning of this project. Maybe it'll 55 | encourage people to tinker with the code or submit a pull request. 56 | 57 | The current plan is to get a basic spectrogram visualizater up and 58 | running as quickly as possible, choosing to release one tiny feature 59 | at a time in rapid succession. I intend to follow [GitHub 60 | Flow](https://guides.github.com/introduction/flow/); in particular, 61 | the `master` branch should always contain working code, and feature 62 | additions should be small and frequent. Release whenever a feature 63 | has been added and it hasn't broken anything. 64 | 65 | --- 66 | 67 | ### installation step 1 - preparing for your `wow` 68 | 69 | Install the dependencies for your platform: 70 | 71 | #### windows dependencies 72 | 73 | Pop open a beer, 'cause there ain't no thang for you to do but to head 74 | down to installation step 2. Scroll down like it's 1968! 75 | 76 | 77 | #### ubuntu / debian dependencies 78 | 79 | Paste this into your terminal: 80 | 81 | ```bash 82 | 83 | cat <<'EOF' > wow_such_debian.sh 84 | 85 | # update your sources. 86 | sudo apt-get update 87 | 88 | # install git and checkout the repo. 89 | sudo apt-get install git -y 90 | 91 | # install realpath. 92 | sudo apt-get install realpath -y 93 | 94 | # install Mono. Time to go grab a cup of coffee Kappa 95 | sudo apt-get install mono-complete -y 96 | 97 | # install build dependencies. 98 | sudo apt-get install build-essential libc6-dev-i386 -y 99 | 100 | EOF 101 | 102 | # install the dependencies. 103 | bash ./wow_such_debian.sh; 104 | 105 | ``` 106 | 107 | 108 | 109 | #### os x dependencies 110 | 111 | Paste this into a Terminal window: 112 | 113 | ```bash 114 | 115 | cat <<'EOF' > wow_such_osx.sh 116 | 117 | # sudo privs will be required later for brew cask. 118 | sudo echo 119 | 120 | # install Homebrew. http://brew.sh 121 | if [ -z "`which brew`" ]; then 122 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"; 123 | fi 124 | 125 | # update Homebrew. 126 | brew update 127 | 128 | # install `realpath` 129 | if [ -z "`which realpath`" ]; then 130 | brew tap strayptr/tap 131 | brew install realpath 132 | fi 133 | 134 | # install `git` 135 | if [ -z "`which git`" ]; then brew install git; fi 136 | 137 | # install `mono`. 138 | if [ -z "`which mono`" ]; then 139 | # we also need libgdiplus, which doesn't come with `brew install 140 | # mono`. See https://github.com/Homebrew/homebrew/pull/34973 141 | # Let's install mono from `brew cask` instead. 142 | 143 | # install cask, the brew binary package manager. 144 | brew install caskroom/cask/brew-cask 145 | 146 | # install the full mono-mdk from cask. 147 | brew cask install mono-mdk 148 | fi 149 | 150 | EOF 151 | 152 | # install the dependencies. 153 | bash ./wow_such_osx.sh; 154 | 155 | ``` 156 | 157 | - 158 | 159 | ### installation step 2 - choosing your `wow` 160 | 161 | Go to the Releases page 162 | ([https://git.io/wow-many-release](//git.io/wow-many-release)) and 163 | download the latest archive, such as 164 | [wow-v0.0.1.tar.gz](https://github.com/strayptr/wow/releases/download/v0.0.1-alpha/wow-0.0.1.tar.gz). 165 | 166 | - Extract the archive, which produces a folder structure like 167 | `wow-0.0.1/wow/...` 168 | 169 | (Note: If https://git.io/wow-many-release doesn't suit your tastes, a 170 | number of alternatives have been prepared): 171 | - [https://git.io/wow-such-release](//git.io/wow-such-release) 172 | - [https://git.io/wow-very-releases](//git.io/wow-very-releases) 173 | - [https://git.io/wow-releases](//git.io/wow-releases) 174 | 175 | ### installation step 3 - exercising your `wow` 176 | 177 | - To launch the visualizer, navigate to `wow-0.0.1/wow/bin` and double 178 | click on `wow` (or `wow.cmd` on Windows). 179 | 180 | (Or run `wow-0.0.1/wow/bin/wow` in a terminal window or a cmd.exe 181 | window. Same thing.) 182 | 183 | ### installation step 4 (optional) - housing your `wow` 184 | 185 | The folder you got from the archive file is portable, i.e. `bin/wow` 186 | will probably run properly no matter where you put it or how you 187 | launch it. So feel free to put it wherever you want; just add the 188 | subfolder `wow/bin` to your PATH. 189 | 190 | Eventually there will probably be some snazzy installer with snazzy 191 | installer features, but in the meantime here's some boilerplate 192 | recipes. 193 | 194 | To install `wow`: 195 | 196 | **Linux** users: Copy `wow-x.y.z/wow` to `/usr/local/wow` then add the 197 | bin folder to your PATH: `export PATH="$PATH:/usr/local/wow/bin"`. 198 | Now you can run `wow` from anywhere. Thrilling. 199 | 200 | **Windows** users: Create a shortcut to `wow.cmd` on your desktop. 201 | Name it something like `help im trapped in a shortcut factory`. You 202 | could also add `C:\wow-0.0.1\wow\bin` to your PATH if you want to 203 | launch wow from a cmd.exe terminal (assuming you extracted the release 204 | archive to `C:\`). 205 | 206 | ### build from source 207 | 208 | **Install the dependencies** via **installation step 1** above. It 209 | includes everything you need to build from source. 210 | 211 | Paste this into your terminal: 212 | 213 | ```bash 214 | 215 | # get the code. 216 | git clone https://github.com/strayptr/wow && cd wow 217 | 218 | # build the project, then switch to the output folder it generated. 219 | etc/make_build.py && cd build/wow-such-signal 220 | 221 | ``` 222 | 223 | If there were no build errors, you'll end up inside a folder path like 224 | `build/wow-such-signal`. The `wow-such-signal` folder is analogous 225 | to the folder you'd get from extracting a release archive, like 226 | `wow-v0.0.1/`. It's a self-contained directory structure which can 227 | be copied anywhere else and has no external dependencies, i.e. it's 228 | a portable installation. 229 | 230 | Really, I'm making it sound more complicated than it is: just run 231 | `wow/bin/wow` in your terminal and the visualizer should launch. 232 | 233 | Now you can **goto installation step 3** above and pretend like it's 234 | the folder you got from a release archive. 235 | 236 | -- 237 | 238 | The process of making an actual release is exactly the same, except 239 | you pass in a version number: 240 | 241 | - run `etc/make_build.py --version x.y.z` where x/y/z are 242 | major/minor/revision versions. This will produce a 243 | `build/wow-x.y.z.tar.gz` file. 244 | 245 | - create a [GitHub 246 | release](https://github.com/blog/1547-release-your-software) and 247 | attach the `wow-x.y.z.tar.gz` file. 248 | 249 | -- 250 | 251 | This README is probably way too long and wordy, but, with apologies, 252 | at this point I think I should stop trying to write READMEs / build 253 | methodologies and start writing useful signal analysis code. 254 | 255 | -- 256 | 257 | Pull requests welcome! I'd be like 258 | [![PogChamp](https://git.io/PogChamp)](//git.io/memes) 259 | 260 | 261 | ### mindmap 262 | 263 | We use [XMind](https://www.xmind.net/) to keep track of notes, 264 | ideas, design decisions, cornercase troubleshooting issues, etc. 265 | 266 | Current mindmap: 267 | 268 | ![Mindmap](http://i.imgur.com/ZBz2lyn.jpg) 269 | 270 | -------------------------------------------------------------------------------- /doc/Package.xmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/doc/Package.xmp -------------------------------------------------------------------------------- /doc/design-ideas.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/doc/design-ideas.xmind -------------------------------------------------------------------------------- /doc/media/memes.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/doc/media/memes.zip -------------------------------------------------------------------------------- /doc/media/stackoverflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/doc/media/stackoverflow.png -------------------------------------------------------------------------------- /doc/wow-such-mindmap.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/doc/wow-such-mindmap.xmind -------------------------------------------------------------------------------- /etc/deploy/bin/etc/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This file is meant to be sourced by your own shell scripts, for 4 | # example: 5 | # 6 | # source etc/common.sh 7 | # 8 | 9 | #============================================================================== 10 | # Provide some useful bash utility functions. 11 | #============================================================================== 12 | 13 | #------------------------------------------------------------------------------ 14 | # Provide `echoerr`, a way to echo to stderr. Example usage: 15 | # 16 | # if [ -e "filename.txt" ]; then 17 | # echoerr "filename.txt not found" 18 | # exit 1 19 | # fi 20 | # 21 | # see http://stackoverflow.com/questions/2990414/echo-that-outputs-to-stderr 22 | #------------------------------------------------------------------------------ 23 | echoerr() { >&2 echo "$@"; } 24 | 25 | # provide a variant that prefixes the msg with the script's filepath. 26 | echoerr2() { >&2 echo "$ScriptParent/$ScriptName: $@"; } 27 | 28 | #------------------------------------------------------------------------------ 29 | # Provide `panic`, a way to exit after printing an error to stderr. 30 | # Example usage: 31 | # 32 | # if [ -z "$var" ]; then 33 | # panic $LINENO "\$var isn't set." 34 | # fi 35 | #------------------------------------------------------------------------------ 36 | panic() 37 | { 38 | local filename=$(basename "$ScriptPath") 39 | local line_number=$1; shift 1 40 | local msg=$@ 41 | 42 | #echo "[$filename:$line_number]: $msg" 1>&2 43 | >&2 echo "`basename \"$ScriptPath\"`/$ScriptName: $@" 44 | exit 1 45 | } 46 | 47 | #------------------------------------------------------------------------------ 48 | # Provide `echovars`, a way to print a list of variables for testing 49 | # purposes. 50 | #------------------------------------------------------------------------------ 51 | echovars() 52 | { 53 | for var in $@; do 54 | echo "$var=${!var}" 55 | done 56 | } 57 | 58 | #------------------------------------------------------------------------------ 59 | # Provide `depends_on`, a way for a script to provide a list of 60 | # variable names and fail if any of the variables aren't set. 61 | #------------------------------------------------------------------------------ 62 | depends_on() 63 | { 64 | for var in $@; do 65 | # see http://unix.stackexchange.com/questions/41292/variable-substitution-with-an-exclamation-mark-in-bash/41293#41293 66 | if [ -z "${!var}" ] ; then 67 | echoerr2 "\$$var is blank." 68 | exit 1 69 | fi 70 | done 71 | } 72 | 73 | 74 | #============================================================================== 75 | # This script relies on realpath, so verify that it's installed and 76 | # suggest ways of installing it. 77 | #============================================================================== 78 | if [ -z "`which realpath`" ]; then 79 | echoerr "realpath isn't installed." 80 | echoerr "" 81 | echoerr " On Debian-based systems (Ubuntu, etc) try: " 82 | echoerr " sudo apt-get install realpath" 83 | echoerr "" 84 | echoerr " On OS X, install Homebrew and then run:" 85 | echoerr " brew update" 86 | echoerr " brew tap strayptr/tap" 87 | echoerr " brew install realpath" 88 | exit 1 89 | fi 90 | 91 | #============================================================================== 92 | # Provide the following two variables: 93 | # 94 | # $ScriptPath - This is the absolute path to the directory 95 | # containing the current script. 96 | # 97 | # $ScriptName - The filename of the current script. 98 | # 99 | # $ScriptParent - The name of the parent directory of the current 100 | # script. (Useful in error messages.) 101 | # 102 | #============================================================================== 103 | 104 | # get the full path to the current scriptfile in a way that won't 105 | # break if the path contains spaces. 106 | ScriptPath="`realpath \"$0\"`" 107 | ScriptName="`basename \"$ScriptPath\"`" 108 | ScriptPath="`dirname \"$ScriptPath\"`" 109 | ScriptParent="`basename \"$ScriptPath\"`" 110 | 111 | # ensure that neither variable is blank. This is important in case 112 | # someone runs a command like `rm -rf $ScriptPath/etc`. See 113 | # https://github.com/valvesoftware/steam-for-linux/issues/3671 114 | depends_on ScriptPath ScriptName 115 | 116 | #============================================================================== 117 | # Load our project's global settings from "config.sh". 118 | #============================================================================== 119 | 120 | # try to source the config from our directory. 121 | if [ -e "$ScriptPath/config.sh" ]; then 122 | source "$ScriptPath/config.sh" 123 | fi 124 | 125 | # also try to source the config from our parent directory. This 126 | # enables organizing your project's scriptfiles into paths like 127 | # `etc/utils/foo.sh`, `etc/build/compile.sh`, etc, while keeping your 128 | # config file at `etc/config.sh`. 129 | if [ -e "$ScriptPath/../config.sh" ]; then 130 | source "$ScriptPath/../config.sh" 131 | fi 132 | 133 | #============================================================================== 134 | # Determine the platform. 135 | #============================================================================== 136 | SystemPlatform=`uname` 137 | unamestr=`uname` 138 | 139 | -------------------------------------------------------------------------------- /etc/deploy/bin/etc/config.sh: -------------------------------------------------------------------------------- 1 | 2 | ProjectName=wow 3 | ProjectVersion=0.0.1 4 | 5 | -------------------------------------------------------------------------------- /etc/deploy/bin/wow: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include common functionality. 4 | source "`dirname "$BASH_SOURCE"`/etc/common.sh" 5 | 6 | #============================================================================== 7 | # Fail if any of our required vars are missing. 8 | #============================================================================== 9 | depends_on \ 10 | ScriptPath 11 | 12 | #============================================================================== 13 | # If mono isn't installed, alert the user. 14 | #============================================================================== 15 | if [[ -z "`which mono`" ]]; then 16 | echo "mono isn't installed." 17 | echo "\tOS X: try running \`brew install mono\`" 18 | echo "\tLinux: try running \`sudo apt-get install mono-complete\`" 19 | exit 1 20 | fi 21 | 22 | #============================================================================== 23 | # Execute the visualizer, passing in any commandline args. 24 | #============================================================================== 25 | if [[ "$SystemPlatform" == 'Linux' ]]; then 26 | mono "$ScriptPath/x86/Visualizer/Visualizer.exe" $* 27 | else 28 | "$ScriptPath/x86/Visualizer/Visualizer" $* 29 | fi 30 | 31 | 32 | -------------------------------------------------------------------------------- /etc/deploy/bin/wow-debug: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # include common functionality. 4 | source "`dirname "$BASH_SOURCE"`/etc/common.sh" 5 | 6 | MONO_LOG_LEVEL=debug "$ScriptPath/wow" "$@" 7 | 8 | -------------------------------------------------------------------------------- /etc/deploy/bin/wow.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | :: get the scriptfile's path. 5 | SET scriptdir=%~dp0 6 | 7 | :: execute the visualizer, passing in any commandline args. 8 | start "" "%scriptdir%/x86/Visualizer/Visualizer.exe" %* 9 | 10 | -------------------------------------------------------------------------------- /etc/deploy/bin/wow.vbs: -------------------------------------------------------------------------------- 1 | Set fso = CreateObject("Scripting.FileSystemObject") 2 | 3 | Set objFile = fso.GetFile(Wscript.ScriptFullName) 4 | strFolder = fso.GetParentFolderName(objFile) 5 | strPath = strFolder & "\\wow.cmd" 6 | 7 | CreateObject("Wscript.Shell").Run strPath, 0, True 8 | 9 | -------------------------------------------------------------------------------- /etc/deploy/media/Doge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/etc/deploy/media/Doge.png -------------------------------------------------------------------------------- /etc/get-nuget: -------------------------------------------------------------------------------- 1 | # fetch nuget.exe. 2 | wget https://nuget.org/nuget.exe 3 | 4 | -------------------------------------------------------------------------------- /etc/make_build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import os, errno 5 | import fnmatch 6 | import shutil 7 | import tarfile 8 | import platform 9 | 10 | #============================================================================== 11 | # Constants 12 | #============================================================================== 13 | ProgramName = "wow" 14 | 15 | #============================================================================== 16 | # Functionality 17 | #============================================================================== 18 | 19 | import re 20 | WS = re.compile(r'\s+', re.MULTILINE) 21 | 22 | def contains_whitespace(x): 23 | return WS.search(x) 24 | 25 | def quot(x): 26 | #return ("%s" % x) if contains_whitespace(x) else x 27 | return WS.sub('\\ ', x) if contains_whitespace(x) else x 28 | 29 | # http://stackoverflow.com/questions/595305/python-path-of-script 30 | def scriptpath(): 31 | """ 32 | Returns the absolute path of the current scriptfile. 33 | """ 34 | return os.path.realpath(__file__) 35 | 36 | def projectpath(): 37 | """ 38 | Returns the absolute path to our project's root directory, with 39 | the assumption that this script file is underneath 40 | '$projectpath/etc/' and that the script will never be located 41 | within a nested folder named 'etc', e.g. this is not allowed: 42 | '$projectpath/etc/foo/etc/script.py' 43 | """ 44 | # get the absolute path to the current scriptfile. 45 | path = scriptpath() 46 | # we're somewhere underneath '$projectpath/etc/*', so traverse up 47 | # until reaching '$projectpath/etc/' 48 | while os.path.basename(path).lower() != 'etc': 49 | # if we've reached /etc or / then our assumptions are 50 | # incorrect. 51 | assert(os.path.normpath(path) not in [os.path.normpath(p) for p in ['/', '/etc']]) 52 | path = os.path.dirname(path) 53 | # traverse up once more to reach our project's root dir. 54 | return os.path.dirname(path) 55 | 56 | def query_yes_no(question, default="yes"): 57 | """Ask a yes/no question via raw_input() and return their answer. 58 | 59 | "question" is a string that is presented to the user. 60 | "default" is the presumed answer if the user just hits . 61 | It must be "yes" (the default), "no" or None (meaning 62 | an answer is required of the user). 63 | 64 | The "answer" return value is True for "yes" or False for "no". 65 | """ 66 | valid = {"yes": True, "y": True, "ye": True, 67 | "no": False, "n": False} 68 | if default is None: 69 | prompt = " [y/n] " 70 | elif default == "yes": 71 | prompt = " [Y/n] " 72 | elif default == "no": 73 | prompt = " [y/N] " 74 | else: 75 | raise ValueError("invalid default answer: '%s'" % default) 76 | 77 | while True: 78 | sys.stdout.write(question + prompt) 79 | choice = raw_input().lower() 80 | if default is not None and choice == '': 81 | return valid[default] 82 | elif choice in valid: 83 | return valid[choice] 84 | else: 85 | sys.stdout.write("Please respond with 'yes' or 'no' " 86 | "(or 'y' or 'n').\n") 87 | 88 | def mkdir_p(path): 89 | try: 90 | os.makedirs(path) 91 | except OSError as exc: # Python >2.5 92 | if exc.errno == errno.EEXIST and os.path.isdir(path): 93 | pass 94 | else: raise 95 | 96 | def subfolders(path): 97 | return [x for x in os.listdir(path) if os.path.isdir(os.path.join(path, x))] 98 | 99 | def match_any(name, patterns): 100 | for pat in patterns: 101 | if fnmatch.fnmatch(name, pat): 102 | return True 103 | return False 104 | 105 | def listdir(path, include=['*'], exclude=[]): 106 | # build a list of all files. 107 | files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))] 108 | # include only the files we care about. 109 | r = [] 110 | for pat in include: 111 | r += fnmatch.filter(files, pat) 112 | r.sort() 113 | files = list(set(r)) 114 | for f in files: 115 | # exclude files we don't care about. 116 | if not match_any(f, exclude): 117 | yield f 118 | # try to copy an executable by the same name, but no 119 | # extension. (The convention I've chosen for a bundled exe.) 120 | if f.lower().endswith('.exe'): 121 | bundle = mkpath(os.path.splitext(os.path.join(path, f))[0]) 122 | if os.path.isfile(bundle): 123 | yield bundle 124 | 125 | def csharp_binfiles(path): 126 | """Return a list of files that should be bundled for a .NET project. 127 | 128 | "path" is a .NET build path like "SlnName/ProjectName/bin/x86/Release" 129 | 130 | """ 131 | if not os.path.isdir(path): 132 | raise Exception("Not a directory: %s" % path) 133 | # types of files we want: 134 | include = [ 135 | # assemblies, 136 | '*.dll', 137 | # executables, 138 | '*.exe', 139 | # and application configuration files (provides 140 | # mono with info about how to run the exe) 141 | '*.exe.config'] 142 | # types of files we don't want: 143 | exclude = [ 144 | # vshost files (created by .NET IDEs for 145 | # debugging purposes) 146 | '*.vshost.*' ] 147 | for f in listdir(path, include=include, exclude=exclude): 148 | yield f 149 | 150 | def getslnpath(slnpath): 151 | # if slnpath is a file, convert it into the dir the file resides in. 152 | if os.path.isfile(slnpath): 153 | slnpath = os.path.dirname(slnpath) 154 | if not os.path.exists(slnpath): 155 | raise Exception("No such sln path: %s" % slnpath) 156 | return slnpath 157 | 158 | def sln_binfiles(slnpath): 159 | slnpath = getslnpath(slnpath) 160 | # for each project subfolder... 161 | for project in subfolders(slnpath): 162 | # yield any project binaries. 163 | for binpath in ['bin/x86/Release']: 164 | path = os.path.join(slnpath, project, binpath) 165 | if os.path.isdir(path): 166 | for binfile in csharp_binfiles(path): 167 | yield ('x86', project, os.path.join(path, binfile)) 168 | 169 | def rmfile(filename): 170 | if os.path.exists(filename): 171 | print 'rm %s' % quot(filename) 172 | os.unlink(filename) 173 | 174 | def rmrfdir(dirpath): 175 | """Extremely dangerous. Use with caution.""" 176 | if os.path.isdir(dirpath): 177 | print 'rm -rf %s' % quot(dirpath) 178 | shutil.rmtree(dirpath) 179 | 180 | def copyfile(src, dst, copymode=True): 181 | print 'cp %s %s' % (quot(src), quot(dst)) 182 | shutil.copyfile(src, dst) 183 | if copymode: 184 | shutil.copymode(src, dst) 185 | 186 | def cp_r(src, dst): 187 | print 'cp -r %s %s' % (quot(src), quot(dst)) 188 | #shutil.copytree(src, dst) # won't work when dst exists, and sadly there's no accepted solution. 189 | for filename in os.listdir(src): 190 | dstp = joinpath(dst, filename) 191 | srcp = joinpath(src, filename) 192 | if os.path.isfile(srcp): 193 | mkdir_p(os.path.dirname(dstp)) 194 | copyfile(srcp, dstp) 195 | elif os.path.isdir(srcp): 196 | cp_r(srcp, dstp) 197 | 198 | def make_tarfile(output_filename, source_dir): 199 | """Build a .tar.gz for an entire directory tree.""" 200 | print 'tar cvzf %s %s/' % ( 201 | quot(os.path.basename(output_filename)), 202 | quot(os.path.basename(source_dir))) 203 | with tarfile.open(output_filename, "w:gz") as tar: 204 | tar.add(source_dir, arcname=os.path.basename(source_dir)) 205 | 206 | # credit to http://stackoverflow.com/questions/1855095/how-to-create-a-zip-archive-of-a-directory 207 | import zipfile 208 | def zipdir(path, ziph): 209 | # ziph is zipfile handle 210 | for root, dirs, files in os.walk(path): 211 | for file in files: 212 | ziph.write(os.path.join(root, file)) 213 | 214 | def make_zipfile(output_filename, source_dir): 215 | """Build a .zip for an entire directory tree.""" 216 | print 'zip %s %s/' % ( 217 | quot(os.path.basename(output_filename)), 218 | quot(os.path.basename(source_dir))) 219 | with zipfile.ZipFile(output_filename, 'w') as zipf: 220 | cwd = os.getcwd() 221 | try: 222 | os.chdir(os.path.dirname(source_dir)) 223 | zipdir(os.path.basename(source_dir), zipf) 224 | finally: 225 | os.chdir(cwd) 226 | 227 | def sln_deploy(dst, slnpath): 228 | slnpath = getslnpath(slnpath) 229 | if not os.path.isdir(dst): 230 | raise Exception("Not a directory: %s" % dst) 231 | # deploy each binary. 232 | for platform, project, binfile in sln_binfiles(slnpath): 233 | filename = os.path.basename(binfile) 234 | path = os.path.join(dst, 'bin', platform, project) 235 | mkdir_p(path) 236 | copyfile(binfile, os.path.join(path, filename)) 237 | 238 | def etc_deploy(dst, etcpath): 239 | # recursively copy 'etc/deploy/*' to '$prefix/$vername/$ProgramName/' 240 | cp_r(os.path.join(etcpath, 'deploy'), dst) 241 | 242 | #============================================================================== 243 | # Cmdline 244 | #============================================================================== 245 | import argparse 246 | 247 | parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 248 | description=""" 249 | TODO 250 | """) 251 | 252 | parser.add_argument('-p', '--prefix', 253 | default="build", 254 | help="The destination where the binaries will be placed." ) 255 | 256 | parser.add_argument('-s', '--sourcedir', 257 | default="src/csharp/Wow", 258 | help="The directory containing the project's code." ) 259 | 260 | parser.add_argument('-e', '--etcdir', 261 | default="etc", 262 | help="The directory containing other deployment files." ) 263 | 264 | parser.add_argument('-v', '--version', 265 | default="such-signal", 266 | help="Append the deployment tarball with a version number, such as v0.0.01" ) 267 | 268 | 269 | #============================================================================== 270 | # Main 271 | #============================================================================== 272 | 273 | def joinpath(*args): 274 | return os.path.normpath(os.path.join(*args)) 275 | 276 | def mkpath(childpath): 277 | return os.path.normpath(os.path.join(projectpath(), childpath)) 278 | 279 | def joincmd(*args): 280 | return ' \\\n'.join(args) 281 | 282 | def bundle(): 283 | # windows can't build bundles. 284 | if platform.system().lower() == 'windows': 285 | return 286 | # bundle everything together. 287 | cmd = [] 288 | flags = '' 289 | if platform.system().lower() == 'darwin': 290 | flags += ' -framework CoreFoundation -lobjc -liconv' 291 | cmd += ['PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig/'] 292 | if platform.system().lower() == 'darwin': 293 | cmd += ['CC="cc -m32 -arch i386 %s"' % flags] 294 | cmd += ['AS="as -arch i386"'] 295 | else: 296 | cmd += ['CC="cc -m32 %s"' % flags] 297 | cmd += ['AS="as -32 -march i386"'] 298 | path = quot(mkpath('src/csharp/Wow/Visualizer/bin/x86/Release')) 299 | cmd += ['mkbundle --deps --static'] 300 | cmd += ['%s/Visualizer.exe' % path] 301 | cmd += ['%s/*.dll' % path] 302 | cmd += ['-o %s/Visualizer' % path] 303 | cmd = joincmd(*cmd) 304 | print cmd 305 | os.system(cmd) 306 | 307 | def gen_binaries(): 308 | slnpath = mkpath('src/csharp/Wow/Wow.sln') 309 | os.system('xbuild /p:Configuration=Release "%s"' % slnpath) 310 | bundle() 311 | 312 | def gen_build(): 313 | # build the destination directory path. 314 | vername = '%s-%s' % (ProgramName, args.version) 315 | # build the deployment tarball name. 316 | tarball = os.path.join(args.prefix, '%s.tar.gz' % vername) 317 | zipfile = os.path.join(args.prefix, '%s.zip' % vername) 318 | # build the base path. 319 | base = os.path.join(args.prefix, vername) 320 | base = os.path.normpath(base) 321 | # if the destination directory already exists, ask the user 322 | # whether it's okay to delete it. (WARNING: This is a very 323 | # dangerous operation, equivalent to rm -rf, so we need to think 324 | # carefully about how it's used in order to protect the user. In 325 | # this case, we're going to create a subfolder in the prefix path, 326 | # and only that subfolder will ever be deleted, not the prefix 327 | # path itself.) 328 | if os.path.exists(base): 329 | if not query_yes_no(""""%s" already exists. Okay to delete?""" % base, default="no"): 330 | sys.exit(1) 331 | rmrfdir(base) 332 | # delete the tarball if it exists. 333 | rmfile(tarball) 334 | rmfile(zipfile) 335 | dst = os.path.join(base, ProgramName) 336 | # create the destination dir. 337 | mkdir_p(dst) 338 | # deploy sln binaries. 339 | sln_deploy(dst, args.sourcedir) 340 | # recursively copy the contents of the 'etc/bin' folder '$prefix/$vername/$ProgramName/bin' 341 | etc_deploy(dst, args.etcdir) 342 | # build the deployment tarball. 343 | print 'cd %s' % quot(os.path.dirname(base)) 344 | if os.path.exists(tarball): 345 | raise Exception("Tarball already exists: %s" % tarball) 346 | make_tarfile(tarball, base) 347 | if os.path.exists(zipfile): 348 | raise Exception("Zipfile already exists: %s" % zipfile) 349 | make_zipfile(zipfile, base) 350 | 351 | def main(): 352 | gen_binaries() 353 | gen_build() 354 | 355 | if __name__ == "__main__": 356 | args = parser.parse_args() 357 | main() 358 | 359 | -------------------------------------------------------------------------------- /src/csharp/Wow/Common/Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {77AABEE0-2C4B-488B-8B2E-CB07298572DC} 8 | Library 9 | Properties 10 | Common 11 | Common 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | bin\x86\Debug\ 19 | DEBUG;TRACE 20 | true 21 | full 22 | x86 23 | prompt 24 | MinimumRecommendedRules.ruleset 25 | 26 | 27 | bin\x86\Release\ 28 | TRACE 29 | true 30 | true 31 | pdbonly 32 | x86 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | $(SolutionDir)Tools\nuget install $(ProjectDir)packages.config -o $(SolutionDir)Packages 54 | 55 | 62 | -------------------------------------------------------------------------------- /src/csharp/Wow/Common/DSP/Complex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common.DSP 8 | { 9 | public struct Complex 10 | { 11 | public float Re; 12 | public float Im; 13 | 14 | public Complex(float re, float im) 15 | { 16 | Re = re; 17 | Im = im; 18 | } 19 | 20 | public static void FromUInt8Complex( 21 | Complex[] dst, long dstOffset, 22 | byte[] src, long srcOffset, long srcNumBytes) 23 | { 24 | long at = dstOffset; 25 | for (long i = srcOffset; i < srcOffset + srcNumBytes; i += 2, at++) 26 | { 27 | dst[at].Re = (src[i] / 256.0f) * 2.0f - 1.0f; 28 | dst[at].Im = (src[i+1] / 256.0f) * 2.0f - 1.0f; 29 | } 30 | } 31 | 32 | public static unsafe void FromInt8Complex( 33 | Complex[] dst, long dstOffset, 34 | byte[] src, long srcOffset, long srcNumBytes) 35 | { 36 | fixed (byte* p = src) 37 | { 38 | sbyte* psrc = (sbyte*)p; 39 | long at = dstOffset; 40 | for (long i = srcOffset; i < srcOffset + srcNumBytes; i += 2, at++) 41 | { 42 | dst[at].Re = ((psrc[i] + 128) / 256.0f) * 2.0f - 1.0f; 43 | dst[at].Im = ((psrc[i + 1] + 128) / 256.0f) * 2.0f - 1.0f; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/csharp/Wow/Common/DSP/HackRFSignal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | 8 | namespace Common.DSP 9 | { 10 | public class HackRFSignal : ISignal 11 | { 12 | public struct Settings 13 | { 14 | public int Frequency; 15 | public int SamplesPerSec; 16 | } 17 | 18 | static int BytesPerSample = 2; 19 | 20 | Settings _settings; 21 | string _filepath; 22 | FileStream _stream; 23 | byte[] _samplesCache; 24 | 25 | public HackRFSignal(HackRFSignal.Settings settings, string filepath) 26 | { 27 | _settings = settings; 28 | _filepath = filepath; 29 | _stream = File.OpenRead(filepath); 30 | _samplesCache = new byte[BytesPerSample * 1024]; 31 | } 32 | 33 | public int SamplesPerSec 34 | { 35 | get { return _settings.SamplesPerSec; } 36 | } 37 | 38 | public long NumSamples 39 | { 40 | get { return (_stream.Length / BytesPerSample); } 41 | } 42 | 43 | public long Position 44 | { 45 | get { return (_stream.Position / BytesPerSample); } 46 | } 47 | 48 | public void Seek(long sampleIdx) 49 | { 50 | _stream.Seek(BytesPerSample * sampleIdx, SeekOrigin.Begin); 51 | } 52 | 53 | public unsafe long ReadSamples(Complex[] dstSamples, long dstOffset, long numSamples) 54 | { 55 | long remainingSamples = (this.NumSamples - this.Position); 56 | long count = Math.Min(numSamples, remainingSamples); 57 | long stepBy = (_samplesCache.Length / BytesPerSample); 58 | 59 | for (; count > 0; count -= stepBy) 60 | { 61 | long n = BytesPerSample * Math.Min(count, stepBy); 62 | if (n <= 0) 63 | break; 64 | 65 | int read = _stream.Read(_samplesCache, 0, (int)n); 66 | read -= (read % 2); 67 | 68 | Complex.FromInt8Complex(dstSamples, dstOffset, _samplesCache, 0, read); 69 | } 70 | 71 | return 0; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/csharp/Wow/Common/DSP/ISignal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Common.DSP 8 | { 9 | public interface ISignal 10 | { 11 | int SamplesPerSec { get; } 12 | long NumSamples { get; } 13 | long Position { get; } 14 | void Seek(long sampleIdx); 15 | 16 | long ReadSamples(Complex[] dst, long dstOffset, long count); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/csharp/Wow/Common/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Common")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Common")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e2ee2dd0-61da-4abe-84d8-e08fc8641802")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Common/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/ChooseOrEnterValue.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Controls.Basic 2 | { 3 | partial class ChooseOrEnterValue 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.tbValue = new System.Windows.Forms.TextBox(); 32 | this.SuspendLayout(); 33 | // 34 | // tbValue 35 | // 36 | this.tbValue.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.tbValue.Location = new System.Drawing.Point(0, 0); 38 | this.tbValue.Name = "tbValue"; 39 | this.tbValue.Size = new System.Drawing.Size(159, 20); 40 | this.tbValue.TabIndex = 0; 41 | // 42 | // ChooseOrEnterValue 43 | // 44 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 45 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 46 | this.Controls.Add(this.tbValue); 47 | this.Name = "ChooseOrEnterValue"; 48 | this.Size = new System.Drawing.Size(159, 24); 49 | this.ResumeLayout(false); 50 | this.PerformLayout(); 51 | 52 | } 53 | 54 | #endregion 55 | 56 | private System.Windows.Forms.TextBox tbValue; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/ChooseOrEnterValue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Controls.Basic 12 | { 13 | public partial class ChooseOrEnterValue: UserControl 14 | { 15 | //----------------------------------------------------------------------------- 16 | public ChooseOrEnterValue() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | //----------------------------------------------------------------------------- 22 | public delegate void ValueChangedHandler(object sender); 23 | public event ValueChangedHandler OnValueChanged; 24 | 25 | //============================================================================= 26 | // Properties 27 | //============================================================================= 28 | 29 | //----------------------------------------------------------------------------- 30 | public string Value 31 | { 32 | get { return tbValue.Text; } 33 | set 34 | { 35 | if (value != tbValue.Text) 36 | { 37 | tbValue.Text = value; 38 | OnValueChanged(this); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/ChooseOrEnterValue.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/DoubleBufferedPanel.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Controls.Basic 2 | { 3 | partial class DoubleBufferedPanel 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | } 33 | 34 | #endregion 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/DoubleBufferedPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Controls.Basic 12 | { 13 | public partial class DoubleBufferedPanel : Panel 14 | { 15 | public DoubleBufferedPanel() 16 | { 17 | InitializeComponent(); 18 | 19 | base.SetStyle(ControlStyles.DoubleBuffer, true); 20 | base.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 21 | base.SetStyle(ControlStyles.UserPaint, true); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/DoubleBufferedUserControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Controls.Basic 2 | { 3 | partial class DoubleBufferedUserControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 33 | } 34 | 35 | #endregion 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/DoubleBufferedUserControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Controls.Basic 12 | { 13 | public partial class DoubleBufferedUserControl : UserControl 14 | { 15 | public DoubleBufferedUserControl() 16 | { 17 | InitializeComponent(); 18 | 19 | base.SetStyle(ControlStyles.DoubleBuffer, true); 20 | base.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 21 | base.SetStyle(ControlStyles.UserPaint, true); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/GradientPanel.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Controls.Basic 2 | { 3 | partial class GradientPanel 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | } 33 | 34 | #endregion 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Basic/GradientPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Data; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace Controls.Basic 13 | { 14 | public partial class GradientPanel : DoubleBufferedPanel 15 | { 16 | //============================================================================= 17 | // Private Variables 18 | //============================================================================= 19 | Control _trackedParent = null; 20 | Control TrackedParent 21 | { 22 | get { return _trackedParent; } 23 | set 24 | { 25 | if (_trackedParent != null) 26 | _trackedParent.Paint -= _trackedParent_Paint; 27 | _trackedParent = value; 28 | if (_trackedParent != null) 29 | _trackedParent.Paint += _trackedParent_Paint; 30 | } 31 | } 32 | 33 | //============================================================================= 34 | // Methods 35 | //============================================================================= 36 | 37 | public GradientPanel() 38 | { 39 | InitializeComponent(); 40 | _gradientColor1 = Color.AliceBlue; 41 | _gradientColor2 = Color.LightSteelBlue; 42 | _border3DStyle = Border3DStyle.RaisedInner; 43 | _dropshadow = true; 44 | } 45 | 46 | //============================================================================= 47 | // Properties 48 | //============================================================================= 49 | 50 | //----------------------------------------------------------------------------- 51 | bool _dropshadow; 52 | [Category("Appearance")] 53 | public bool Dropshadow 54 | { 55 | get { return _dropshadow; } 56 | set 57 | { 58 | _dropshadow = value; 59 | base.Invalidate(); 60 | } 61 | } 62 | 63 | //----------------------------------------------------------------------------- 64 | Color _gradientColor1; 65 | [Category("Appearance")] 66 | public Color GradientColor1 67 | { 68 | get { return _gradientColor1; } 69 | set 70 | { 71 | _gradientColor1 = value; 72 | base.Invalidate(); 73 | } 74 | } 75 | 76 | //----------------------------------------------------------------------------- 77 | Color _gradientColor2; 78 | [Category("Appearance")] 79 | public Color GradientColor2 80 | { 81 | get { return _gradientColor2; } 82 | set 83 | { 84 | _gradientColor2 = value; 85 | base.Invalidate(); 86 | } 87 | } 88 | 89 | //----------------------------------------------------------------------------- 90 | Border3DStyle _border3DStyle; 91 | [Category("Appearance")] 92 | public Border3DStyle Border3DStyle 93 | { 94 | get { return _border3DStyle; } 95 | set 96 | { 97 | _border3DStyle = value; 98 | base.Invalidate(); 99 | } 100 | } 101 | 102 | //============================================================================= 103 | // Events 104 | //============================================================================= 105 | 106 | //----------------------------------------------------------------------------- 107 | protected override void OnPaint(PaintEventArgs e) 108 | { 109 | Graphics g = e.Graphics; 110 | if (Utility.Util.PaintingIsVisible(this, e)) 111 | { 112 | // draw an etched border. 113 | ControlPaint.DrawBorder3D(g, base.ClientRectangle, this.Border3DStyle); 114 | 115 | // if our parent has changed, hook its paint event. 116 | this.TrackedParent = this.Parent; 117 | } 118 | base.OnPaint(e); 119 | } 120 | 121 | //----------------------------------------------------------------------------- 122 | void _trackedParent_Paint(object sender, PaintEventArgs e) 123 | { 124 | Graphics g = e.Graphics; 125 | if (Utility.Util.PaintingIsVisible(this, e)) 126 | { 127 | if (this.Dropshadow) 128 | { 129 | // draw our dropshadow onto the parent control. 130 | Utility.Util.Draw.Dropshadow(g, this); 131 | } 132 | } 133 | } 134 | 135 | //----------------------------------------------------------------------------- 136 | protected override void OnPaintBackground(PaintEventArgs e) 137 | { 138 | Graphics g = e.Graphics; 139 | if (Utility.Util.PaintingIsVisible(this, e)) 140 | { 141 | // draw the gradient from the upper-left corner to the lower- 142 | // right corner, changing from one color to the other. 143 | using (LinearGradientBrush brush = new LinearGradientBrush( 144 | e.ClipRectangle, 145 | this.GradientColor1, this.GradientColor2, 146 | 45.0f)) 147 | { 148 | e.Graphics.FillRectangle(brush, e.ClipRectangle); 149 | return; 150 | } 151 | } 152 | base.OnPaintBackground(e); 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/BasicGL/GLView.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Controls.BasicGL 2 | { 3 | partial class GLView 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | components = new System.ComponentModel.Container(); 32 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 33 | } 34 | 35 | #endregion 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/BasicGL/GLView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using OpenTK; 11 | using OpenTK.Graphics; 12 | using OpenTK.Graphics.OpenGL; 13 | 14 | namespace Controls.BasicGL 15 | { 16 | public partial class GLView : GLControl 17 | { 18 | public GLView() 19 | { 20 | InitializeComponent(); 21 | } 22 | 23 | protected override void OnPaint(PaintEventArgs e) 24 | { 25 | base.OnPaint(e); 26 | 27 | if (!this.DesignMode) 28 | { 29 | MakeCurrent(); 30 | GL.ClearColor(Color.Black); 31 | GL.Clear(ClearBufferMask.ColorBufferBit); 32 | SwapBuffers(); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Controls.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {20235B91-D804-4ECA-9B55-E0FC40725040} 8 | Library 9 | Properties 10 | Controls 11 | Controls 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | bin\x86\Debug\ 19 | DEBUG;TRACE 20 | full 21 | x86 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | 25 | 26 | bin\x86\Release\ 27 | TRACE 28 | true 29 | pdbonly 30 | x86 31 | prompt 32 | MinimumRecommendedRules.ruleset 33 | 34 | 35 | 36 | ..\Packages\OpenTK.1.1.1589.5942\lib\NET40\OpenTK.dll 37 | 38 | 39 | ..\Packages\OpenTK.GLControl.1.1.1589.5942\lib\NET40\OpenTK.GLControl.dll 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | UserControl 54 | 55 | 56 | ChooseOrEnterValue.cs 57 | 58 | 59 | Component 60 | 61 | 62 | DoubleBufferedPanel.cs 63 | 64 | 65 | UserControl 66 | 67 | 68 | DoubleBufferedUserControl.cs 69 | 70 | 71 | Component 72 | 73 | 74 | GradientPanel.cs 75 | 76 | 77 | 78 | UserControl 79 | 80 | 81 | GLView.cs 82 | 83 | 84 | UserControl 85 | 86 | 87 | Spectrogram.cs 88 | 89 | 90 | 91 | 92 | 93 | ChooseOrEnterValue.cs 94 | 95 | 96 | Spectrogram.cs 97 | 98 | 99 | 100 | 101 | {d597f633-7c18-4c8a-b7bd-26468881533c} 102 | Utility 103 | 104 | 105 | 106 | 107 | $(SolutionDir)Tools\nuget install $(ProjectDir)packages.config -o $(SolutionDir)Packages 108 | 109 | 116 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Controls")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Controls")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d5842fbf-5fa7-4d9a-846f-af62d8397ea0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Visualization/Spectrogram.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Controls.Visualization 2 | { 3 | partial class Spectrogram 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.glView1 = new Controls.BasicGL.GLView(); 32 | this.SuspendLayout(); 33 | // 34 | // glView1 35 | // 36 | this.glView1.BackColor = System.Drawing.Color.Black; 37 | this.glView1.Dock = System.Windows.Forms.DockStyle.Fill; 38 | this.glView1.Location = new System.Drawing.Point(0, 0); 39 | this.glView1.Name = "glView1"; 40 | this.glView1.Size = new System.Drawing.Size(294, 280); 41 | this.glView1.TabIndex = 0; 42 | this.glView1.VSync = false; 43 | // 44 | // Spectrogram 45 | // 46 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 48 | this.Controls.Add(this.glView1); 49 | this.Name = "Spectrogram"; 50 | this.Size = new System.Drawing.Size(294, 280); 51 | this.ResumeLayout(false); 52 | 53 | } 54 | 55 | #endregion 56 | 57 | private BasicGL.GLView glView1; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Visualization/Spectrogram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Data; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Controls.Visualization 12 | { 13 | public partial class Spectrogram : UserControl 14 | { 15 | public Spectrogram() 16 | { 17 | InitializeComponent(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/Visualization/Spectrogram.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/csharp/Wow/Controls/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/csharp/Wow/Tools/nuget: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | scriptpath="`dirname "$BASH_SOURCE"`" 3 | 4 | mono "$scriptpath/nuget.exe" $* 5 | 6 | -------------------------------------------------------------------------------- /src/csharp/Wow/Tools/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strayptr/wow/a6bc00fb90631c6af3d8e41410d83de0ccc6a7fe/src/csharp/Wow/Tools/nuget.exe -------------------------------------------------------------------------------- /src/csharp/Wow/Utility/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Utility")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Utility")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c97c4dca-71ba-4472-a61b-3408dd8e2d06")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Utility/Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Drawing; 7 | using System.Drawing.Drawing2D; 8 | using System.Windows.Forms; 9 | 10 | namespace Utility 11 | { 12 | public static class Util 13 | { 14 | //====================================================================== 15 | // math. 16 | //====================================================================== 17 | 18 | //---------------------------------------------------------------------- 19 | public static PointF Add(PointF A, PointF B) 20 | { 21 | return new PointF( 22 | A.X + B.X, 23 | A.Y + B.Y); 24 | } 25 | 26 | //---------------------------------------------------------------------- 27 | public static PointF Subtract(PointF A, PointF B) 28 | { 29 | return new PointF( 30 | A.X - B.X, 31 | A.Y - B.Y); 32 | } 33 | 34 | //---------------------------------------------------------------------- 35 | // constrains a value to be in [min .. max]. 36 | //---------------------------------------------------------------------- 37 | public static float Clamp(float min, float max, float val) 38 | { 39 | // if the programmer said Clamp(max, min, val) instead of the 40 | // expected Clamp(min, max, val), then swap them. There's no reason 41 | // not to. 42 | if (min > max) Swap(ref min, ref max); 43 | 44 | if (val < min) return min; 45 | if (val > max) return max; 46 | return val; 47 | } 48 | 49 | //---------------------------------------------------------------------- 50 | public static float Dot(PointF A, PointF B) 51 | { 52 | return (A.X * B.X) + (A.Y * B.Y); 53 | } 54 | 55 | //---------------------------------------------------------------------- 56 | public static float Distance(float x1, float x2) 57 | { 58 | return Abs(x2 - x1); 59 | } 60 | 61 | //---------------------------------------------------------------------- 62 | public static float DistanceSq(PointF A, PointF B) 63 | { 64 | PointF P = Subtract(B, A); 65 | return Dot(P, P); // "ha ha you said peepee" 66 | } 67 | 68 | //---------------------------------------------------------------------- 69 | public static float Distance(PointF A, PointF B) 70 | { 71 | return Sqrt(DistanceSq(A, B)); 72 | } 73 | 74 | //---------------------------------------------------------------------- 75 | public static Color Invert(Color color) 76 | { 77 | return Color.FromArgb(color.A, 78 | // using base 10 is like sooooo 0x7ce. 79 | 0xff - color.R, 80 | 0xff - color.G, 81 | 0xff - color.B); 82 | } 83 | 84 | //---------------------------------------------------------------------- 85 | // the one, the only, the classic! lerp! now in technicolor. 86 | //---------------------------------------------------------------------- 87 | public static float Lerp(float a, float b, float t) 88 | { 89 | return (((b - a) * t) + a); 90 | } 91 | 92 | //---------------------------------------------------------------------- 93 | public static Color Multiply(Color color, float s) 94 | { 95 | return Color.FromArgb(color.A, 96 | (int)Clamp(0.0f, 255.0f, (color.R * s)), 97 | (int)Clamp(0.0f, 255.0f, (color.G * s)), 98 | (int)Clamp(0.0f, 255.0f, (color.B * s))); 99 | } 100 | 101 | //---------------------------------------------------------------------- 102 | public static PointF Negate(PointF P) 103 | { 104 | return new PointF(-P.X, -P.Y); 105 | } 106 | 107 | //---------------------------------------------------------------------- 108 | // hides the ugly type conversions. I wonder why Math.* doesn't contain 109 | // overloads for float types... 110 | //---------------------------------------------------------------------- 111 | public static float Abs(float x) { return (float)Math.Abs((double)x); } 112 | public static float Abs(double x) { return (float)Math.Abs(x); } 113 | public static float Sqrt(float x) { return (float)Math.Sqrt((double)x); } 114 | public static float Sqrt(double x) { return (float)Math.Sqrt(x); } 115 | 116 | //====================================================================== 117 | // drawing utils. 118 | //====================================================================== 119 | 120 | //---------------------------------------------------------------------- 121 | public static RectangleF Add(RectangleF rect, PointF offset) 122 | { 123 | PointF pos = Add(rect.Location, offset); 124 | return new RectangleF(pos, rect.Size); 125 | } 126 | public static RectangleF Translate(RectangleF rect, PointF offset) 127 | { 128 | return Add(rect, offset); 129 | } 130 | 131 | //---------------------------------------------------------------------- 132 | public static RectangleF Add(RectangleF rect, 133 | float top, float bottom, float left, float right) 134 | { 135 | return RectFromSides( 136 | rect.Top + top, 137 | rect.Bottom + bottom, 138 | rect.Left + left, 139 | rect.Right + right); 140 | } 141 | 142 | //---------------------------------------------------------------------- 143 | // Occasionally, the result of some sequence of operations is actually 144 | // 1px larger than you need. Not for any bad reason, just because of 145 | // a similar thing as http://en.wikipedia.org/wiki/Off-by-one_error#Fencepost_error 146 | // 147 | // (When you're working with pixels, sometimes you're "counting fenceposts," 148 | // and other times you're "counting sections." This function is used 149 | // when you need to convert from 'fenceposts' to 'sections'.") 150 | //---------------------------------------------------------------------- 151 | public static RectangleF AdjustRectForDrawing(RectangleF rect) 152 | { 153 | return new RectangleF( 154 | rect.Location, 155 | new SizeF(rect.Width - 1.0f, rect.Height - 1.0f)); 156 | } 157 | //---------------------------------------------------------------------- 158 | // represents a rect as a closed set of connected points, starting 159 | // from its upper-right corner and going anticlockwise. 160 | // 161 | // (useful for getting the border of a rect as a GraphicsPath, which 162 | // can then be used for e.g. drawing its dropshadow.) 163 | //---------------------------------------------------------------------- 164 | public static PointF[] BorderOf(RectangleF rect) 165 | { 166 | rect = Unpretzel(rect); 167 | return new PointF[] 168 | { 169 | new PointF(rect.Right, rect.Top), 170 | new PointF(rect.Left, rect.Top), 171 | new PointF(rect.Left, rect.Bottom), 172 | new PointF(rect.Right, rect.Bottom), 173 | new PointF(rect.Right, rect.Top) 174 | }; 175 | } 176 | // an alias for getting the border of a control. 177 | public static PointF[] BorderOf(Control control) 178 | { 179 | // get the control's rectangle. 180 | RectangleF rect = Worldspace(control); 181 | 182 | // subtract 1px from its right and bottom sides. 183 | // In other words, move its right side <--- that way by 1px, 184 | // and move the bottom side ^ upwards by 1px. 185 | rect = Add(rect, 0.0f, -1.0f, 0.0f, -1.0f); 186 | 187 | return BorderOf(rect); 188 | } 189 | // converts the border to a GraphicsPath. 190 | public static GraphicsPath ToPath(PointF[] points) 191 | { 192 | GraphicsPath path = new GraphicsPath(); 193 | path.AddPolygon(points); 194 | return path; 195 | } 196 | 197 | //---------------------------------------------------------------------- 198 | // the center of a rectangle. 199 | //---------------------------------------------------------------------- 200 | public static PointF Center(RectangleF rect) 201 | { 202 | rect = Unpretzel(rect); 203 | float x = rect.X + (rect.Width / 2.0f); 204 | float y = rect.Y + (rect.Height / 2.0f); 205 | return new PointF(x, y); 206 | } 207 | 208 | //---------------------------------------------------------------------- 209 | // constrains val.x to be in [container.left .. container.right] 210 | // constrains val.y to be in [container.top .. container.bottom] 211 | //---------------------------------------------------------------------- 212 | public static PointF Clamp(RectangleF container, PointF val) 213 | { 214 | float x = Clamp(container.Left, container.Right, val.X); 215 | float y = Clamp(container.Top, container.Bottom, val.Y); 216 | return new PointF(x, y); 217 | } 218 | public static PointF Clip(PointF val, RectangleF container) 219 | { 220 | return Clamp(container, val); 221 | } 222 | 223 | //---------------------------------------------------------------------- 224 | // CornerOf(rect, -1.0f, -1.0f) will give the rect's bottom-left corner. 225 | // CornerOf(rect, 1.0f, 1.0f) will give the rect's upper-right corner. 226 | // etc. 227 | //---------------------------------------------------------------------- 228 | public static PointF CornerOf(RectangleF rect, float sx, float sy) 229 | { 230 | // remap from [-1.0 .. 1.0] to [0.0 ..1.0] 231 | float tx = ((sx * 0.5f) + 0.5f); 232 | float ty = ((sy * 0.5f) + 0.5f); 233 | return new PointF( 234 | rect.Location.X + rect.Width * tx, 235 | rect.Location.Y + rect.Height * ty); 236 | } 237 | public static PointF CornerOf(Control control, float sx, float sy) 238 | { 239 | // return a "world position," i.e. the resulting point is in a space 240 | // relative to the control's parent. 241 | return CornerOf(Worldspace(control), sx, sy); 242 | } 243 | public static PointF LocalCornerOf(Control control, float sx, float sy) 244 | { 245 | // return a "local position," i.e. the resulting point is in a space 246 | // relative to the control itself. (The upper-left is at (0,0).) 247 | return CornerOf(Localspace(control), sx, sy); 248 | } 249 | 250 | //---------------------------------------------------------------------- 251 | // returns the distance between two rectangles. 252 | //---------------------------------------------------------------------- 253 | public static float Distance(RectangleF a, RectangleF b) 254 | { 255 | return Distance( 256 | Clip(b.Location, a), 257 | Clip(a.Location, b)); 258 | } 259 | 260 | //---------------------------------------------------------------------- 261 | public static bool IsInRange(float left, float right, float at) 262 | { 263 | if (left > right) 264 | Swap(ref left, ref right); 265 | return ((at >= left) && (at <= right)); 266 | } 267 | 268 | //---------------------------------------------------------------------- 269 | public static SizeF MeasureString(Graphics g, string text, Font font) 270 | { 271 | return g.MeasureString(text, font, (int)g.VisibleClipBounds.Width, 272 | StringFormat.GenericTypographic); 273 | } 274 | 275 | //---------------------------------------------------------------------- 276 | public static Color Opaque(Color color) 277 | { 278 | return Color.FromArgb(255, color); 279 | } 280 | 281 | //---------------------------------------------------------------------- 282 | // returns whether the clipping region that we'd be drawing onto is 283 | // actually visible. This way we can skip drawing operations if they'd 284 | // cover zero pixels. 285 | //---------------------------------------------------------------------- 286 | public static bool PaintingIsVisible(Control control, PaintEventArgs e) 287 | { 288 | if (!control.Visible) 289 | return false; 290 | if (e.ClipRectangle.Width < 0) 291 | return false; 292 | if (e.ClipRectangle.Height < 0) 293 | return false; 294 | return true; 295 | } 296 | 297 | //---------------------------------------------------------------------- 298 | // some drawing functions require an integer rectangle. 299 | // (Those functions are such squares!) 300 | //---------------------------------------------------------------------- 301 | public static Rectangle Quantize(RectangleF rect) 302 | { 303 | // TODO: should we do (int)Round(foo) instead of (int)foo? 304 | return new Rectangle( 305 | (int) rect.Location.X, 306 | (int) rect.Location.Y, 307 | (int) rect.Width, 308 | (int) rect.Height); 309 | } 310 | 311 | //---------------------------------------------------------------------- 312 | // converts [0.0 .. 1.0] to [0 .. 255] 313 | //---------------------------------------------------------------------- 314 | public static int QuantizeColorComponent(float colorComponent) 315 | { 316 | return (int) (255.0f * Clamp(0.0f, 1.0f, colorComponent)); 317 | } 318 | 319 | //---------------------------------------------------------------------- 320 | // you tell it where you want a rectangle's top, bottom, left, and right 321 | // to be, and it'll deliver one to you via Euclidcart (YC S1NaN). 322 | //---------------------------------------------------------------------- 323 | public static RectangleF RectFromSides(float top, float bottom, float left, float right) 324 | { 325 | float x = left; 326 | float y = top; 327 | float w = (right - left); 328 | float h = (bottom - top); 329 | return new RectangleF(x, y, w, h); 330 | } 331 | public static Rectangle RectFromSides(int top, int bottom, int left, int right) 332 | { 333 | return Quantize(RectFromSides((float)top, (float)bottom, (float)left, (float)right)); 334 | } 335 | 336 | //---------------------------------------------------------------------- 337 | // if 'val' is at beforeLeft, returns afterLeft. 338 | // if 'val' is at beforeRight, returns afterRight. 339 | // if 'val' is anywhere inside [beforeLeft .. beforeRight], returns 340 | // an interpolation such that it ends up inside [afterLeft .. afterRight]. 341 | // 342 | // in other words, it transforms 'val' such that it starts out in a space 343 | // with a range "[beforeLeft .. beforeRight]", and ends up in a space 344 | // with a range "[afterLeft .. afterRight]". 345 | // 346 | // (it's not actually implemented like that, obviously. I'm just 347 | // explaining the operation like that.) 348 | //---------------------------------------------------------------------- 349 | public static float Remap( 350 | float beforeLeft, float beforeRight, 351 | float afterLeft, float afterRight, 352 | float val) 353 | { 354 | //---------------------------------------------------------------------- 355 | // who says there's no room for ugly mathematics? pssh, we'll make 356 | // space! 357 | // 358 | // float r; 359 | // r = ((afterRight - afterLeft) * (val - beforeLeft)); 360 | // r /= (beforeRight - beforeLeft); 361 | // r += afterLeft; 362 | // return r; 363 | //---------------------------------------------------------------------- 364 | 365 | // the following code is equivalent to the code in the above comments. 366 | // I've expanded it and made it readable, in hopes that someone 367 | // might one day find this illuminating. 368 | 369 | // start with the value we want to remap. 370 | float r = val; 371 | 372 | // alias some quantities for convenience. 373 | float afterSize = (afterRight - afterLeft); 374 | float beforeSize = (beforeRight - beforeLeft); 375 | 376 | // translate the value such that the "origin" becomes the left side 377 | // of the `before` range. Graphics programmers, this is like going 378 | // from worldspace to localspace. 379 | // i.e. map from [beforeLeft .. beforeRight] to [0.0 .. beforeSize]. 380 | r -= beforeLeft; 381 | 382 | // undo the "scaling that was being imposed by the `before` range." 383 | // i.e. map from [0.0 .. beforeSize] to [0.0 .. 1.0]. 384 | r /= beforeSize; 385 | 386 | // map from [0.0 .. 1.0] to [0.0 .. afterSize]. 387 | r *= afterSize; 388 | 389 | // now translate this back to worldspace, except we want to be 390 | // relative to the `after` origin, not the `before` origin. 391 | // i.e. map from [0.0 .. afterSize] to [afterLeft .. afterRight]. 392 | r += afterLeft; 393 | 394 | // presto! 395 | return r; 396 | } 397 | // the 2D version of Remap(). Takes a point that lives inside `before` 398 | // and returns the corresponding point that lives in `after`. The cool 399 | // thing is that this works as expected regardless of whether the point 400 | // is inside or outside the `before` range. It will always end up relative 401 | // to `after`. (I remember how confusing this was when first starting 402 | // out, though, so I feel your pain. On the other hand, maybe you feel 403 | // no pain, in which case you're far smarter than I was at the time.) 404 | public static PointF Transform(RectangleF before, RectangleF after, PointF pt) 405 | { 406 | return new PointF( 407 | Lerp(after.Left, after.Right, WhereBetween(before.Left, before.Right, pt.X)), 408 | Lerp(after.Bottom, after.Top, WhereBetween(before.Bottom, before.Top, pt.Y))); 409 | } 410 | // the 2D version of Remap(), Takes a rectangle that lives inside `before` 411 | // and returns the corresponding rectangle that lives in `after`. 412 | public static RectangleF Transform(RectangleF before, RectangleF after, RectangleF rect) 413 | { 414 | PointF tf = Transform(before, after, new PointF(rect.Left, rect.Top)); 415 | PointF tf2 = Transform(before, after, new PointF(rect.Right, rect.Bottom)); 416 | return RectFromSides(tf.Y, tf2.Y, tf.X, tf2.X); 417 | } 418 | 419 | //---------------------------------------------------------------------- 420 | // scales a rect's width and height where the scaling operation is 421 | // relative to the rect's center. 422 | //---------------------------------------------------------------------- 423 | public static RectangleF Scale(RectangleF rect, float factorX, float factorY) 424 | { 425 | return new RectangleF( 426 | rect.Location.X - (((rect.Width * factorX) - rect.Width) / 2.0f), 427 | rect.Location.Y - (((rect.Height * factorY) - rect.Height) / 2.0f), 428 | rect.Width * factorX, 429 | rect.Height * factorY); 430 | } 431 | 432 | //---------------------------------------------------------------------- 433 | // I'll give you N = N - 1 guesses what this function does. 434 | //---------------------------------------------------------------------- 435 | public static void Swap(ref T a, ref T b) 436 | { 437 | T local = a; 438 | a = b; 439 | b = local; 440 | } 441 | 442 | //---------------------------------------------------------------------- 443 | // converts a GraphicsPath from "worldspace" to "localspace", i.e. it 444 | // starts in a space relative to `client.Parent` and ends up in a space 445 | // relative to `client`. 446 | //---------------------------------------------------------------------- 447 | public static GraphicsPath ToClient(GraphicsPath path, Control client) 448 | { 449 | GraphicsPath path2 = path.Clone() as GraphicsPath; 450 | Matrix matrix = new Matrix(); 451 | matrix.Translate((float)-client.Left, (float)-client.Top); 452 | path2.Transform(matrix); 453 | return path2; 454 | } 455 | 456 | //---------------------------------------------------------------------- 457 | // if a rect has negative width, then negate the width. Same for height. 458 | // 459 | // Seem strange? Turns out negative heights occur sometimes in 2D 460 | // graphics, usually because people tend to confuse whether (0,0) is 461 | // supposed to mean "upper-left" or "lower-left." And by "people" I 462 | // mean "I." 463 | // 464 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 465 | // (The answer, by the way, is "(0,0) means lower-left." Why? Well, 466 | // OpenGL adopts that convention, for one. But the most persuasive 467 | // reason is as follows: 468 | // 469 | // Imagine a graph where the domain and range are both [-1.0 .. 1.0]. 470 | // On such a graph, (0,0) is at the center. Then imagine a graph where 471 | // the domain and range are [0.0 .. 1.0]. Now (0,0) is at the lower-left. 472 | // 473 | // But I've given up fighting that battle long ago, since everyone uses 474 | // "(0,0) is upper-left." 475 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 476 | // 477 | // You can sort of think of this operation as "taking the absolute value 478 | // of a rectangle." So why'd I call this "Unpretzel" instead of "Abs"? 479 | // Because "taking the absolute value of a rectangle" could mean several 480 | // different things. It could mean: 481 | // 482 | // Rect(rect.Location, Abs(rect.Size)) 483 | // 484 | // ... Or it could mean: 485 | // 486 | // Rect(Abs(rect.Location), Abs(rect.Size)) 487 | // 488 | // Whereas "Unpretzel" is perfectly clear: If the rectangle is shaped 489 | // like a pretzel, then turn it inside-out! 490 | // 491 | // Just kidding, just kidding. The name makes no sense to anyone but me. 492 | // (We physicists now.) 493 | // 494 | // ..... fine, think of it like this: If the width or height is shaped 495 | // like a sock that's been turned inside-out, then turn it rightside-in. 496 | // But I couldn't very well call this "Unsock(rect)" now, could I? Gawdd! 497 | // 498 | // Okay, the real reason for this big ol' comment block is because it 499 | // was fun to write. Selfish! Here's the boooooringgggg (but simple) 500 | // explanation: 501 | // 502 | // returns Rectangle(rect.Location, Abs(rect.Size)) 503 | // 504 | // (Oh who am I kidding, no one will ever read any of this but me. And 505 | // you.) 506 | //---------------------------------------------------------------------- 507 | public static RectangleF Unpretzel(RectangleF rect) 508 | { 509 | float top = rect.Top; 510 | float bottom = rect.Bottom; 511 | float left = rect.Left; 512 | float right = rect.Right; 513 | if (rect.Height < 0.0f) Swap(ref top, ref bottom); 514 | if (rect.Width < 0.0f) Swap(ref left, ref right); 515 | return RectFromSides(top, bottom, left, right); 516 | } 517 | 518 | //---------------------------------------------------------------------- 519 | // remaps `at` from [left .. right] to [0.0 .. 1.0] 520 | //---------------------------------------------------------------------- 521 | public static float WhereBetween(float left, float right, float at) 522 | { 523 | return ((at - left) / (right - left)); 524 | } 525 | 526 | //---------------------------------------------------------------------- 527 | // constrains `rect.Location` to be within the bounds of `container`. 528 | //---------------------------------------------------------------------- 529 | public static RectangleF Within(RectangleF container, RectangleF rect) 530 | { 531 | float num = Clamp(0.0f, container.Width, (container.Width - rect.Width)); 532 | float num2 = Clamp(0.0f, container.Height, (container.Height - rect.Height)); 533 | float x = Clamp(container.Location.X, container.Location.X + num, rect.Location.X); 534 | float y = Clamp(container.Location.Y, container.Location.Y + num2, rect.Location.Y); 535 | return new RectangleF(x, y, rect.Width, rect.Height); 536 | } 537 | 538 | //====================================================================== 539 | // misc. 540 | //====================================================================== 541 | 542 | //---------------------------------------------------------------------- 543 | // to keep the distinction clear in my head. (And, incidentally, in code.) 544 | //---------------------------------------------------------------------- 545 | public static RectangleF Localspace(Control control) { return control.ClientRectangle; } 546 | public static RectangleF Worldspace(Control control) { return control.Bounds; } 547 | public static RectangleF Worldspace(ToolStripItem tsi) { return tsi.Bounds; } 548 | 549 | //---------------------------------------------------------------------- 550 | // returns whether your mouse is in control of your life's decisions. 551 | //---------------------------------------------------------------------- 552 | public static bool MouseInControl(Control control) 553 | { 554 | // get the cursor's position relative to the control. 555 | Point point = control.PointToClient(Cursor.Position); 556 | 557 | // if the control has a region, return whether the pos is within it. 558 | if (control.Region != null) 559 | return control.Region.IsVisible(point); 560 | 561 | // otherwise return whether the control's local boundary contains 562 | // the pos. 563 | return Localspace(control).Contains(point); 564 | } 565 | public static bool MouseInControl(ToolStripItem toolStripItem) 566 | { 567 | Point pt = toolStripItem.Owner.PointToClient(Cursor.Position); 568 | return Worldspace(toolStripItem).Contains(pt); 569 | } 570 | 571 | //====================================================================== 572 | // matrix helpers. 573 | //====================================================================== 574 | public static class Mat 575 | { 576 | //---------------------------------------------------------------------- 577 | public static Matrix Translate(float dx, float dy) 578 | { 579 | Matrix mat = new Matrix(); 580 | mat.Translate(dx, dy); 581 | return mat; 582 | } 583 | 584 | //---------------------------------------------------------------------- 585 | public static Matrix Remap(RectangleF before, RectangleF after) 586 | { 587 | Matrix mat = new Matrix(); 588 | // start with the value we want to remap. 589 | 590 | // translate the value such that the "origin" becomes the location 591 | // of the `before` range. Graphics programmers, this is like going 592 | // from worldspace to localspace. 593 | // i.e. map from [before.Left .. before.Right] to [0.0 .. before.Width]. 594 | // and map from [before.Top .. before.Bottom] to [0.0 .. before.Height]. 595 | mat.Translate(-before.Location.X, -before.Location.Y); 596 | 597 | // undo the "scaling that was being imposed by the `before` range." 598 | // i.e. map X from [0.0 .. before.Width] to [0.0 .. 1.0]. 599 | // and map Y from [0.0 .. before.Height] to [0.0 .. 1.0]. 600 | mat.Scale(1.0f / before.Width, 1.0f / before.Height); 601 | 602 | // map X from [0.0 .. 1.0] to [0.0 .. after.Width]. 603 | // map Y from [0.0 .. 1.0] to [0.0 .. after.Height]. 604 | mat.Scale(after.Width, after.Height); 605 | 606 | // now translate this back to worldspace, except we want to be 607 | // relative to the `after` origin, not the `before` origin. 608 | // i.e. map X from [0.0 .. after.Width] to [after.Left .. after.Right]. 609 | // and map Y from [0.0 .. after.Height] to [after.Top .. after.Bottom]. 610 | mat.Translate(after.Location.X, after.Location.Y); 611 | 612 | // presto! 613 | return mat; 614 | } 615 | 616 | //---------------------------------------------------------------------- 617 | // TODO. 618 | //---------------------------------------------------------------------- 619 | //public static RectangleF TransformRect(RectangleF rect, Matrix xform) 620 | //{ 621 | //} 622 | } 623 | 624 | //====================================================================== 625 | // actual drawing operations. 626 | //====================================================================== 627 | public static class Draw 628 | { 629 | //---------------------------------------------------------------------- 630 | // draws the dropshadow of a path. This function was designed to 631 | // have a bunch of configurable options. 632 | //---------------------------------------------------------------------- 633 | public static void Dropshadow(Graphics g, GraphicsPath path, 634 | int alpha, Color color, float offsetInPixelsX, float offsetInPixelsY) 635 | { 636 | using (GraphicsPath path2 = (GraphicsPath)path.Clone()) 637 | { 638 | path2.Transform(Util.Mat.Translate(offsetInPixelsX, offsetInPixelsY)); 639 | using (Brush brush = new SolidBrush(Color.FromArgb(alpha, color))) 640 | { 641 | g.FillPath(brush, path2); 642 | } 643 | } 644 | } 645 | public static void Dropshadow(Graphics g, GraphicsPath path, 646 | int alpha, float offsetInPixelsX, float offsetInPixelsY) 647 | { 648 | Dropshadow(g, path, alpha, Color.Black, 649 | offsetInPixelsX, offsetInPixelsY); 650 | } 651 | 652 | //---------------------------------------------------------------------- 653 | // draws the dropshadow of a control. This function was designed to 654 | // have a certain look and feel to it, specific to `wow`. 655 | //---------------------------------------------------------------------- 656 | public static void Dropshadow(Graphics g, Control control) 657 | { 658 | GraphicsPath path = Util.RoundedRect(control, 3.0f); 659 | Dropshadow(g, path); 660 | } 661 | public static void Dropshadow(Graphics g, GraphicsPath path) 662 | { 663 | Util.Draw.Dropshadow(g, path, 48, Color.MidnightBlue, 1.5f, 1.0f); 664 | } 665 | 666 | //---------------------------------------------------------------------- 667 | public static void TextBubble(Graphics g, 668 | //RectangleF boundary, 669 | PointF location, 670 | string text, 671 | Color bgColor, Color fgColor, 672 | Font font, float feather, SizeF pad) 673 | { 674 | PointF tf = new PointF(pad.Width, pad.Height); 675 | feather *= 2f; 676 | SizeF size = MeasureString(g, text, font); 677 | RectangleF rect = new RectangleF(location, size); 678 | rect.Inflate((feather / 2f) + tf.X, (feather / 2f) + tf.Y); 679 | //rect = Util.Within(boundary, rect); 680 | GraphicsPath path = Util.RoundedRect(rect, feather, feather); 681 | Dropshadow(g, path, 0x20, 2.6f, 2f); 682 | using (PathGradientBrush brush = new PathGradientBrush(path)) 683 | { 684 | brush.SurroundColors = new Color[] { Color.FromArgb(0x20, bgColor) }; 685 | brush.CenterColor = Color.White; 686 | brush.CenterPoint = Util.Subtract(brush.CenterPoint, new PointF(rect.Width / 2f, rect.Height / 2f)); 687 | g.FillPath(brush, path); 688 | } 689 | using (Pen pen = new Pen(Color.FromArgb(0x60, Color.Black))) 690 | { 691 | g.DrawPath(pen, path); 692 | } 693 | using (SolidBrush brush2 = new SolidBrush(fgColor)) 694 | { 695 | g.DrawString(text, font, brush2, Util.Add(rect.Location, new PointF((tf.X + feather) / 2f, (tf.Y + feather) / 2f))); 696 | } 697 | } 698 | public static void TextBubble(Graphics g, 699 | //RectangleF boundary, 700 | PointF location, 701 | string text, 702 | Color bgColor, Color fgColor, 703 | Font font, float feather) 704 | { 705 | TextBubble(g, 706 | //boundary, 707 | location, 708 | text, 709 | bgColor, fgColor, 710 | font, feather, new SizeF(0f, 0f)); 711 | } 712 | 713 | //---------------------------------------------------------------------- 714 | public static void Tracker(Graphics g, RectangleF aTrackerRect, Color innerColor, Color outerColor) 715 | { 716 | Color[] colorArray; 717 | using (GraphicsPath path = new GraphicsPath()) 718 | { 719 | path.AddEllipse(aTrackerRect); 720 | using (PathGradientBrush brush = new PathGradientBrush(path)) 721 | { 722 | brush.CenterColor = innerColor; 723 | colorArray = new Color[] { outerColor }; 724 | brush.SurroundColors = colorArray; 725 | colorArray = new Color[] { brush.CenterColor }; 726 | brush.SurroundColors = colorArray; 727 | g.FillEllipse(new SolidBrush(brush.SurroundColors[0]), aTrackerRect); 728 | g.FillPath(brush, path); 729 | } 730 | } 731 | using (GraphicsPath path2 = new GraphicsPath()) 732 | { 733 | RectangleF rect = new RectangleF(aTrackerRect.Width * 0.1f, aTrackerRect.Height * 0.05f, aTrackerRect.Width * 0.8f, aTrackerRect.Height * 0.9f); 734 | path2.AddEllipse(aTrackerRect); 735 | rect.Offset(aTrackerRect.Location); 736 | path2.AddEllipse(rect); 737 | using (PathGradientBrush brush2 = new PathGradientBrush(path2)) 738 | { 739 | brush2.CenterColor = Color.FromArgb(200, Color.White); 740 | colorArray = new Color[] { Color.FromArgb(0, Color.White) }; 741 | brush2.SurroundColors = colorArray; 742 | g.FillPath(brush2, path2); 743 | } 744 | } 745 | using (GraphicsPath path3 = new GraphicsPath()) 746 | { 747 | RectangleF ef2 = new RectangleF(0f, aTrackerRect.Height * 0.33f, aTrackerRect.Width, aTrackerRect.Height); 748 | ef2.Offset(aTrackerRect.Location); 749 | path3.AddEllipse(ef2); 750 | using (Region region = new Region(path3)) 751 | { 752 | using (GraphicsPath path4 = new GraphicsPath()) 753 | { 754 | path4.AddEllipse(aTrackerRect); 755 | region.Complement(path4); 756 | using (SolidBrush brush3 = new SolidBrush(Color.FromArgb(30, Color.White))) 757 | { 758 | g.FillRegion(brush3, region); 759 | } 760 | } 761 | } 762 | } 763 | using (GraphicsPath path5 = new GraphicsPath()) 764 | { 765 | RectangleF ef3 = new RectangleF(0f, 0f, aTrackerRect.Width * 0.56f, aTrackerRect.Height * 0.248f); 766 | ef3.Offset((aTrackerRect.Width / 2f) - (ef3.Width / 2f), aTrackerRect.Height * 0.04f); 767 | ef3.Offset(aTrackerRect.Location); 768 | path5.AddEllipse(ef3); 769 | using (LinearGradientBrush brush4 = new LinearGradientBrush(path5.GetBounds(), Color.FromArgb(200, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical)) 770 | { 771 | g.FillPath(brush4, path5); 772 | } 773 | } 774 | using (GraphicsPath path6 = new GraphicsPath()) 775 | { 776 | RectangleF ef4 = new RectangleF(0f, 0f, aTrackerRect.Width * 0.3f, aTrackerRect.Height * 0.15f); 777 | ef4.Offset((aTrackerRect.Width / 2f) - (ef4.Width / 2f), (aTrackerRect.Height - ef4.Height) - (aTrackerRect.Height * 0.03f)); 778 | ef4.Offset(aTrackerRect.Location); 779 | path6.AddEllipse(ef4); 780 | using (LinearGradientBrush brush5 = new LinearGradientBrush(path6.GetBounds(), Color.FromArgb(0, Color.White), Color.FromArgb(100, Color.White), LinearGradientMode.Vertical)) 781 | { 782 | g.FillPath(brush5, path6); 783 | } 784 | } 785 | } 786 | public static void Tracker(Graphics g, RectangleF aTrackerRect) 787 | { 788 | Tracker(g, aTrackerRect, Color.FromArgb(2, 0x6b, 0xe1), Color.FromArgb(0, 6, 0x8a)); 789 | } 790 | } 791 | 792 | //---------------------------------------------------------------------- 793 | // I'm lumping this in with the "drawing operations" file section since 794 | // this has the look and feel of a drawing operation in addition to 795 | // merely being related to the concept of "drawing stuff." It's still 796 | // a utility though. 797 | //---------------------------------------------------------------------- 798 | public static GraphicsPath RoundedRect(RectangleF rect, float featherX, float featherY) 799 | { 800 | // stand back, I'm about to do Graphics(tm)! 801 | GraphicsPath path = new GraphicsPath(); 802 | float width = rect.Width; 803 | float height = rect.Height; 804 | float num3 = Clamp(0.0f, rect.Width, 2.0f * featherX); 805 | float num4 = Clamp(0.0f, rect.Width, 2.0f * featherY); 806 | SizeF size = new SizeF(num3, num4); 807 | if (size.Width == 0.0f) size.Width = 0.01f; 808 | if (size.Height == 0.0f) size.Height = 0.01f; 809 | RectangleF ef2 = new RectangleF(new PointF(width - num3, height - num4), size); 810 | RectangleF ef3 = new RectangleF(new PointF(0.0f, height - num4), size); 811 | RectangleF ef4 = new RectangleF(new PointF(0.0f, 0.0f), size); 812 | RectangleF ef5 = new RectangleF(new PointF(width - num3, 0.0f), size); 813 | path.AddArc(ef2, 0.0f, 90.0f); 814 | path.AddArc(ef3, 90.0f, 90.0f); 815 | path.AddArc(ef4, 180.0f, 90.0f); 816 | path.AddArc(ef5, 270.0f, 90.0f); 817 | path.CloseFigure(); 818 | Matrix matrix = new Matrix(); 819 | matrix.Translate(rect.Location.X, rect.Location.Y); 820 | path.Transform(matrix); 821 | return path; 822 | } 823 | public static GraphicsPath RoundedRect(RectangleF rect, float feather) 824 | { 825 | return RoundedRect(rect, feather, feather); 826 | } 827 | public static GraphicsPath RoundedRect(Control control, float feather) 828 | { 829 | return RoundedRect(Worldspace(control), feather, feather); 830 | } 831 | } 832 | } 833 | -------------------------------------------------------------------------------- /src/csharp/Wow/Utility/Utility.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D597F633-7C18-4C8A-B7BD-26468881533C} 8 | Library 9 | Properties 10 | Utility 11 | Utility 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | bin\x86\Debug\ 19 | DEBUG;TRACE 20 | full 21 | x86 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | 25 | 26 | bin\x86\Release\ 27 | TRACE 28 | true 29 | pdbonly 30 | x86 31 | prompt 32 | MinimumRecommendedRules.ruleset 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Visualizer 2 | { 3 | partial class MainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.splitMain = new System.Windows.Forms.SplitContainer(); 32 | this.gradientPanel1 = new Controls.Basic.GradientPanel(); 33 | this.pnTestDropshadow = new Controls.Basic.GradientPanel(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.spectrogram1 = new Controls.Visualization.Spectrogram(); 36 | ((System.ComponentModel.ISupportInitialize)(this.splitMain)).BeginInit(); 37 | this.splitMain.Panel1.SuspendLayout(); 38 | this.splitMain.Panel2.SuspendLayout(); 39 | this.splitMain.SuspendLayout(); 40 | this.pnTestDropshadow.SuspendLayout(); 41 | this.SuspendLayout(); 42 | // 43 | // splitMain 44 | // 45 | this.splitMain.Dock = System.Windows.Forms.DockStyle.Fill; 46 | this.splitMain.Location = new System.Drawing.Point(0, 0); 47 | this.splitMain.Name = "splitMain"; 48 | this.splitMain.Orientation = System.Windows.Forms.Orientation.Horizontal; 49 | // 50 | // splitMain.Panel1 51 | // 52 | this.splitMain.Panel1.BackColor = System.Drawing.Color.AliceBlue; 53 | this.splitMain.Panel1.Controls.Add(this.gradientPanel1); 54 | this.splitMain.Panel1.Controls.Add(this.pnTestDropshadow); 55 | // 56 | // splitMain.Panel2 57 | // 58 | this.splitMain.Panel2.Controls.Add(this.spectrogram1); 59 | this.splitMain.Size = new System.Drawing.Size(731, 625); 60 | this.splitMain.SplitterDistance = 106; 61 | this.splitMain.TabIndex = 1; 62 | // 63 | // gradientPanel1 64 | // 65 | this.gradientPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 66 | | System.Windows.Forms.AnchorStyles.Left))); 67 | this.gradientPanel1.Border3DStyle = System.Windows.Forms.Border3DStyle.RaisedInner; 68 | this.gradientPanel1.GradientColor1 = System.Drawing.Color.AliceBlue; 69 | this.gradientPanel1.GradientColor2 = System.Drawing.Color.LightSteelBlue; 70 | this.gradientPanel1.Location = new System.Drawing.Point(160, 12); 71 | this.gradientPanel1.Name = "gradientPanel1"; 72 | this.gradientPanel1.Size = new System.Drawing.Size(134, 79); 73 | this.gradientPanel1.TabIndex = 1; 74 | // 75 | // pnTestDropshadow 76 | // 77 | this.pnTestDropshadow.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 78 | | System.Windows.Forms.AnchorStyles.Left))); 79 | this.pnTestDropshadow.Border3DStyle = System.Windows.Forms.Border3DStyle.RaisedInner; 80 | this.pnTestDropshadow.Controls.Add(this.label1); 81 | this.pnTestDropshadow.GradientColor1 = System.Drawing.Color.AliceBlue; 82 | this.pnTestDropshadow.GradientColor2 = System.Drawing.Color.LightSteelBlue; 83 | this.pnTestDropshadow.Location = new System.Drawing.Point(12, 12); 84 | this.pnTestDropshadow.Name = "pnTestDropshadow"; 85 | this.pnTestDropshadow.Size = new System.Drawing.Size(142, 79); 86 | this.pnTestDropshadow.TabIndex = 0; 87 | // 88 | // label1 89 | // 90 | this.label1.BackColor = System.Drawing.Color.Transparent; 91 | this.label1.Dock = System.Windows.Forms.DockStyle.Fill; 92 | this.label1.Location = new System.Drawing.Point(0, 0); 93 | this.label1.Name = "label1"; 94 | this.label1.Padding = new System.Windows.Forms.Padding(4); 95 | this.label1.Size = new System.Drawing.Size(142, 79); 96 | this.label1.TabIndex = 0; 97 | this.label1.Text = "Wow, this \"UI\" looks legitimately terrible. But I\'m just playing around with dif" + 98 | "ferent possibilities at this point."; 99 | // 100 | // spectrogram1 101 | // 102 | this.spectrogram1.Dock = System.Windows.Forms.DockStyle.Fill; 103 | this.spectrogram1.Location = new System.Drawing.Point(0, 0); 104 | this.spectrogram1.Name = "spectrogram1"; 105 | this.spectrogram1.Size = new System.Drawing.Size(731, 515); 106 | this.spectrogram1.TabIndex = 0; 107 | // 108 | // MainForm 109 | // 110 | this.AllowDrop = true; 111 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 112 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 113 | this.ClientSize = new System.Drawing.Size(731, 625); 114 | this.Controls.Add(this.splitMain); 115 | this.Name = "MainForm"; 116 | this.Text = "wow such signal"; 117 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); 118 | this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainForm_DragDrop); 119 | this.DragEnter += new System.Windows.Forms.DragEventHandler(this.MainForm_DragEnter); 120 | this.splitMain.Panel1.ResumeLayout(false); 121 | this.splitMain.Panel2.ResumeLayout(false); 122 | ((System.ComponentModel.ISupportInitialize)(this.splitMain)).EndInit(); 123 | this.splitMain.ResumeLayout(false); 124 | this.pnTestDropshadow.ResumeLayout(false); 125 | this.ResumeLayout(false); 126 | 127 | } 128 | 129 | #endregion 130 | 131 | private Controls.Visualization.Spectrogram spectrogram1; 132 | private System.Windows.Forms.SplitContainer splitMain; 133 | private Controls.Basic.GradientPanel pnTestDropshadow; 134 | private System.Windows.Forms.Label label1; 135 | private Controls.Basic.GradientPanel gradientPanel1; 136 | } 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using Common.DSP; 11 | using Utility; 12 | using System.Drawing.Drawing2D; 13 | 14 | namespace Visualizer 15 | { 16 | public partial class MainForm : Form 17 | { 18 | //============================================================================= 19 | // Variables 20 | //============================================================================= 21 | 22 | private ISignal _signal; 23 | private readonly Font _font = new Font(FontFamily.GenericSansSerif, 10.0f); 24 | 25 | //============================================================================= 26 | // Methods 27 | //============================================================================= 28 | 29 | //----------------------------------------------------------------------------- 30 | public MainForm() 31 | { 32 | InitializeComponent(); 33 | splitMain.Panel1.Paint += Panel1_Paint; 34 | } 35 | 36 | //----------------------------------------------------------------------------- 37 | public void Frame(uint dt) 38 | { 39 | } 40 | 41 | //----------------------------------------------------------------------------- 42 | public bool LoadSignalFromFile(string filepath) 43 | { 44 | if (!IsFileAllowed(filepath)) 45 | return false; 46 | 47 | if (filepath.ToLower().EndsWith(".iq")) 48 | { 49 | // for now, just fill in some values for testing purposes. (Eventually 50 | // we'll prompt the user to provide this info.) 51 | HackRFSignal.Settings settings; 52 | settings.Frequency = 27000000; 53 | settings.SamplesPerSec = 10000000; 54 | 55 | _signal = new HackRFSignal(settings, filepath); 56 | 57 | Complex[] samples = new Complex[2048]; 58 | _signal.ReadSamples(samples, 0, 2048); 59 | 60 | return true; 61 | } 62 | 63 | throw new NotImplementedException("Support for that filetype isn't implemented yet."); 64 | } 65 | 66 | //----------------------------------------------------------------------------- 67 | bool IsFileAllowed(string filepath) 68 | { 69 | // only allow .iq and .wav files. 70 | return filepath.ToLower().EndsWith(".iq") || filepath.ToLower().EndsWith(".wav"); 71 | } 72 | 73 | //============================================================================= 74 | // Properties 75 | //============================================================================= 76 | 77 | //----------------------------------------------------------------------------- 78 | public bool Done; 79 | 80 | //============================================================================= 81 | // Events 82 | //============================================================================= 83 | 84 | //----------------------------------------------------------------------------- 85 | private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 86 | { 87 | this.Done = true; 88 | } 89 | 90 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 91 | // pretty stuff. (like you!) 92 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 93 | 94 | //----------------------------------------------------------------------------- 95 | void Panel1_Paint(object sender, PaintEventArgs e) 96 | { 97 | Graphics g = e.Graphics; 98 | 99 | // draw a fake panel to the right of a real panel, but with rounded corners! 100 | // (We apple now.) 101 | { 102 | GraphicsPath gp = Util.RoundedRect(Util.Worldspace(pnTestDropshadow), 5.0f); 103 | PointF pos = new PointF(2.0f * pnTestDropshadow.Width + 2, 0.0f); 104 | gp.Transform(Util.Mat.Translate(pos.X, pos.Y)); 105 | pos = Util.Add(pos, pnTestDropshadow.Location); 106 | Util.Draw.Dropshadow(g, gp); 107 | Util.Draw.Dropshadow(g, gp, 128 + 64, pnTestDropshadow.BackColor, 0.0f, 0.0f); 108 | using (Pen p = new Pen(Color.FromArgb(64, Color.MidnightBlue))) 109 | { 110 | g.DrawPath(p, gp); 111 | } 112 | pos = Util.Add(pos, new PointF(20.0f, 20.0f)); 113 | pos = Util.Add(pos, new PointF(pnTestDropshadow.Width, 0.0f)); 114 | Util.Draw.TextBubble(g, pos, "wow", Color.AliceBlue, Color.SteelBlue, _font, 5.0f); 115 | 116 | Util.Draw.Tracker(g, new RectangleF(Util.Add(pos, new PointF(50.0f, 0.0f)), new SizeF(20.0f, 20.0f))); 117 | } 118 | } 119 | 120 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 121 | // drag'n'drop. 122 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 123 | 124 | //----------------------------------------------------------------------------- 125 | private void MainForm_DragEnter(object sender, DragEventArgs e) 126 | { 127 | // is the user dropping files? 128 | if (e.Data.GetDataPresent(DataFormats.FileDrop)) 129 | { 130 | // get the list of files the user's dropping. 131 | string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); 132 | foreach (string file in files) 133 | { 134 | // if the list contains a valid file type, then allow it. 135 | if (IsFileAllowed(file)) 136 | { 137 | e.Effect = DragDropEffects.Copy; 138 | return; 139 | } 140 | } 141 | } 142 | 143 | // if there were no valid files, then ignore the dragdrop. 144 | e.Effect = DragDropEffects.None; 145 | } 146 | 147 | //----------------------------------------------------------------------------- 148 | private void MainForm_DragDrop(object sender, DragEventArgs e) 149 | { 150 | // get the list of files the user's dropping. 151 | string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); 152 | foreach (string file in files) 153 | { 154 | // try to load the first valid file. 155 | if (IsFileAllowed(file)) 156 | { 157 | if (this.LoadSignalFromFile(file)) 158 | { 159 | // update the header bar's text to indicate a file is open. 160 | string basename = System.IO.Path.GetFileName(file); 161 | this.Text = String.Format("{0} ({1})", Program.Title, basename); 162 | return; 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace Visualizer 8 | { 9 | static class Program 10 | { 11 | //---------------------------------------------------------------------- 12 | [STAThread] 13 | static void Main() 14 | { 15 | Application.EnableVisualStyles(); 16 | Application.SetCompatibleTextRenderingDefault(false); 17 | 18 | while (!MainForm.Done) 19 | { 20 | // compute elapsed time since last frame. 21 | uint dt = 0; 22 | 23 | // process application events. 24 | Application.DoEvents(); 25 | 26 | // process the current frame. 27 | MainForm.Frame(dt); 28 | } 29 | } 30 | 31 | //---------------------------------------------------------------------- 32 | static MainForm _mainForm; 33 | public static MainForm MainForm 34 | { 35 | get 36 | { 37 | if (_mainForm == null) 38 | { 39 | _mainForm = new MainForm(); 40 | _title = _mainForm.Text; 41 | _mainForm.Show(); 42 | } 43 | return _mainForm; 44 | } 45 | } 46 | 47 | //---------------------------------------------------------------------- 48 | static string _title; 49 | public static string Title 50 | { 51 | get { return _title; } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Visualizer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Visualizer")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1ea88b5f-e2f4-478c-be5a-9947c2f87651")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Visualizer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Visualizer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Visualizer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/Visualizer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8E2AD688-9C97-4F2A-ACC1-332D42D61FB1} 8 | WinExe 9 | Properties 10 | Visualizer 11 | Visualizer 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | bin\x86\Debug\ 19 | DEBUG;TRACE 20 | true 21 | full 22 | x86 23 | prompt 24 | MinimumRecommendedRules.ruleset 25 | true 26 | 27 | 28 | bin\x86\Release\ 29 | TRACE 30 | true 31 | true 32 | pdbonly 33 | x86 34 | prompt 35 | MinimumRecommendedRules.ruleset 36 | true 37 | 38 | 39 | 40 | ..\Packages\OpenTK.1.1.1589.5942\lib\NET40\OpenTK.dll 41 | 42 | 43 | ..\Packages\OpenTK.GLControl.1.1.1589.5942\lib\NET40\OpenTK.GLControl.dll 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Form 58 | 59 | 60 | MainForm.cs 61 | 62 | 63 | 64 | 65 | MainForm.cs 66 | 67 | 68 | ResXFileCodeGenerator 69 | Resources.Designer.cs 70 | Designer 71 | 72 | 73 | True 74 | Resources.resx 75 | True 76 | 77 | 78 | SettingsSingleFileGenerator 79 | Settings.Designer.cs 80 | 81 | 82 | True 83 | Settings.settings 84 | True 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | {77aabee0-2c4b-488b-8b2e-cb07298572dc} 93 | Common 94 | 95 | 96 | {20235B91-D804-4ECA-9B55-E0FC40725040} 97 | Controls 98 | 99 | 100 | {d597f633-7c18-4c8a-b7bd-26468881533c} 101 | Utility 102 | 103 | 104 | 105 | 106 | $(SolutionDir)Tools\nuget install $(ProjectDir)packages.config -o $(SolutionDir)Packages 107 | 108 | 115 | -------------------------------------------------------------------------------- /src/csharp/Wow/Visualizer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/csharp/Wow/Wow.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Visualizer", "Visualizer\Visualizer.csproj", "{8E2AD688-9C97-4F2A-ACC1-332D42D61FB1}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {D597F633-7C18-4C8A-B7BD-26468881533C} = {D597F633-7C18-4C8A-B7BD-26468881533C} 7 | {20235B91-D804-4ECA-9B55-E0FC40725040} = {20235B91-D804-4ECA-9B55-E0FC40725040} 8 | {77AABEE0-2C4B-488B-8B2E-CB07298572DC} = {77AABEE0-2C4B-488B-8B2E-CB07298572DC} 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls", "Controls\Controls.csproj", "{20235B91-D804-4ECA-9B55-E0FC40725040}" 12 | ProjectSection(ProjectDependencies) = postProject 13 | {D597F633-7C18-4C8A-B7BD-26468881533C} = {D597F633-7C18-4C8A-B7BD-26468881533C} 14 | EndProjectSection 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{77AABEE0-2C4B-488B-8B2E-CB07298572DC}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utility", "Utility\Utility.csproj", "{D597F633-7C18-4C8A-B7BD-26468881533C}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|x86 = Debug|x86 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {8E2AD688-9C97-4F2A-ACC1-332D42D61FB1}.Debug|x86.ActiveCfg = Debug|x86 27 | {8E2AD688-9C97-4F2A-ACC1-332D42D61FB1}.Debug|x86.Build.0 = Debug|x86 28 | {8E2AD688-9C97-4F2A-ACC1-332D42D61FB1}.Release|x86.ActiveCfg = Release|x86 29 | {8E2AD688-9C97-4F2A-ACC1-332D42D61FB1}.Release|x86.Build.0 = Release|x86 30 | {20235B91-D804-4ECA-9B55-E0FC40725040}.Debug|x86.ActiveCfg = Debug|x86 31 | {20235B91-D804-4ECA-9B55-E0FC40725040}.Debug|x86.Build.0 = Debug|x86 32 | {20235B91-D804-4ECA-9B55-E0FC40725040}.Release|x86.ActiveCfg = Release|x86 33 | {20235B91-D804-4ECA-9B55-E0FC40725040}.Release|x86.Build.0 = Release|x86 34 | {77AABEE0-2C4B-488B-8B2E-CB07298572DC}.Debug|x86.ActiveCfg = Debug|x86 35 | {77AABEE0-2C4B-488B-8B2E-CB07298572DC}.Debug|x86.Build.0 = Debug|x86 36 | {77AABEE0-2C4B-488B-8B2E-CB07298572DC}.Release|x86.ActiveCfg = Release|x86 37 | {77AABEE0-2C4B-488B-8B2E-CB07298572DC}.Release|x86.Build.0 = Release|x86 38 | {D597F633-7C18-4C8A-B7BD-26468881533C}.Debug|x86.ActiveCfg = Debug|x86 39 | {D597F633-7C18-4C8A-B7BD-26468881533C}.Debug|x86.Build.0 = Debug|x86 40 | {D597F633-7C18-4C8A-B7BD-26468881533C}.Release|x86.ActiveCfg = Release|x86 41 | {D597F633-7C18-4C8A-B7BD-26468881533C}.Release|x86.Build.0 = Release|x86 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | EndGlobal 47 | --------------------------------------------------------------------------------