├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── resources │ └── color-dark-2048.png └── workflows │ ├── Release.yml │ └── continuous-integration.yml ├── .gitignore ├── AUTHORS ├── BuildSystem └── scripts │ ├── build-all.cmd │ └── install-dependencies.cmd ├── CHANGELOG ├── Desktop ├── Application │ ├── MaxMix.sln │ ├── MaxMix │ │ ├── App.config │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Framework │ │ │ ├── AppExtensions.cs │ │ │ ├── AttachedProperties │ │ │ │ └── BalloonMessageProperty.cs │ │ │ ├── Converters │ │ │ │ ├── BoolToStringConverter.cs │ │ │ │ ├── BoolToVisibilityConverter.cs │ │ │ │ └── ColorToUint32Converter.cs │ │ │ └── Mvvm │ │ │ │ ├── DelegateCommand.cs │ │ │ │ └── ObservableObject.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── MaxMix.csproj │ │ ├── Properties │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ ├── Services │ │ │ ├── Audio │ │ │ │ ├── AudioCommon.cs │ │ │ │ ├── AudioDevice.cs │ │ │ │ ├── AudioExtensions.cs │ │ │ │ ├── AudioSession.cs │ │ │ │ ├── AudioSessionGroup.cs │ │ │ │ ├── AudioSessionService.cs │ │ │ │ ├── IAudioDevice.cs │ │ │ │ ├── IAudioSession.cs │ │ │ │ ├── IAudioSessionService.cs │ │ │ │ ├── ISession.cs │ │ │ │ └── PolicyConfig.cs │ │ │ └── Communication │ │ │ │ ├── CircularBuffer.cs │ │ │ │ ├── CommunicationService.cs │ │ │ │ ├── FirmwareVersions.cs │ │ │ │ └── Messages.cs │ │ ├── ViewModels │ │ │ ├── BaseViewModel.cs │ │ │ ├── MainViewModel.cs │ │ │ └── SettingsViewModel.cs │ │ ├── Views │ │ │ ├── SettingsView.xaml │ │ │ └── SettingsView.xaml.cs │ │ └── packages.config │ └── MaxMixTest │ │ ├── App.config │ │ ├── MaxMixTest.csproj │ │ ├── Program.cs │ │ └── Properties │ │ └── AssemblyInfo.cs ├── Build.msbuild ├── DriverInstaller │ ├── DriverInstaller.sln │ └── DriverInstaller │ │ ├── App.config │ │ ├── DriverInstaller.csproj │ │ ├── Program.cs │ │ └── Properties │ │ └── AssemblyInfo.cs ├── FirmwareInstaller │ ├── FirmwareInstaller.sln │ └── FirmwareInstaller │ │ ├── App.config │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── FirmwareInstaller.csproj │ │ ├── FirmwareInstaller.csproj.user │ │ ├── Framework │ │ ├── Attached │ │ │ └── Commands.cs │ │ ├── Converters │ │ │ └── BoolNegateConverter.cs │ │ └── Mvvm │ │ │ ├── DelegateCommand.cs │ │ │ └── ObservableObject.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── Models │ │ ├── VersionIndexModel.cs │ │ └── VersionModel.cs │ │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ │ ├── Services │ │ ├── BaseService.cs │ │ ├── DiscoveryService.cs │ │ ├── DownloadSevice.cs │ │ ├── IService.cs │ │ └── InstallService.cs │ │ ├── ViewModels │ │ ├── BaseViewModel.cs │ │ └── MainViewModel.cs │ │ └── packages.config ├── Installer │ └── Maxmix.aip └── Resources │ ├── NLog.config │ ├── bin │ ├── Driver │ │ ├── CH341PT.DLL │ │ ├── CH341S64.SYS │ │ ├── CH341S98.SYS │ │ ├── CH341SER.INF │ │ ├── CH341SER.SYS │ │ ├── CH341SER.VXD │ │ └── ch341SER.CAT │ └── avrdude │ │ ├── avrdude.conf │ │ ├── avrdude.exe │ │ └── libusb0.dll │ └── icons │ ├── app.ico │ ├── device_connected.ico │ ├── device_disconnected.ico │ └── fwinstaller.ico ├── Embedded ├── MaxMix │ ├── .gitignore │ ├── Communications.cpp │ ├── Communications.h │ ├── Config.h │ ├── Display.cpp │ ├── Display.h │ ├── Enums.h │ ├── Lighting.ino │ ├── Logo.h │ ├── MaxMix.ino │ ├── Structs.h │ ├── _Template.ino │ ├── platformio.ini │ └── src │ │ ├── Adafruit_GFX │ │ ├── Adafruit_GFX.cpp │ │ ├── Adafruit_GFX.h │ │ ├── Adafruit_SPITFT.cpp │ │ ├── Adafruit_SPITFT.h │ │ ├── Adafruit_SPITFT_Macros.h │ │ ├── Fonts │ │ │ ├── FreeMono12pt7b.h │ │ │ ├── FreeMono18pt7b.h │ │ │ ├── FreeMono24pt7b.h │ │ │ ├── FreeMono9pt7b.h │ │ │ ├── FreeMonoBold12pt7b.h │ │ │ ├── FreeMonoBold18pt7b.h │ │ │ ├── FreeMonoBold24pt7b.h │ │ │ ├── FreeMonoBold9pt7b.h │ │ │ ├── FreeMonoBoldOblique12pt7b.h │ │ │ ├── FreeMonoBoldOblique18pt7b.h │ │ │ ├── FreeMonoBoldOblique24pt7b.h │ │ │ ├── FreeMonoBoldOblique9pt7b.h │ │ │ ├── FreeMonoOblique12pt7b.h │ │ │ ├── FreeMonoOblique18pt7b.h │ │ │ ├── FreeMonoOblique24pt7b.h │ │ │ ├── FreeMonoOblique9pt7b.h │ │ │ ├── FreeSans12pt7b.h │ │ │ ├── FreeSans18pt7b.h │ │ │ ├── FreeSans24pt7b.h │ │ │ ├── FreeSans9pt7b.h │ │ │ ├── FreeSansBold12pt7b.h │ │ │ ├── FreeSansBold18pt7b.h │ │ │ ├── FreeSansBold24pt7b.h │ │ │ ├── FreeSansBold9pt7b.h │ │ │ ├── FreeSansBoldOblique12pt7b.h │ │ │ ├── FreeSansBoldOblique18pt7b.h │ │ │ ├── FreeSansBoldOblique24pt7b.h │ │ │ ├── FreeSansBoldOblique9pt7b.h │ │ │ ├── FreeSansOblique12pt7b.h │ │ │ ├── FreeSansOblique18pt7b.h │ │ │ ├── FreeSansOblique24pt7b.h │ │ │ ├── FreeSansOblique9pt7b.h │ │ │ ├── FreeSerif12pt7b.h │ │ │ ├── FreeSerif18pt7b.h │ │ │ ├── FreeSerif24pt7b.h │ │ │ ├── FreeSerif9pt7b.h │ │ │ ├── FreeSerifBold12pt7b.h │ │ │ ├── FreeSerifBold18pt7b.h │ │ │ ├── FreeSerifBold24pt7b.h │ │ │ ├── FreeSerifBold9pt7b.h │ │ │ ├── FreeSerifBoldItalic12pt7b.h │ │ │ ├── FreeSerifBoldItalic18pt7b.h │ │ │ ├── FreeSerifBoldItalic24pt7b.h │ │ │ ├── FreeSerifBoldItalic9pt7b.h │ │ │ ├── FreeSerifItalic12pt7b.h │ │ │ ├── FreeSerifItalic18pt7b.h │ │ │ ├── FreeSerifItalic24pt7b.h │ │ │ ├── FreeSerifItalic9pt7b.h │ │ │ ├── Org_01.h │ │ │ ├── Picopixel.h │ │ │ ├── Tiny3x3a2pt7b.h │ │ │ └── TomThumb.h │ │ ├── Meta │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ └── library.properties │ │ ├── gfxfont.h │ │ └── glcdfont.c │ │ ├── Adafruit_NeoPixel │ │ ├── Adafruit_NeoPixel.cpp │ │ ├── Adafruit_NeoPixel.h │ │ ├── Meta │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ └── library.properties │ │ └── esp8266.c │ │ ├── Adafruit_SSD1306 │ │ ├── Adafruit_SSD1306.cpp │ │ ├── Adafruit_SSD1306.h │ │ └── Meta │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ └── library.properties │ │ ├── Bounce2 │ │ ├── Bounce2.cpp │ │ ├── Bounce2.h │ │ └── Meta │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── extras │ │ │ ├── Bounce1.zip │ │ │ ├── BouncySwitch_lockout.png │ │ │ ├── BouncySwitch_stable.png │ │ │ └── circuit-bounce-change-duration-retrigger.png │ │ │ └── library.properties │ │ ├── ButtonEvents │ │ ├── ButtonEvents.cpp │ │ ├── ButtonEvents.h │ │ └── Meta │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── library.properties │ │ ├── FixedPoints │ │ ├── FixedPoints.h │ │ ├── FixedPoints │ │ │ ├── Details.h │ │ │ ├── FixedPoints.h │ │ │ ├── SFixed.h │ │ │ ├── SFixedFreeFunctions.h │ │ │ ├── SFixedMemberFunctions.h │ │ │ ├── UFixed.h │ │ │ ├── UFixedFreeFunctions.h │ │ │ ├── UFixedMemberFunctions.h │ │ │ └── Utils.h │ │ ├── FixedPointsCommon.h │ │ ├── FixedPointsCommon │ │ │ ├── FixedPointsCommon.h │ │ │ ├── SFixedCommon.h │ │ │ └── UFixedCommon.h │ │ ├── Meta │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── library.json │ │ │ └── library.properties │ │ └── keywords.txt │ │ ├── Rotary │ │ ├── Meta │ │ │ ├── README.md │ │ │ └── library.properties │ │ ├── Rotary.cpp │ │ └── Rotary.h │ │ └── TimerOne │ │ ├── Meta │ │ ├── README.md │ │ ├── library.json │ │ └── library.properties │ │ ├── TimerOne.cpp │ │ ├── TimerOne.h │ │ ├── config │ │ └── known_16bit_timers.h │ │ └── keywords.txt └── MaxMixTests │ ├── .gitignore │ ├── include │ ├── README │ └── main.h │ ├── lib │ └── README │ ├── platformio.ini │ ├── src │ └── main.cpp │ └── test │ └── README ├── LICENSE ├── LICENSES.md ├── NOTICE └── README.md /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Maxmix 2 | 3 | A big welcome and thank you for considering contributing to Maxmix! It’s people like you that make it a reality for users in our community. 4 | 5 | Reading and following these guidelines will help us make the contribution process easy and effective for everyone involved. It also communicates that you agree to respect the time of the developers managing and developing these open source projects. In return, we will reciprocate that respect by addressing your issue, assessing changes, and helping you finalize your pull requests. 6 | 7 | ## Quicklinks 8 | 9 | - [Contributing to Maxmix](#contributing-to-maxmix) 10 | - [Quicklinks](#quicklinks) 11 | - [Code of Conduct](#code-of-conduct) 12 | - [Getting Started](#getting-started) 13 | - [Issues](#issues) 14 | - [Priorities](#priorities) 15 | - [Pull Requests](#pull-requests) 16 | - [Getting Help](#getting-help) 17 | 18 | ## Code of Conduct 19 | 20 | We take our open source community seriously and hold ourselves and other contributors to high standards of communication. By participating and contributing to this project, you agree to uphold our [Code of Conduct](https://github.com/t3knomanzer/.github/blob/master/CODE_OF_CONDUCT.md). 21 | 22 | ## Getting Started 23 | 24 | Contributions are made to this repo via Issues and Pull Requests (PRs). A few general guidelines that cover both: 25 | 26 | - Search for existing Issues and PRs before creating your own. 27 | - We work hard to makes sure issues are handled in a timely manner but, depending on the impact, it could take a while to investigate the root cause. A friendly ping in the comment thread to the submitter or a contributor can help draw attention if your issue is blocking. 28 | - If you've never contributed before, see [the first timer's guide](https://auth0.com/blog/a-first-timers-guide-to-an-open-source-project/) for resources and tips on how to get started. 29 | 30 | ### Issues 31 | 32 | Issues should be used to report problems with the application, request a new feature, or to discuss potential changes before a PR is created. When you create a new Issue, a template will be loaded that will guide you through collecting and providing the information we need to investigate. 33 | 34 | If you find an Issue that addresses the problem you're having, please add your own reproduction information to the existing issue rather than creating a new one. Adding a [reaction](https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) can also help be indicating to our maintainers that a particular problem is affecting more than just the reporter. 35 | 36 | ### Priorities 37 | 38 | In order to ensure the project moving forward smoothly, we utilize [Kanban Boards](https://github.com/t3knomanzer/maxmix-software/projects) to plan releases. 39 | For every release we try to find a balance between bug fixes, new features and code maintnance. 40 | The selected issues are moved to the **To Do** column of the board for the next release. After that, a priority is assigned to the issues as a label to indicate the order in which issues whould be addressed. 41 | Contributors are then free to assign issues to themselves if they haven't done yet and move them over to the **In propgress** column to inform others of the current status. 42 | After a PR has been reviewed and approved, the issue is automatically moved to the **Done** column. 43 | 44 | Contributors are free to work on issues that are not part of the next release. However, by doing so, you must understand that PRs won't be reviewed until the current release is completed and you must be willing to rebase as other changes get merged into master. 45 | 46 | ### Pull Requests 47 | 48 | PRs are always welcome and can be a quick way to get your fix or improvement slated for the next release. In general, PRs should: 49 | 50 | - Only fix/add the functionality in question **OR** address wide-spread whitespace/style issues, not both. 51 | - Add unit or integration tests for fixed or changed functionality (if a test suite already exists). 52 | - Address a single concern in the least number of changed lines as possible. 53 | - Be accompanied by a complete Pull Request template (loaded automatically when a PR is created). 54 | 55 | For changes that address core functionality or would require breaking changes (e.g. a major release), it's best to open an Issue to discuss your proposal first. This is not required but can save time creating and reviewing changes. 56 | 57 | In general, we follow the ["fork-and-pull" Git workflow](https://github.com/susam/gitpr) 58 | 59 | 1. Fork the repository to your own Github account 60 | 2. Clone the project to your machine 61 | 3. Create a branch locally with a succinct but descriptive name 62 | 4. Commit changes to the branch 63 | 5. Following any formatting and testing guidelines specific to this repo 64 | 6. Push changes to your fork 65 | 7. Open a PR in our repository and follow the PR template so that we can efficiently review the changes. 66 | 67 | ## Getting Help 68 | 69 | If you need some help, feel free to [mention](https://guides.github.com/features/issues/#:~:text=like%20this%20functionality).-,%40mentions,to%20send%20them%20a%20notification.) other developers in the comments of your issue or PR. 70 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: 5 | labels: bug 6 | assignees: 7 | 8 | --- 9 | 10 | **Guidelines** 11 | - [ ] I have reviewed the [guidelines for contributing](https://github.com/t3knomanzer/maxmix-software/blob/master/.github/CONTRIBUTING.md) to this repository. 12 | 13 | **Describe the bug** 14 | A clear and concise description of what the bug is. 15 | 16 | **To Reproduce** 17 | Steps to reproduce the behavior: 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Screenshots** 27 | If applicable, add screenshots to help explain your problem. 28 | 29 | **System information:** 30 | - OS version: [e.g. Windows 10 x64 1008] 31 | - Firmware version: [e.g 1.0.4] 32 | 33 | **Additional context** 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: GitHub Community Forum 4 | url: https://github.community/ 5 | about: Please ask and answer questions here. 6 | - name: GitHub Security Bug Bounty 7 | url: https://bounty.github.com/ 8 | about: Please report security vulnerabilities here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: 5 | labels: feature 6 | assignees: 7 | 8 | --- 9 | 10 | **Guidelines** 11 | - [ ] I have reviewed the [guidelines for contributing](https://github.com/t3knomanzer/maxmix-software/blob/master/.github/CONTRIBUTING.md) to this repository. 12 | 13 | **Is your feature request related to a problem? Please describe.** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the solution you'd like** 17 | A clear and concise description of what you want to happen. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ## Issues 3 | - Fixes # 4 | - Resolves # 5 | - Closes # 6 | 7 | ## Description 8 | Please explain the changes you made here. 9 | 10 | ## Types of changes 11 | _Put an `x` in the boxes that apply_ 12 | 13 | - [ ] Bugfix (non-breaking change which fixes an issue) 14 | - [ ] New feature (non-breaking change which adds functionality) 15 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 16 | - [ ] Documentation Update (if none of the other choices apply) 17 | 18 | ## Checklist 19 | 20 | _Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._ 21 | 22 | - [ ] Requested changes are in a branch 23 | - [ ] Compiled and tested requested changes on target hardware (PC, device) 24 | - [ ] Updated the documentation, if necessary 25 | - [ ] Updated the LICENSES file, if necessary 26 | - [ ] Reviewed the [guidelines for contributing](../CONTRIBUTING.md) to this repository 27 | 28 | 29 | ## Further comments 30 | 31 | If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... 32 | -------------------------------------------------------------------------------- /.github/resources/color-dark-2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/t3knomanzer/maxmix-software/b3d1937d15a5625133d205aab6ff8689d356cc37/.github/resources/color-dark-2048.png -------------------------------------------------------------------------------- /.github/workflows/Release.yml: -------------------------------------------------------------------------------- 1 | name: 'release' 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*.*.*' 7 | 8 | jobs: 9 | build: 10 | runs-on: windows-latest 11 | 12 | defaults: 13 | run: 14 | shell: cmd 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | fetch-depth: 0 20 | 21 | - name: Get tag version 22 | id: get_version 23 | run: | 24 | echo VERSION="${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV 25 | shell: bash 26 | 27 | - name: Check version 28 | run: | 29 | echo 1: ${{env.VERSION}} 30 | echo 2: $VERSION 31 | 32 | - name: Setup Python 3.8 33 | uses: actions/setup-python@v2 34 | with: 35 | python-version: 3.8 36 | 37 | - name: Setup PlatformIO 38 | run: | 39 | python -m pip install --upgrade pip 40 | pip install -U platformio 41 | 42 | - name: Build Firmware - Full step 43 | run: platformio run --project-dir .\Embedded\Maxmix -e nano-cli -e nano-cli-halfstep 44 | 45 | - name: Setup NuGet.exe 46 | uses: NuGet/setup-nuget@v1 47 | - name: Setup MSBuild.exe 48 | uses: microsoft/setup-msbuild@v1 49 | - name: Setup MSBuild ExtensionPack 50 | run: choco install msbuild.extensionpack --version=4.0.15.0 -y 51 | 52 | - name: Restore Application packages 53 | run: nuget restore Desktop\Application\MaxMix.sln 54 | - name: Build Application 55 | run: msbuild Desktop\Build.msbuild -p:SolutionDir=Application -p:Version=${{env.VERSION}}.0 -p:Configuration=Debug -p:Platform="Any CPU" 56 | 57 | - name: Restore DriverInstaller packages 58 | run: nuget restore Desktop\DriverInstaller\DriverInstaller.sln 59 | - name: Build DriverInstaller 60 | run: msbuild Desktop\Build.msbuild -p:SolutionDir=DriverInstaller -p:Version=${{env.VERSION}}.0 -p:Configuration=Debug -p:Platform="Any CPU" 61 | 62 | - name: Restore FirmwareInstaller packages 63 | run: nuget restore Desktop\FirmwareInstaller\FirmwareInstaller.sln 64 | - name: Build FirmwareInstaller 65 | run: msbuild Desktop\Build.msbuild -p:SolutionDir=FirmwareInstaller -p:Version=${{env.VERSION}}.0 -p:Configuration=Debug -p:Platform="Any CPU" 66 | 67 | - name: Setup Advanced Installer 68 | run: choco install advanced-installer --version=17.1.2 -y 69 | - name: Add Advanced Installer to path 70 | shell: bash 71 | run: echo "C:/Program Files (x86)/Caphyon/Advanced Installer 17.1.2/bin/x86" >> $GITHUB_PATH 72 | - name: Register Advanced Installer 73 | run: AdvancedInstaller.com /register ${{secrets.ADVANCEDINSTALLER_LICENSE}} 74 | 75 | - name: Set Installer version 76 | run: AdvancedInstaller.com /edit Desktop\Installer\Maxmix.aip /SetVersion ${{env.VERSION}} 77 | 78 | - name: Build Installer 79 | run: AdvancedInstaller.com /build Desktop\Installer\Maxmix.aip 80 | 81 | - name: Create Release 82 | id: create-release 83 | uses: actions/create-release@v1 84 | env: 85 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 86 | with: 87 | tag_name: ${{env.VERSION}} 88 | release_name: ${{env.VERSION}} 89 | body: '' 90 | draft: false 91 | prerelease: true 92 | 93 | - name: Upload Release Assets - Installer 94 | id: upload-release-assets-installer 95 | uses: actions/upload-release-asset@v1 96 | env: 97 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 98 | with: 99 | upload_url: ${{ steps.create-release.outputs.upload_url }} 100 | asset_path: Desktop\Installer\Builds\Maxmix.msi 101 | asset_name: Maxmix.${{env.VERSION}}.msi 102 | asset_content_type: application/zip 103 | 104 | - name: Upload Release Assets - Firmware (FullStep) 105 | id: upload-release-assets-firmware-fullstep 106 | uses: actions/upload-release-asset@v1 107 | env: 108 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 109 | with: 110 | upload_url: ${{ steps.create-release.outputs.upload_url }} 111 | asset_path: Embedded\Maxmix\.pio\build\nano-cli\firmware.hex 112 | asset_name: Maxmix.${{env.VERSION}}.hex 113 | asset_content_type: application/zip 114 | 115 | - name: Upload Release Assets - Firmware (HalfStep) 116 | id: upload-release-assets-firmware-halfstep 117 | uses: actions/upload-release-asset@v1 118 | env: 119 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 120 | with: 121 | upload_url: ${{ steps.create-release.outputs.upload_url }} 122 | asset_path: Embedded\Maxmix\.pio\build\nano-cli-halfstep\firmware.hex 123 | asset_name: Maxmix.${{env.VERSION}}_Half-step.hex 124 | asset_content_type: application/zip 125 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration.yml: -------------------------------------------------------------------------------- 1 | name: 'Continuous Integration' 2 | on: [push, pull_request] 3 | defaults: 4 | run: 5 | shell: cmd 6 | 7 | jobs: 8 | build-firware: 9 | name: 'Build MaxMix Firmware' 10 | runs-on: windows-latest 11 | steps: 12 | - name: Checkout Repo 13 | uses: actions/checkout@v2 14 | - name: Setup Python 3.8 15 | uses: actions/setup-python@v2 16 | with: 17 | python-version: 3.8 18 | - name: Setup PlatformIO 19 | run: | 20 | python -m pip install --upgrade pip 21 | pip install -U platformio 22 | - name: Build Firmware 23 | run: platformio run --project-dir .\Embedded\Maxmix -e nano-cli 24 | 25 | build-app: 26 | name: 'Build MaxMix App' 27 | runs-on: windows-latest 28 | steps: 29 | - name: Checkout Repo 30 | uses: actions/checkout@v2 31 | - name: Setup MSBuild.exe 32 | uses: microsoft/setup-msbuild@v1 33 | - name: Setup MSBuild ExtensionPack 34 | run: choco install msbuild.extensionpack --version=4.0.15.0 -y 35 | - name: Build 36 | run: msbuild Desktop\Build.msbuild -t:restore -p:SolutionDir=Application -p:Version=0.0.0.0 -p:Configuration=Release -p:Platform="Any CPU" 37 | 38 | build-driver-installer: 39 | name: 'Build Driver Installer' 40 | runs-on: windows-latest 41 | steps: 42 | - name: Checkout Repo 43 | uses: actions/checkout@v2 44 | - name: Setup MSBuild.exe 45 | uses: microsoft/setup-msbuild@v1 46 | - name: Setup MSBuild ExtensionPack 47 | run: choco install msbuild.extensionpack --version=4.0.15.0 -y 48 | - name: Build 49 | run: msbuild Desktop\Build.msbuild -t:restore -p:SolutionDir=DriverInstaller -p:Version=0.0.0.0 -p:Configuration=Release -p:Platform="Any CPU" 50 | 51 | build-firmware-installer: 52 | name: 'Build Firware Installer' 53 | runs-on: windows-latest 54 | steps: 55 | - name: Checkout Repo 56 | uses: actions/checkout@v2 57 | - name: Setup MSBuild.exe 58 | uses: microsoft/setup-msbuild@v1 59 | - name: Setup MSBuild ExtensionPack 60 | run: choco install msbuild.extensionpack --version=4.0.15.0 -y 61 | - name: Build 62 | run: msbuild Desktop\Build.msbuild -t:restore -p:SolutionDir=FirmwareInstaller -p:Version=0.0.0.0 -p:Configuration=Release -p:Platform="Any CPU" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE 2 | .vs 3 | .vs/ 4 | Desktop/**/bin 5 | .pio 6 | .vscode/ 7 | Desktop/**/obj 8 | 9 | Desktop/**/packages 10 | # Build 11 | Embedded/MaxMix/build 12 | bin/ 13 | BuildSystem/build 14 | obj/ 15 | BuildSystem/release 16 | packages/ 17 | 18 | # Advanced Installer 19 | Desktop/Installer/*-cache/ 20 | Desktop/Installer/Setup Files/ 21 | Desktop/Installer/Builds/ 22 | Desktop/Installer/*.back.aip 23 | 24 | # Excludes 25 | !Desktop/Resources/bin/ 26 | 27 | # Build System 28 | BuildSystem/build 29 | BuildSystem/release 30 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | 140 Ruben Henares 2 | 19 GitHub Action 3 | 16 GIT-Desktop 4 | 13 Ryan Caltabiano 5 | 11 Sébastien Atoch 6 | 2 SchemingWeasels 7 | 1 Maxwell J Branvall <36718512+MaxBranvall@users.noreply.github.com> 8 | 1 rubenhenares 9 | -------------------------------------------------------------------------------- /BuildSystem/scripts/build-all.cmd: -------------------------------------------------------------------------------- 1 | :: ================================================= 2 | :: This script compiles the 2 versions of the firmware 3 | :: for different rotary encoder condfigurations (full/half step) 4 | :: It assumes the arduino-cli is installed and added to the path. 5 | :: If you haven't done so, run install-dependencies.cmd first. 6 | :: ================================================= 7 | 8 | @echo off 9 | echo ==== MaxMix Project Firmware Builder ==== 10 | 11 | set ROOT_DIR=%CD%\.. 12 | set BUILD_DIR=%ROOT_DIR%\build 13 | set RELEASE_DIR=%ROOT_DIR%\release 14 | set MAIN_INO=%ROOT_DIR%\..\Embedded\MaxMix\MaxMix.ino 15 | 16 | rmdir /s /q %RELEASE_DIR% 17 | mkdir %RELEASE_DIR% 18 | 19 | rmdir /s /q %BUILD_DIR% 20 | arduino-cli compile -b arduino:avr:nano:cpu=atmega328 -v --build-path %BUILD_DIR% --build-properties "build.extra_flags=-DVERSION_MAJOR=9 -DVERSION_MINOR=9 -DVERSION_PATCH=9" %MAIN_INO% 21 | move %BUILD_DIR%\MaxMix.ino.hex %RELEASE_DIR%\MaxMix.ino.hex 22 | 23 | rmdir /s /q %BUILD_DIR% 24 | arduino-cli compile -b arduino:avr:nano:cpu=atmega328 -v --build-path %BUILD_DIR% --build-properties "build.extra_flags=-DHALF_STEP -DVERSION_MAJOR=9 -DVERSION_MINOR=9 -DVERSION_PATCH=9" %MAIN_INO% 25 | move %BUILD_DIR%\MaxMix.ino.hex %RELEASE_DIR%\MaxMix.halfstep.ino.hex 26 | 27 | rmdir /s /q %BUILD_DIR% 28 | 29 | pause 30 | -------------------------------------------------------------------------------- /BuildSystem/scripts/install-dependencies.cmd: -------------------------------------------------------------------------------- 1 | :: ================================================= 2 | :: This script sets up the arduino toolchain needed 3 | :: to compile the firmware. 4 | :: It uses the windows package manager chocolatey (https://chocolatey.org/) 5 | :: and it assumes it is already installed. 6 | :: It needs to be executed from an console with admin rights. 7 | :: ================================================= 8 | 9 | @echo off 10 | 11 | choco install arduino-cli --version=0.12.1 -y 12 | arduino-cli core install arduino:avr 13 | 14 | pause 15 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ## [1.0.0] - 2017-06-20 10 | ### Added 11 | - Sample. 12 | 13 | ### Changed 14 | - Sample. 15 | 16 | ### Removed 17 | - Sample. 18 | 19 | ### Fixed 20 | - Sample. 21 | 22 | [Unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD 23 | [1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0 -------------------------------------------------------------------------------- /Desktop/Application/MaxMix.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30002.166 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaxMix", "MaxMix\MaxMix.csproj", "{B45D3A30-5617-494C-AB4D-44946056A5F8}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaxMixTest", "MaxMixTest\MaxMixTest.csproj", "{3496C4A3-CF21-49AA-8F55-CBD428D960E7}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Debug|x64.ActiveCfg = Debug|Any CPU 23 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Debug|x64.Build.0 = Debug|Any CPU 24 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Debug|x86.ActiveCfg = Debug|Any CPU 25 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Debug|x86.Build.0 = Debug|Any CPU 26 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Release|x64.ActiveCfg = Release|Any CPU 29 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Release|x64.Build.0 = Release|Any CPU 30 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Release|x86.ActiveCfg = Release|Any CPU 31 | {B45D3A30-5617-494C-AB4D-44946056A5F8}.Release|x86.Build.0 = Release|Any CPU 32 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Debug|x64.ActiveCfg = Debug|Any CPU 35 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Debug|x64.Build.0 = Debug|Any CPU 36 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Debug|x86.ActiveCfg = Debug|Any CPU 37 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Debug|x86.Build.0 = Debug|Any CPU 38 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Release|x64.ActiveCfg = Release|Any CPU 41 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Release|x64.Build.0 = Release|Any CPU 42 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Release|x86.ActiveCfg = Release|Any CPU 43 | {3496C4A3-CF21-49AA-8F55-CBD428D960E7}.Release|x86.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {5EBDD4A7-0D3E-4AE4-9BF3-2D92D0D1F85E} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | True 15 | 16 | 17 | True 18 | 19 | 20 | 5 21 | 22 | 23 | True 24 | 25 | 26 | 60 27 | 28 | 29 | 150 30 | 31 | 32 | 4294901760 33 | 34 | 35 | 4278190335 36 | 37 | 38 | 4294901760 39 | 40 | 41 | 4294902015 42 | 43 | 44 | MODE_OUTPUT 45 | 46 | 47 | True 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using MaxMix.ViewModels; 2 | using Sentry; 3 | using Sentry.Protocol; 4 | using System; 5 | using System.Diagnostics; 6 | using System.Reflection; 7 | using System.Threading; 8 | using System.Windows; 9 | using System.Windows.Threading; 10 | 11 | namespace MaxMix 12 | { 13 | /// 14 | /// Interaction logic for App.xaml 15 | /// 16 | public partial class App : Application 17 | { 18 | IDisposable _errorReporter; 19 | private static Mutex _singleInstanceMutex = null; 20 | 21 | private void InitErrorReporting() 22 | { 23 | _errorReporter = SentrySdk.Init("https://54cf266b03ed4ee380b0577653172a98@o431430.ingest.sentry.io/5382488"); 24 | SentrySdk.ConfigureScope(scope => 25 | { 26 | scope.User = new User { Username = Environment.MachineName }; 27 | }); 28 | 29 | } 30 | 31 | void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) 32 | { 33 | SentrySdk.CaptureException(e.Exception); 34 | _errorReporter.Dispose(); 35 | } 36 | 37 | private bool IsApplicationRunning() 38 | { 39 | var assemblyName = Assembly.GetExecutingAssembly().GetName().Name; 40 | _singleInstanceMutex = new Mutex(true, assemblyName, out bool mutexAcquired); 41 | return mutexAcquired; 42 | } 43 | 44 | private void ApplicationStartup(object sender, StartupEventArgs e) 45 | { 46 | if (!IsApplicationRunning()) 47 | { 48 | // Application is already running 49 | Debug.WriteLine("[App] Application is already running, exiting."); 50 | Current.Shutdown(); 51 | return; 52 | } 53 | 54 | if (!Debugger.IsAttached) 55 | { 56 | // Initialize error reporing only if not running from Visual Studio. 57 | InitErrorReporting(); 58 | DispatcherUnhandledException += OnDispatcherUnhandledException; 59 | } 60 | 61 | var window = new MainWindow(); 62 | 63 | var assemblyName = Assembly.GetExecutingAssembly().GetName().Name; 64 | string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); 65 | window.Title = string.Format("{0} {1}", assemblyName, assemblyVersion); 66 | 67 | var dataContext = new MainViewModel(); 68 | dataContext.ExitRequested += OnExitRequested; 69 | 70 | window.DataContext = dataContext; 71 | dataContext.Start(); 72 | } 73 | 74 | private void OnExitRequested(object sender, EventArgs e) 75 | { 76 | var viewModel = (MainViewModel)sender; 77 | viewModel.Stop(); 78 | 79 | // Calling dispose explicitly on closing so the icon dissapears from the windows task bar. 80 | var window = (MainWindow)Current.MainWindow; 81 | window.taskbarIcon.Dispose(); 82 | if (_errorReporter != null) 83 | { 84 | _errorReporter.Dispose(); 85 | } 86 | _singleInstanceMutex.Dispose(); 87 | 88 | Current.Shutdown(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/Framework/AppExtensions.cs: -------------------------------------------------------------------------------- 1 | using MaxMix.Services.Audio; 2 | using MaxMix.Services.Communication; 3 | using MaxMix.ViewModels; 4 | using System; 5 | 6 | namespace MaxMix.Framework 7 | { 8 | internal static class AppExtensions 9 | { 10 | public static DeviceSettings ToDeviceSettings(this SettingsViewModel model) 11 | { 12 | DeviceSettings settings = DeviceSettings.Default(); 13 | settings.sleepAfterSeconds = (byte)(model.SleepWhenInactive ? model.SleepAfterSeconds : 0); 14 | settings.accelerationPercentage = (byte)model.AccelerationPercentage; 15 | settings.continuousScroll = model.LoopAroundItems; 16 | //_settingsViewModel.DoubleTapTime 17 | settings.volumeMinColor.SetBytes(BitConverter.GetBytes(model.VolumeMinColor)); 18 | settings.volumeMaxColor.SetBytes(BitConverter.GetBytes(model.VolumeMaxColor)); 19 | settings.mixChannelAColor.SetBytes(BitConverter.GetBytes(model.MixChannelAColor)); 20 | settings.mixChannelBColor.SetBytes(BitConverter.GetBytes(model.MixChannelBColor)); 21 | return settings; 22 | } 23 | 24 | public static SessionData ToSessionData(this ISession[] audioDevices, int index) 25 | { 26 | SessionData session = SessionData.Default(); 27 | session.name = audioDevices[index].DisplayName; 28 | session.data.id = (byte)index; 29 | session.data.isDefault = audioDevices[index].IsDefault; 30 | session.data.volume = (byte)audioDevices[index].Volume; 31 | session.data.isMuted = audioDevices[index].IsMuted; 32 | return session; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/Framework/AttachedProperties/BalloonMessageProperty.cs: -------------------------------------------------------------------------------- 1 | using Hardcodet.Wpf.TaskbarNotification; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace MaxMix.Framework.AttachedProperties 10 | { 11 | internal class BalloonMessageProperty 12 | { 13 | public static readonly DependencyProperty BallonMessageProperty = DependencyProperty.RegisterAttached( 14 | "BallonMessage", 15 | typeof(string), 16 | typeof(BalloonMessageProperty), 17 | new PropertyMetadata(string.Empty, BallonMessageChanged)); 18 | 19 | private static void BallonMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 20 | { 21 | if (d is TaskbarIcon) 22 | { 23 | var obj = (TaskbarIcon)d; 24 | var oldArg = e.OldValue.ToString(); 25 | var newArg = e.NewValue.ToString(); 26 | 27 | // Check if the previous value was null, meaning this is the first 28 | // time this is called (application startup). 29 | // Or if the new value is null, meaning and invalid value was received. 30 | if (string.IsNullOrEmpty(oldArg) || 31 | string.IsNullOrEmpty(newArg)) 32 | return; 33 | 34 | obj.ShowBalloonTip("MaxMix", e.NewValue.ToString(), BalloonIcon.Info); 35 | } 36 | } 37 | 38 | public static string GetBallonMessage(DependencyObject obj) 39 | { 40 | return (string)obj.GetValue(BallonMessageProperty); 41 | } 42 | 43 | public static void SetBallonMessage(DependencyObject obj, string value) 44 | { 45 | obj.SetValue(BallonMessageProperty, value); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/Framework/Converters/BoolToStringConverter.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.Windows; 7 | using System.Windows.Data; 8 | 9 | namespace MaxMix.Framework.Converters 10 | { 11 | public class BoolToStringConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 14 | { 15 | if (value != null && parameter != null) 16 | { 17 | var input = (bool)value; 18 | var param = (string[])parameter; 19 | 20 | if (input) 21 | return param[0]; 22 | else 23 | return param[1]; 24 | } 25 | 26 | return null; 27 | } 28 | 29 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 30 | { 31 | throw new InvalidOperationException("Should never be called"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/Framework/Converters/BoolToVisibilityConverter.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.Windows; 7 | using System.Windows.Data; 8 | 9 | namespace MaxMix.Framework.Converters 10 | { 11 | public class BoolToVisibilityConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 14 | { 15 | if (value != null) 16 | { 17 | var input = (bool)value; 18 | if (input) 19 | return Visibility.Visible; 20 | else 21 | return Visibility.Hidden; 22 | } 23 | 24 | return null; 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 28 | { 29 | throw new InvalidOperationException("Should never be called"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/Framework/Converters/ColorToUint32Converter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Data; 3 | using System.Windows.Media; 4 | 5 | namespace MaxMix.Framework.Converters 6 | { 7 | public class ColorToUint32Converter : IValueConverter 8 | { 9 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 10 | { 11 | if (value != null) 12 | { 13 | var input = (Color)value; 14 | var result = 0xFF << 24 | input.B << 16 | input.G << 8 | input.R; 15 | return (uint)result; 16 | } 17 | 18 | return 0; 19 | } 20 | 21 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 22 | { 23 | if(value != null) 24 | { 25 | var input = (uint)value; 26 | byte b = (byte)(input >> 16); 27 | byte g = (byte)(input >> 8); 28 | byte r = (byte)(input); 29 | return Color.FromRgb(r, g, b); 30 | } 31 | 32 | return Color.FromRgb(0, 0, 0); 33 | } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/Framework/Mvvm/ObservableObject.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace MaxMix.Framework.Mvvm 5 | { 6 | internal class ObservableObject : INotifyPropertyChanged 7 | { 8 | #region INotifyPropertyChanged 9 | public event PropertyChangedEventHandler PropertyChanged; 10 | #endregion 11 | 12 | #region Methods 13 | protected virtual void SetProperty(ref T field, T value, [CallerMemberName] string name = null) 14 | { 15 | if (field.Equals(value)) 16 | return; 17 | 18 | field = value; 19 | RaisePropertyChanged(name); 20 | } 21 | 22 | protected virtual void RaisePropertyChanged([CallerMemberName] string name = null) 23 | { 24 | if (string.IsNullOrEmpty(name)) 25 | return; 26 | 27 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 28 | } 29 | #endregion 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Desktop/Application/MaxMix/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  18 | 19 | 20 | 21 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 49 | 50 |