├── .gitignore ├── ColourControl ├── ColourControl.Designer.cs ├── ColourControl.cs ├── ColourControl.csproj ├── ColourControl.resx ├── HueSelector.cs ├── HueSelectorTypesEnum.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx └── Resources │ └── Colour Wheel.png ├── DesktopDuplication ├── DesktopDuplication.csproj ├── DesktopDuplicationException.cs ├── DesktopDuplicator.cs ├── DesktopFrame.cs ├── MovedRegion.cs ├── PointerInfo.cs ├── Properties │ └── AssemblyInfo.cs ├── app.config └── packages.config ├── LICENSE ├── MaxArdLifx2.ino ├── MaxLifx.sln ├── MaxLifx ├── App.config ├── ColourThemes │ ├── BerriesColourTheme.cs │ ├── BlackAndWhite.cs │ ├── BlueAndOrangeColourTheme.cs │ ├── BlueAndWhite.cs │ ├── BlueColourTheme.cs │ ├── GreenColourTheme.cs │ ├── IColourTheme.cs │ ├── RainbowColourTheme.cs │ ├── RainbowV2ColourTheme.cs │ ├── RandomColourTheme.cs │ ├── RedAndOrangeColourTheme.cs │ ├── RedColourTheme.cs │ └── SpokesColourTheme.cs ├── Controls │ ├── BrightnessSelector │ │ ├── BrightnessSelector.cs │ │ └── BrightnessSelectorHandle.cs │ ├── ColourStrategy │ │ ├── AnalogousColourStrategy.cs │ │ ├── FreeColourStrategy.cs │ │ ├── IColourStrategy.cs │ │ └── OppositeColourStrategy.cs │ ├── HueSelector │ │ ├── HueSelector.cs │ │ └── HueSelectorHandle.cs │ ├── SpectrumAnalyser │ │ ├── SampleAggregator.cs │ │ ├── SpectrumAnalyser.Drawing.cs │ │ ├── SpectrumAnalyser.Overrides.cs │ │ ├── SpectrumAnalyser.cs │ │ ├── SpectrumAnalyserEngine.cs │ │ └── SpectrumAnalyserHandle.cs │ └── Timeline │ │ ├── Timeline.Overrides.cs │ │ ├── Timeline.cs │ │ └── TimelineEvent.cs ├── LightControlThread.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── MaxLifx.csproj ├── Payload │ ├── GetColourZonesPayload.cs │ ├── GetLabelPayload.cs │ ├── GetServicePayload.cs │ ├── GetVersionPayload.cs │ ├── IPayload.cs │ ├── SetColourPayload.cs │ └── SetColourZonesPayload.cs ├── Processors │ ├── CursorPosition.cs │ ├── IProcessor.cs │ ├── ProcessorBase.cs │ ├── ProcessorSettings │ │ ├── ISettings.cs │ │ ├── ScreenColourSettings.cs │ │ ├── SettingsBase.cs │ │ ├── SoundGeneratorSettings.cs │ │ └── SoundResponseSettings.cs │ ├── ScreenColourProcessor.cs │ ├── SoundGeneratorProcessor.cs │ └── SoundResponseProcessor.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── Colour Wheel.png │ ├── crosshair.png │ └── m (1).png ├── Scheduler │ └── SchedulerEvent.cs ├── Settings.cs ├── Sound │ └── Sound.cs ├── UIs │ ├── About.Designer.cs │ ├── About.cs │ ├── About.resx │ ├── AdvancedDiscover.Designer.cs │ ├── AdvancedDiscover.cs │ ├── AdvancedDiscover.resx │ ├── AssignAreaToBulbForm.Designer.cs │ ├── AssignAreaToBulbForm.cs │ ├── AssignAreaToBulbForm.resx │ ├── EditTimelineEvent.Designer.cs │ ├── EditTimelineEvent.cs │ ├── EditTimelineEvent.resx │ ├── FakeBulb.Designer.cs │ ├── FakeBulb.cs │ ├── FakeBulb.resx │ ├── Form2.Designer.cs │ ├── Form2.cs │ ├── Form2.resx │ ├── ProcessorUIs │ │ ├── ScreenColourUI.Designer.cs │ │ ├── ScreenColourUI.cs │ │ ├── ScreenColourUI.resx │ │ ├── SoundGeneratorUI.Designer.cs │ │ ├── SoundGeneratorUI.cs │ │ ├── SoundGeneratorUI.resx │ │ ├── SoundMessage.cs │ │ ├── SoundResponseUI.Designer.cs │ │ ├── SoundResponseUI.cs │ │ └── SoundResponseUI.resx │ └── UiFormBase.cs ├── Utils.cs └── packages.config ├── MaxLifxBulbController ├── Bulb.cs ├── HomebrewDevicePayloadCache.cs ├── MaxLifxBulbController.cs ├── MaxLifxBulbController.csproj ├── PacketFactory.cs ├── Payload │ ├── GetColourZonesPayload.cs │ ├── GetLabelPayload.cs │ ├── GetServicePayload.cs │ ├── GetVersionPayload.cs │ ├── IPayload.cs │ ├── SetColourPayload.cs │ ├── SetColourZonesPayload.cs │ ├── SetHomebrewColourZonesPayload.cs │ ├── SetMaxLifxColourPayload.cs │ └── SetPowerPayload.cs ├── Properties │ └── AssemblyInfo.cs ├── Utils.cs └── packages.config ├── MaxLifxCmd ├── App.config ├── MaxLifxCmd.csproj ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── Media ├── Demo1.gif ├── Demo2.gif └── DemoThmstec.gif ├── NAudio license.txt ├── NAudio.WindowsMediaFormat.dll ├── NAudio.dll ├── NAudio.pdb ├── NAudio.xml ├── README.md └── nAudio-readme.txt /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Dd]ebugPublic/ 12 | [Rr]elease/ 13 | [Rr]eleases/ 14 | [Bb]in/ 15 | [Oo]bj/ 16 | *.DotSettings 17 | # NuGet Packages 18 | *.nupkg 19 | # The packages folder can be ignored because of Package Restore 20 | **/packages/* 21 | # except build/, which is used as an MSBuild target. 22 | !**/packages/build/ 23 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 24 | #!**/packages/repositories.config 25 | 26 | -------------------------------------------------------------------------------- /ColourControl/ColourControl.Designer.cs: -------------------------------------------------------------------------------- 1 | using ColourControl; 2 | 3 | namespace ColourControl 4 | { 5 | partial class ColourControl 6 | { 7 | /// 8 | /// Required designer variable. 9 | /// 10 | private System.ComponentModel.IContainer components = null; 11 | 12 | /// 13 | /// Clean up any resources being used. 14 | /// 15 | /// true if managed resources should be disposed; otherwise, false. 16 | protected override void Dispose(bool disposing) 17 | { 18 | if (disposing && (components != null)) 19 | { 20 | components.Dispose(); 21 | } 22 | base.Dispose(disposing); 23 | } 24 | 25 | #region Component Designer generated code 26 | 27 | /// 28 | /// Required method for Designer support - do not modify 29 | /// the contents of this method with the code editor. 30 | /// 31 | private void InitializeComponent() 32 | { 33 | this.hueSelector1 = new HueSelector(); 34 | this.SuspendLayout(); 35 | // 36 | // hueSelector1 37 | // 38 | this.hueSelector1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 39 | | System.Windows.Forms.AnchorStyles.Left) 40 | | System.Windows.Forms.AnchorStyles.Right))); 41 | this.hueSelector1.Location = new System.Drawing.Point(0, 0); 42 | this.hueSelector1.Margin = new System.Windows.Forms.Padding(0); 43 | this.hueSelector1.Name = "hueSelector1"; 44 | this.hueSelector1.Size = new System.Drawing.Size(150, 150); 45 | this.hueSelector1.TabIndex = 0; 46 | this.hueSelector1.Text = "hueSelector1"; 47 | // 48 | // ColourControl 49 | // 50 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 51 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 52 | this.BackColor = System.Drawing.SystemColors.Control; 53 | this.Controls.Add(this.hueSelector1); 54 | this.Margin = new System.Windows.Forms.Padding(0); 55 | this.Name = "ColourControl"; 56 | this.ResumeLayout(false); 57 | 58 | } 59 | 60 | #endregion 61 | 62 | private HueSelector hueSelector1; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ColourControl/ColourControl.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 ColourControl 12 | { 13 | public partial class ColourControl: UserControl 14 | { 15 | public ColourControl() 16 | { 17 | InitializeComponent(); 18 | hueSelector1.HuesChanged += HueSelector1_HuesChanged; 19 | } 20 | 21 | private void HueSelector1_HuesChanged(object sender, EventArgs e) 22 | { 23 | HuesChanged(null, null); 24 | } 25 | 26 | [Category("Action"), Description("Fires when hues change.")] 27 | public event EventHandler HuesChanged; 28 | 29 | public List GetHues() { return hueSelector1.GetHues(); } 30 | public void SetHues(List hues) { hueSelector1.SetHues(hues); Invalidate(); } 31 | 32 | public bool Invert { get { return hueSelector1.Invert; } set { hueSelector1.Invert = value; } } 33 | [Category("Behavior"), Description("Determines how many handles there are")] 34 | public int HandleCount { get { return hueSelector1.HandleCount; } set { hueSelector1.HandleCount = value; } } 35 | [Category("Behavior"), Description("Determines whether a range is required")] 36 | public bool RangeRequired { get { return hueSelector1.RangeRequired; } set { hueSelector1.RangeRequired = value; } } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ColourControl/ColourControl.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {22CE06C4-8DDC-47EA-81E9-855C9BDE094E} 8 | Library 9 | Properties 10 | ColourControl 11 | ColourControl 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | UserControl 48 | 49 | 50 | ColourControl.cs 51 | 52 | 53 | Component 54 | 55 | 56 | 57 | 58 | True 59 | True 60 | Resources.resx 61 | 62 | 63 | 64 | 65 | 66 | ColourControl.cs 67 | 68 | 69 | ResXFileCodeGenerator 70 | Resources.Designer.cs 71 | 72 | 73 | 74 | 75 | 76 | 77 | 84 | -------------------------------------------------------------------------------- /ColourControl/ColourControl.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 | -------------------------------------------------------------------------------- /ColourControl/HueSelectorTypesEnum.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 ColourControl 8 | { 9 | /*public class HueSelectorTypesEnum 10 | { 11 | public enum HueSelectorTypes 12 | { 13 | OneHandle, 14 | TwoHandlesOpposite, 15 | ThreeHandlesOpposite, 16 | TwoHandleRange 17 | } 18 | }*/ 19 | } 20 | -------------------------------------------------------------------------------- /ColourControl/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("ColourControl")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ColourControl")] 13 | [assembly: AssemblyCopyright("Copyright © 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("22ce06c4-8ddc-47ea-81e9-855c9bde094e")] 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 | -------------------------------------------------------------------------------- /ColourControl/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 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 ColourControl.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("ColourControl.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 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap ColourWheel { 67 | get { 68 | object obj = ResourceManager.GetObject("ColourWheel", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ColourControl/Resources/Colour Wheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/ColourControl/Resources/Colour Wheel.png -------------------------------------------------------------------------------- /DesktopDuplication/DesktopDuplication.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | DirectX11_2 6 | Debug 7 | AnyCPU 8 | {222C215B-663F-4BD6-9B3E-8FA99C867B22} 9 | Library 10 | Properties 11 | DesktopDuplication 12 | DesktopDuplication 13 | v4.5 14 | 512 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | true 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | true 36 | 37 | 38 | 39 | ..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll 40 | 41 | 42 | ..\packages\SharpDX.Direct3D11.4.2.0\lib\net45\SharpDX.Direct3D11.dll 43 | 44 | 45 | ..\packages\SharpDX.DXGI.4.2.0\lib\net45\SharpDX.DXGI.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /DesktopDuplication/DesktopDuplicationException.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 DesktopDuplication 8 | { 9 | public class DesktopDuplicationException : Exception 10 | { 11 | public DesktopDuplicationException(string message) 12 | : base(message) { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DesktopDuplication/DesktopFrame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DesktopDuplication 9 | { 10 | /// 11 | /// Provides image data, cursor data, and image metadata about the retrieved desktop frame. 12 | /// 13 | public class DesktopFrame 14 | { 15 | /// 16 | /// Gets the bitmap representing the last retrieved desktop frame. This image spans the entire bounds of the specified monitor. 17 | /// 18 | public Bitmap DesktopImage { get; internal set; } 19 | 20 | /// 21 | /// Gets a list of the rectangles of pixels in the desktop image that the operating system moved to another location within the same image. 22 | /// 23 | /// 24 | /// To produce a visually accurate copy of the desktop, an application must first process all moved regions before it processes updated regions. 25 | /// 26 | public MovedRegion[] MovedRegions { get; internal set; } 27 | 28 | /// 29 | /// Returns the list of non-overlapping rectangles that indicate the areas of the desktop image that the operating system updated since the last retrieved frame. 30 | /// 31 | /// 32 | /// To produce a visually accurate copy of the desktop, an application must first process all moved regions before it processes updated regions. 33 | /// 34 | public Rectangle[] UpdatedRegions { get; internal set; } 35 | 36 | /// 37 | /// The number of frames that the operating system accumulated in the desktop image surface since the last retrieved frame. 38 | /// 39 | public int AccumulatedFrames { get; internal set; } 40 | 41 | /// 42 | /// Gets the location of the top-left-hand corner of the cursor. This is not necessarily the same position as the cursor's hot spot, which is the location in the cursor that interacts with other elements on the screen. 43 | /// 44 | public Point CursorLocation { get; internal set; } 45 | 46 | /// 47 | /// Gets whether the cursor on the last retrieved desktop image was visible. 48 | /// 49 | public bool CursorVisible { get; internal set; } 50 | 51 | /// 52 | /// Gets whether the desktop image contains protected content that was already blacked out in the desktop image. 53 | /// 54 | public bool ProtectedContentMaskedOut { get; internal set; } 55 | 56 | /// 57 | /// Gets whether the operating system accumulated updates by coalescing updated regions. If so, the updated regions might contain unmodified pixels. 58 | /// 59 | public bool RectanglesCoalesced { get; internal set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /DesktopDuplication/MovedRegion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DesktopDuplication 9 | { 10 | /// 11 | /// Describes the movement of an image rectangle within a desktop frame. 12 | /// 13 | /// 14 | /// Move regions are always non-stretched regions so the source is always the same size as the destination. 15 | /// 16 | public struct MovedRegion 17 | { 18 | /// 19 | /// Gets the location from where the operating system copied the image region. 20 | /// 21 | public Point Source { get; internal set; } 22 | 23 | /// 24 | /// Gets the target region to where the operating system moved the image region. 25 | /// 26 | public Rectangle Destination { get; internal set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DesktopDuplication/PointerInfo.cs: -------------------------------------------------------------------------------- 1 | using SharpDX.DXGI; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DesktopDuplication 9 | { 10 | internal class PointerInfo 11 | { 12 | public byte[] PtrShapeBuffer; 13 | public OutputDuplicatePointerShapeInformation ShapeInfo; 14 | public System.Drawing.Point Position; 15 | public bool Visible; 16 | public int BufferSize; 17 | public int WhoUpdatedPositionLast; 18 | public long LastTimeStamp; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DesktopDuplication/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("DesktopDuplication")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DesktopDuplication")] 13 | [assembly: AssemblyCopyright("Copyright © 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("edd6f18d-3120-4f8d-84bd-157ad8881019")] 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 | -------------------------------------------------------------------------------- /DesktopDuplication/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DesktopDuplication/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MaxLifx/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/BerriesColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class BerriesColourTheme : IColourTheme 7 | { 8 | public void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | { 12 | switch (r.Next(3)) 13 | { 14 | case 0: 15 | hues[index] = r.Next(20) - 10; // red 16 | break; 17 | case 1: 18 | hues[index] = r.Next(30) + 225; // blue 19 | break; 20 | case 2: 21 | hues[index] = r.Next(20) + 290; // purple 22 | break; 23 | } 24 | 25 | } 26 | 27 | for (int index = 0; index < hueRanges.Count; index++) 28 | hueRanges[index] = r.Next(20); 29 | 30 | for (int index = 0; index < saturations.Count; index++) 31 | saturations[index] = r.NextDouble() / 10 + .9f; 32 | 33 | for (int index = 0; index < saturationRanges.Count; index++) 34 | saturationRanges[index] = r.NextDouble() / 10; 35 | 36 | if (!lockBrightness) 37 | for (int index = 0; index < brightnesses.Count; index++) 38 | brightnesses[index] = (float)(r.NextDouble()/5+.8f); 39 | 40 | if (!lockBrightness) 41 | for (int index = 0; index < brightnessRanges.Count; index++) 42 | brightnessRanges[index] = (float)(r.NextDouble() / 5); 43 | 44 | if (pastel) 45 | { 46 | for (int index = 0; index < saturations.Count; index++) 47 | saturations[index] = saturations[index]/2; 48 | 49 | for (int index = 0; index < brightnesses.Count; index++) 50 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/BlackAndWhite.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class BlackAndWhiteColourTheme : IColourTheme 7 | { 8 | public void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | { 12 | hues[index] = 0; 13 | } 14 | 15 | for (int index = 0; index < hueRanges.Count; index++) 16 | hueRanges[index] = 0; 17 | 18 | for (int index = 0; index < saturations.Count; index++) 19 | saturations[index] = 0f; 20 | 21 | for (int index = 0; index < saturationRanges.Count; index++) 22 | saturationRanges[index] = 0; 23 | 24 | if (!lockBrightness) 25 | for (int index = 0; index < brightnesses.Count; index++) 26 | brightnesses[index] = pastel ? .75f : .5f; 27 | 28 | if (!lockBrightness) 29 | for (int index = 0; index < brightnessRanges.Count; index++) 30 | brightnessRanges[index] = pastel ? .25f : .5f; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/BlueAndOrangeColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class BlueAndOrangeColourTheme : IColourTheme 7 | { 8 | public void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | { 12 | switch (r.Next(2)) 13 | { 14 | case 0: 15 | hues[index] = r.Next(30) + 225; // blue 16 | break; 17 | case 1: 18 | hues[index] = r.Next(30) + 10; // orange 19 | break; 20 | } 21 | 22 | } 23 | 24 | for (int index = 0; index < hueRanges.Count; index++) 25 | hueRanges[index] = r.Next(10); 26 | 27 | for (int index = 0; index < saturations.Count; index++) 28 | saturations[index] = r.NextDouble() / 5 + .8f; 29 | 30 | for (int index = 0; index < saturationRanges.Count; index++) 31 | saturationRanges[index] = r.NextDouble() / 4; 32 | 33 | if (!lockBrightness) 34 | for (int index = 0; index < brightnesses.Count; index++) 35 | brightnesses[index] = (float)(r.NextDouble()/2+.5f); 36 | 37 | if (!lockBrightness) 38 | for (int index = 0; index < brightnessRanges.Count; index++) 39 | brightnessRanges[index] = (float)(r.NextDouble() / 4); 40 | 41 | if (pastel) 42 | { 43 | for (int index = 0; index < saturations.Count; index++) 44 | saturations[index] = saturations[index]/2; 45 | 46 | for (int index = 0; index < brightnesses.Count; index++) 47 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/BlueAndWhite.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class BlueAndWhite : IColourTheme 7 | { 8 | public void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | { 12 | hues[index] = 240; 13 | } 14 | 15 | for (int index = 0; index < hueRanges.Count; index++) 16 | hueRanges[index] = 0; 17 | 18 | for (int index = 0; index < saturations.Count; index++) 19 | saturations[index] = r.Next(2) == 0 ? 0f : 1f; 20 | 21 | for (int index = 0; index < saturationRanges.Count; index++) 22 | saturationRanges[index] = 0; 23 | 24 | if (!lockBrightness) 25 | for (int index = 0; index < brightnesses.Count; index++) 26 | brightnesses[index] = pastel ? .75f : .5f; 27 | 28 | if (!lockBrightness) 29 | for (int index = 0; index < brightnessRanges.Count; index++) 30 | brightnessRanges[index] = pastel ? .25f : .5f; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/BlueColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class BlueColourTheme : IColourTheme 7 | { 8 | public new void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | hues[index] = r.Next(30) + 225; 12 | 13 | for (int index = 0; index < hueRanges.Count; index++) 14 | hueRanges[index] = r.Next(15); 15 | 16 | for (int index = 0; index < saturations.Count; index++) 17 | saturations[index] = r.NextDouble() / 4 + .75f; 18 | 19 | for (int index = 0; index < saturationRanges.Count; index++) 20 | saturationRanges[index] = r.NextDouble() / 4; 21 | 22 | if (!lockBrightness) 23 | for (int index = 0; index < brightnesses.Count; index++) 24 | brightnesses[index] = (float)(r.NextDouble()); 25 | 26 | if (!lockBrightness) 27 | for (int index = 0; index < brightnessRanges.Count; index++) 28 | brightnessRanges[index] = (float)(r.NextDouble() / 4); 29 | 30 | if (pastel) 31 | { 32 | for (int index = 0; index < saturations.Count; index++) 33 | saturations[index] = saturations[index] / 2; 34 | 35 | for (int index = 0; index < brightnesses.Count; index++) 36 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/GreenColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class GreenColourTheme : IColourTheme 7 | { 8 | public new void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | hues[index] = r.Next(30) + 105; 12 | 13 | for (int index = 0; index < hueRanges.Count; index++) 14 | hueRanges[index] = r.Next(15); 15 | 16 | for (int index = 0; index < saturations.Count; index++) 17 | saturations[index] = r.NextDouble() / 4 + .75f; 18 | 19 | for (int index = 0; index < saturationRanges.Count; index++) 20 | saturationRanges[index] = r.NextDouble() / 4; 21 | 22 | if (!lockBrightness) 23 | for (int index = 0; index < brightnesses.Count; index++) 24 | brightnesses[index] = (float)(r.NextDouble()); 25 | 26 | if (!lockBrightness) 27 | for (int index = 0; index < brightnessRanges.Count; index++) 28 | brightnessRanges[index] = (float)(r.NextDouble() / 4); 29 | 30 | if (pastel) 31 | { 32 | for (int index = 0; index < saturations.Count; index++) 33 | saturations[index] = saturations[index] / 2; 34 | 35 | for (int index = 0; index < brightnesses.Count; index++) 36 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/IColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public interface IColourTheme 7 | { 8 | void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/RainbowColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class RainbowColourTheme : IColourTheme 7 | { 8 | public void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | hues[index] = (360/hues.Count)*index; 12 | 13 | for (int index = 0; index < hueRanges.Count; index++) 14 | hueRanges[index] = 360/hueRanges.Count; 15 | 16 | for (int index = 0; index < saturations.Count; index++) 17 | saturations[index] = 1f; 18 | 19 | for (int index = 0; index < saturationRanges.Count; index++) 20 | saturationRanges[index] = 0; 21 | 22 | if (!lockBrightness) 23 | for (int index = 0; index < brightnesses.Count; index++) 24 | brightnesses[index] = 1f; 25 | 26 | if (!lockBrightness) 27 | for (int index = 0; index < brightnessRanges.Count; index++) 28 | brightnessRanges[index] = 0; 29 | 30 | if (pastel) 31 | { 32 | for (int index = 0; index < saturations.Count; index++) 33 | saturations[index] = saturations[index] / 2; 34 | 35 | for (int index = 0; index < brightnesses.Count; index++) 36 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/RainbowV2ColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class RainbowV2ColourTheme : IColourTheme 7 | { 8 | public void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | hues[index] = (360/hues.Count)*index; 12 | 13 | for (int index = 0; index < hueRanges.Count; index++) 14 | hueRanges[index] = 180; 15 | 16 | for (int index = 0; index < saturations.Count; index++) 17 | saturations[index] = 1f; 18 | 19 | for (int index = 0; index < saturationRanges.Count; index++) 20 | saturationRanges[index] = 0; 21 | 22 | if (!lockBrightness) 23 | for (int index = 0; index < brightnesses.Count; index++) 24 | brightnesses[index] = 1f; 25 | 26 | if (!lockBrightness) 27 | for (int index = 0; index < brightnessRanges.Count; index++) 28 | brightnessRanges[index] = 0; 29 | 30 | if (pastel) 31 | { 32 | for (int index = 0; index < saturations.Count; index++) 33 | saturations[index] = saturations[index] / 2; 34 | 35 | for (int index = 0; index < brightnesses.Count; index++) 36 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/RandomColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class RandomColourTheme : IColourTheme 7 | { 8 | public new void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | hues[index] = r.Next(360); 12 | 13 | for (int index = 0; index < hueRanges.Count; index++) 14 | hueRanges[index] = r.Next(180); 15 | 16 | for (int index = 0; index < saturations.Count; index++) 17 | saturations[index] = r.NextDouble(); 18 | 19 | for (int index = 0; index < saturationRanges.Count; index++) 20 | saturationRanges[index] = r.NextDouble(); 21 | 22 | if (!lockBrightness) 23 | for (int index = 0; index < brightnesses.Count; index++) 24 | brightnesses[index] = (float)(r.NextDouble()); 25 | 26 | if (!lockBrightness) 27 | for (int index = 0; index < brightnessRanges.Count; index++) 28 | brightnessRanges[index] = (float)(r.NextDouble()); 29 | 30 | if (pastel) 31 | { 32 | for (int index = 0; index < saturations.Count; index++) 33 | saturations[index] = saturations[index] / 2; 34 | 35 | for (int index = 0; index < brightnesses.Count; index++) 36 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/RedAndOrangeColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class RedAndOrangeColourTheme : IColourTheme 7 | { 8 | public new void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | { 12 | switch (r.Next(2)) 13 | { 14 | case 0: 15 | hues[index] = r.Next(30) - 15; // red 16 | break; 17 | case 1: 18 | hues[index] = r.Next(30) + 15; // orange 19 | break; 20 | } 21 | 22 | } 23 | 24 | for (int index = 0; index < hueRanges.Count; index++) 25 | hueRanges[index] = r.Next(30)-15; 26 | 27 | for (int index = 0; index < saturations.Count; index++) 28 | saturations[index] = r.NextDouble() / 4 + .75f; 29 | 30 | for (int index = 0; index < saturationRanges.Count; index++) 31 | saturationRanges[index] = r.NextDouble() / 4; 32 | 33 | if (!lockBrightness) 34 | for (int index = 0; index < brightnesses.Count; index++) 35 | brightnesses[index] = (float) r.NextDouble(); 36 | 37 | if (!lockBrightness) 38 | for (int index = 0; index < brightnessRanges.Count; index++) 39 | brightnessRanges[index] = (float)(r.NextDouble() / 4); 40 | 41 | if (pastel) 42 | { 43 | for (int index = 0; index < saturations.Count; index++) 44 | saturations[index] = saturations[index] / 2; 45 | 46 | for (int index = 0; index < brightnesses.Count; index++) 47 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/RedColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class RedColourTheme : IColourTheme 7 | { 8 | public new void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | hues[index] = r.Next(30) - 15; 12 | 13 | for (int index = 0; index < hueRanges.Count; index++) 14 | hueRanges[index] = r.Next(15); 15 | 16 | for (int index = 0; index < saturations.Count; index++) 17 | saturations[index] = r.NextDouble() / 4 + .75f; 18 | 19 | for (int index = 0; index < saturationRanges.Count; index++) 20 | saturationRanges[index] = r.NextDouble() / 4; 21 | 22 | if (!lockBrightness) 23 | for (int index = 0; index < brightnesses.Count; index++) 24 | brightnesses[index] = (float)(r.NextDouble()); 25 | 26 | if (!lockBrightness) 27 | for (int index = 0; index < brightnessRanges.Count; index++) 28 | brightnessRanges[index] = (float)(r.NextDouble() / 4); 29 | 30 | if (pastel) 31 | { 32 | for (int index = 0; index < saturations.Count; index++) 33 | saturations[index] = saturations[index] / 2; 34 | 35 | for (int index = 0; index < brightnesses.Count; index++) 36 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MaxLifx/ColourThemes/SpokesColourTheme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MaxLifx.ColourThemes 5 | { 6 | public class SpokesColourTheme : IColourTheme 7 | { 8 | public new void SetColours(Random r, List hues, List hueRanges, List saturations, List saturationRanges, List brightnesses, List brightnessRanges, bool pastel, bool lockBrightness) 9 | { 10 | for (int index = 0; index < hues.Count; index++) 11 | { 12 | hues[index] = r.Next(360); // red 13 | } 14 | 15 | for (int index = 0; index < hueRanges.Count; index++) 16 | hueRanges[index] = 0; 17 | 18 | for (int index = 0; index < saturations.Count; index++) 19 | saturations[index] = .5f; 20 | 21 | for (int index = 0; index < saturationRanges.Count; index++) 22 | saturationRanges[index] = .5f; 23 | 24 | if(!lockBrightness) 25 | for (int index = 0; index < brightnesses.Count; index++) 26 | brightnesses[index] = .5f; 27 | 28 | if (!lockBrightness) 29 | for (int index = 0; index < brightnessRanges.Count; index++) 30 | brightnessRanges[index] = .5f; 31 | 32 | if (pastel) 33 | { 34 | for (int index = 0; index < saturations.Count; index++) 35 | saturations[index] = saturations[index] / 2; 36 | 37 | for (int index = 0; index < brightnesses.Count; index++) 38 | brightnesses[index] = (brightnesses[index] * 2 < 1f ? brightnesses[index] * 2 : 1f); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MaxLifx/Controls/BrightnessSelector/BrightnessSelectorHandle.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace MaxLifx.Controls.BrightnessSelector 4 | { 5 | public class BrightnessSelectorHandle 6 | { 7 | private int _handleNumber; 8 | 9 | public BrightnessSelectorHandle(int handleNumber) 10 | { 11 | HandleNumber = handleNumber; 12 | Brightness = .9f; 13 | BrightnessRange = .1f; 14 | } 15 | 16 | public int HandleNumber 17 | { 18 | get { return _handleNumber; } 19 | set { _handleNumber = value; } 20 | } 21 | 22 | public float Brightness { get; set; } 23 | public float BrightnessRange { get; set; } 24 | 25 | public Rectangle GetHandleRectangle(Rectangle clientRectangle, int halfHandleSizeX, int halfHandleSizeY, 26 | int ring, int handleCount, int handleNumber) 27 | { 28 | var hPos = (int)(clientRectangle.Width / (handleCount) * (handleNumber + .5)); 29 | 30 | var handleRect = new Rectangle(hPos - 15, 31 | (int)(clientRectangle.Height * (1-Brightness)) - 15, 32 | 30, 33 | 30); 34 | 35 | return handleRect; 36 | } 37 | 38 | public Rectangle GetHandleRangeRectangle(Rectangle clientRectangle, int halfHandleSizeX, int halfHandleSizeY, 39 | bool positive, int ring, int handleCount, int handleNumber) 40 | { 41 | var hPos = (int)(clientRectangle.Width/(handleCount) * (handleNumber + .5)); 42 | 43 | var handleRect = new Rectangle(hPos - 10, 44 | (int)(clientRectangle.Height * (1 - ( (positive ? Brightness - BrightnessRange : Brightness + BrightnessRange)))) - 10, 45 | 20, 46 | 20); 47 | 48 | return handleRect; 49 | } 50 | 51 | public Point GetControlCentre(Rectangle clientRectangle) 52 | { 53 | return new Point(clientRectangle.Width/2, clientRectangle.Height/2); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/ColourStrategy/AnalogousColourStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using MaxLifx.Controls.HueSelector; 4 | 5 | namespace MaxLifx.Controls.ColourStrategy 6 | { 7 | public class AnalogousColourStrategy : IColourStrategy 8 | { 9 | public void ProcessHandles(List handles, int fromHandleNumber, double previousHue, 10 | double previousSaturation) 11 | { 12 | if (handles.Count == 0) return; 13 | 14 | var selectedHandle = handles.Single(x => x.HandleNumber == fromHandleNumber); 15 | 16 | var difference = selectedHandle.Hue - previousHue; 17 | var satDifference = selectedHandle.Saturation - previousSaturation; 18 | if (fromHandleNumber == 0) 19 | { 20 | foreach (var handle in handles.Where(x => x.HandleNumber > fromHandleNumber).OrderBy(x => x.HandleNumber)) 21 | { 22 | handle.Hue += difference; 23 | handle.Saturation += satDifference; 24 | if (handle.Saturation < 0) handle.Saturation = 0; 25 | if (handle.Saturation > 1) handle.Saturation = 1; 26 | } 27 | } 28 | else 29 | { 30 | var hueStep = (handles[fromHandleNumber].Hue - handles[0].Hue)/fromHandleNumber; 31 | var satStep = (handles[fromHandleNumber].Saturation - handles[0].Saturation) / fromHandleNumber; 32 | foreach (var handle in handles.Where(x => x.HandleNumber != 0 && x.HandleNumber != fromHandleNumber).OrderBy(x => x.HandleNumber)) 33 | { 34 | handle.Hue = handles[0].Hue + hueStep * handle.HandleNumber; 35 | handle.Saturation = handles[0].Saturation + satStep * handle.HandleNumber; 36 | if (handle.Saturation < 0) handle.Saturation = 0; 37 | if (handle.Saturation > 1) handle.Saturation = 1; 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/ColourStrategy/FreeColourStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MaxLifx.Controls.HueSelector; 3 | 4 | namespace MaxLifx.Controls.ColourStrategy 5 | { 6 | public class FreeColourStrategy : IColourStrategy 7 | { 8 | public void ProcessHandles(List handles, int fromHandleNumber, double previousHue, 9 | double previousSaturation) 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/ColourStrategy/IColourStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MaxLifx.Controls.HueSelector; 3 | 4 | namespace MaxLifx.Controls.ColourStrategy 5 | { 6 | public interface IColourStrategy 7 | { 8 | void ProcessHandles(List handles, int fromHandleNumber, double previousHue, 9 | double previousSaturation); 10 | } 11 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/ColourStrategy/OppositeColourStrategy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using MaxLifx.Controls.HueSelector; 4 | 5 | namespace MaxLifx.Controls.ColourStrategy 6 | { 7 | public class OppositeColourStrategy : IColourStrategy 8 | { 9 | public void ProcessHandles(List handles, int fromHandleNumber, double previousHue, 10 | double previousSaturation) 11 | { 12 | var otherHandle = handles.Single(x => x.HandleNumber != fromHandleNumber); 13 | var thisHandleHue = handles.Single(x => x.HandleNumber == fromHandleNumber).Hue; 14 | otherHandle.Hue = (180 + thisHandleHue)%360; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/HueSelector/HueSelectorHandle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace MaxLifx.Controls.HueSelector 5 | { 6 | public class HueSelectorHandle 7 | { 8 | private int _handleNumber; 9 | 10 | public HueSelectorHandle(int handleNumber) 11 | { 12 | HandleNumber = handleNumber; 13 | Hue = handleNumber*45; 14 | HueRange = 50; 15 | } 16 | 17 | public int HandleNumber 18 | { 19 | get { return _handleNumber; } 20 | set { _handleNumber = value; } 21 | } 22 | 23 | public double Hue { get; set; } 24 | public double HueRange { get; set; } 25 | public double Saturation { get; set; } = 0; 26 | public double SaturationRange { get; set; } = 0; 27 | 28 | public Rectangle GetHandleRectangle(Rectangle clientRectangle, int halfHandleSizeX, int halfHandleSizeY, 29 | int ring, bool shadow) 30 | { 31 | var controlCentre = GetControlCentre(clientRectangle); 32 | var handleRect = new Rectangle(controlCentre.X - halfHandleSizeX, 33 | controlCentre.Y - halfHandleSizeY, 34 | halfHandleSizeX*2, 35 | halfHandleSizeY*2); 36 | 37 | handleRect.X = (int) (handleRect.X + Math.Sin(Hue*Math.PI/180)*(clientRectangle.Width - 20)/2*Saturation); 38 | handleRect.Y = (int) (handleRect.Y - Math.Cos(Hue*Math.PI/180)*(clientRectangle.Height - 20)/2*Saturation); 39 | 40 | return handleRect; 41 | } 42 | 43 | public Rectangle GetHandleRangeRectangle(Rectangle clientRectangle, int halfHandleSizeX, int halfHandleSizeY, 44 | bool positive, int ring, bool shadow) 45 | { 46 | var controlCentre = GetControlCentre(clientRectangle); 47 | var handleRect = new Rectangle(controlCentre.X - halfHandleSizeX, 48 | controlCentre.Y - halfHandleSizeY, 49 | halfHandleSizeX*2, 50 | halfHandleSizeY*2); 51 | 52 | var angle = positive ? Hue + HueRange : Hue - HueRange; 53 | 54 | var satLevel = positive ? Saturation + SaturationRange : Saturation - SaturationRange; 55 | 56 | handleRect.X = (int) (handleRect.X + Math.Sin(angle*Math.PI/180)*(clientRectangle.Width - 20)/2*satLevel); 57 | handleRect.Y = (int) (handleRect.Y - Math.Cos(angle*Math.PI/180)*(clientRectangle.Height - 20)/2* satLevel); 58 | 59 | return handleRect; 60 | } 61 | 62 | public Point GetControlCentre(Rectangle clientRectangle) 63 | { 64 | return new Point(clientRectangle.Width/2, clientRectangle.Height/2); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/SpectrumAnalyser/SampleAggregator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NAudio.Dsp; 3 | 4 | namespace MaxLifx.Controls 5 | { 6 | // Based on the nAudio source code 7 | public class SampleAggregator 8 | { 9 | private readonly FftEventArgs _fftArgs; 10 | private readonly Complex[] _fftBuffer; 11 | private readonly int _fftLength; 12 | private readonly int _m; 13 | private int _fftPos; 14 | 15 | public SampleAggregator(int fftLength) 16 | { 17 | if (!IsPowerOfTwo(fftLength)) 18 | { 19 | throw new ArgumentException("FFT Length must be a power of two"); 20 | } 21 | _m = (int) Math.Log(fftLength, 2.0); 22 | _fftLength = fftLength; 23 | _fftBuffer = new Complex[fftLength]; 24 | _fftArgs = new FftEventArgs(_fftBuffer); 25 | } 26 | 27 | public bool PerformFFT { get; set; } 28 | // FFT 29 | public event EventHandler FftCalculated; 30 | 31 | private bool IsPowerOfTwo(int x) 32 | { 33 | return (x & (x - 1)) == 0; 34 | } 35 | 36 | public void Add(float value) 37 | { 38 | if (FftCalculated != null) 39 | { 40 | // Remember the window function! There are many others as well. 41 | _fftBuffer[_fftPos].X = (float)(value * FastFourierTransform.HammingWindow(_fftPos, _fftLength)); 42 | _fftBuffer[_fftPos].Y = 0; // This is always zero with audio. 43 | _fftPos++; 44 | if (_fftPos >= _fftLength) 45 | { 46 | _fftPos = 0; 47 | FastFourierTransform.FFT(true, _m, _fftBuffer); 48 | FftCalculated(this, _fftArgs); 49 | } 50 | } 51 | } 52 | } 53 | 54 | public class FftEventArgs : EventArgs 55 | { 56 | public FftEventArgs(Complex[] result) 57 | { 58 | Result = result; 59 | } 60 | 61 | public Complex[] Result { get; private set; } 62 | } 63 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/SpectrumAnalyser/SpectrumAnalyser.Overrides.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.Windows.Forms; 7 | 8 | namespace MaxLifx.Controls 9 | { 10 | public partial class SpectrumAnalyser 11 | { 12 | protected override CreateParams CreateParams 13 | { 14 | get 15 | { 16 | var cp = base.CreateParams; 17 | cp.ExStyle |= 0x00000020; 18 | return cp; 19 | } 20 | } 21 | 22 | [Category("Layout"), Description("Specifies size of the control.")] 23 | public Size Size 24 | { 25 | get { return base.Size; } 26 | set 27 | { 28 | base.Size = value; 29 | Invalidate(); 30 | } 31 | } 32 | 33 | protected override void OnPaintBackground(PaintEventArgs e) 34 | { 35 | } 36 | 37 | private void Initialise() 38 | { 39 | Invalidate(); 40 | } 41 | 42 | 43 | protected void InvalidateEx() 44 | { 45 | if (Parent == null) 46 | return; 47 | var rc = new Rectangle(Location, Size); 48 | Parent.Invalidate(rc, true); 49 | } 50 | 51 | protected override void OnCreateControl() 52 | { 53 | base.OnCreateControl(); 54 | Initialise(); 55 | } 56 | 57 | public bool ShowUpdates = true; 58 | protected override void OnPaint(PaintEventArgs e) 59 | { 60 | base.OnPaint(e); 61 | 62 | e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 63 | 64 | e.Graphics.Clear(BackColor); 65 | 66 | DrawGraph(e.Graphics); 67 | 68 | DrawHandles(e.Graphics); 69 | } 70 | 71 | protected override void OnMouseDown(MouseEventArgs e) 72 | { 73 | OnClick(e); 74 | 75 | foreach (var handle in _handles) 76 | { 77 | var handleRects = GetHandleRects(handle, 30); 78 | 79 | if (handleRects[1].Contains(e.Location) || handleRects[2].Contains(e.Location)) 80 | { 81 | _currentHandle = handle; 82 | _currentHandleIsRange = true; 83 | UpdateLevelRangeFromMouse(e); 84 | } 85 | else if (handleRects[0].Contains(e.Location)) 86 | { 87 | _currentHandle = handle; 88 | _currentHandleIsRange = false; 89 | UpdateBinAndLevelFromMouse(e); 90 | } 91 | } 92 | } 93 | 94 | protected override void OnMouseMove(MouseEventArgs e) 95 | { 96 | base.OnMouseMove(e); 97 | if (!_currentHandleIsRange &&_currentHandle != null) 98 | UpdateBinAndLevelFromMouse(e); 99 | else if (_currentHandleIsRange && _currentHandle != null) 100 | UpdateLevelRangeFromMouse(e); 101 | } 102 | 103 | protected override void OnMouseUp(MouseEventArgs e) 104 | { 105 | base.OnMouseMove(e); 106 | _currentHandle = null; 107 | } 108 | 109 | 110 | } 111 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/SpectrumAnalyser/SpectrumAnalyserEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | using NAudio.CoreAudioApi; 6 | using NAudio.Dsp; 7 | using NAudio.Wave; 8 | 9 | namespace MaxLifx.Controls 10 | { 11 | public class SpectrumAnalyserEngine 12 | { 13 | // Based on the nAudio source code 14 | 15 | // Other inputs are also usable. Just look through the NAudio library. 16 | private static readonly int FftLength = 1024; // NAudio fft wants powers of two! 17 | private readonly SampleAggregator _sampleAggregator = new SampleAggregator(FftLength); 18 | public int Bins = 512; // guess a 1024 size FFT, bins is half FFT size 19 | public List LatestPoints; 20 | public int SelectedBin = 10; 21 | private IWaveIn _waveIn; 22 | 23 | public SpectrumAnalyserEngine() 24 | { 25 | LatestPoints = new List{new Point(0, 100), new Point(1, 50)}; 26 | } 27 | 28 | public void StartCapture() 29 | { 30 | _sampleAggregator.FftCalculated += FftCalculated; 31 | var deviceEnum = new MMDeviceEnumerator(); 32 | var device = deviceEnum.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); 33 | 34 | if (_waveIn == null) 35 | { 36 | _waveIn = new WasapiLoopbackCapture(); // device); 37 | _waveIn.DataAvailable += OnDataAvailable; 38 | _waveIn.RecordingStopped += OnRecordingStopped; 39 | } 40 | // Forcibly turn on the microphone (some programs (Skype) turn it off). 41 | device.AudioEndpointVolume.Mute = false; 42 | 43 | _waveIn.StartRecording(); 44 | } 45 | 46 | private void FftCalculated(object sender, FftEventArgs e) 47 | { 48 | Update(e.Result); 49 | } 50 | 51 | public void Update(Complex[] fftResults) 52 | { 53 | if (fftResults.Length/2 != Bins) 54 | { 55 | Bins = fftResults.Length/2; 56 | } 57 | 58 | var points = new List(); 59 | for (var n = 0; n < fftResults.Length/2; n ++) 60 | { 61 | points.Add(new Point(n, (int) (GetYPosLog(fftResults[n])))); 62 | } 63 | LatestPoints = points; 64 | } 65 | 66 | private double GetYPosLog(Complex c) 67 | { 68 | // not entirely sure whether the multiplier should be 10 or 20 in this case. 69 | // going with 10 from here http://stackoverflow.com/a/10636698/7532 70 | var intensityDb = 10*Math.Log10(Math.Sqrt(c.X*c.X + c.Y*c.Y)); 71 | double minDb = -90; 72 | if (intensityDb < minDb) intensityDb = minDb; 73 | var percent = intensityDb/minDb; 74 | // we want 0dB to be at the top (i.e. yPos = 0) 75 | var yPos = percent*200; 76 | return yPos; 77 | } 78 | 79 | private void OnRecordingStopped(object sender, StoppedEventArgs e) 80 | { 81 | if (e.Exception != null) 82 | { 83 | MessageBox.Show($"A problem was encountered during recording {e.Exception.Message}"); 84 | } 85 | } 86 | 87 | private void OnDataAvailable(object sender, WaveInEventArgs e) 88 | { 89 | var buffer = e.Buffer; 90 | var bytesRecorded = e.BytesRecorded; 91 | var bufferIncrement = _waveIn.WaveFormat.BlockAlign; 92 | 93 | for (var index = 0; index < bytesRecorded; index += bufferIncrement) 94 | { 95 | var sample32 = BitConverter.ToSingle(buffer, index); 96 | _sampleAggregator.Add(sample32); 97 | } 98 | } 99 | 100 | public void StopCapture() 101 | { 102 | _waveIn?.StopRecording(); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/SpectrumAnalyser/SpectrumAnalyserHandle.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx.Controls 2 | { 3 | public class SpectrumAnalyserHandle 4 | { 5 | public int Bin = 50; 6 | public byte Level = 50; 7 | public byte LevelRange = 25; 8 | public int Number = 0; 9 | } 10 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/Timeline/Timeline.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | using System.Collections.Generic; 5 | using System.Drawing.Imaging; 6 | using System.Windows; 7 | using NAudio.Wave; 8 | 9 | namespace MaxLifx.Controls 10 | { 11 | public partial class Timeline 12 | { 13 | public List TimelineEvents = new List(); 14 | public Timeline() 15 | { 16 | ResizeRedraw = true; 17 | SetStyle( 18 | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); 19 | SetStyle(ControlStyles.SupportsTransparentBackColor, true); 20 | } 21 | 22 | private readonly int samplesPerPixel = 44100/8; 23 | public Dictionary WaveBitmaps = new Dictionary(); 24 | public Dictionary WaveBitmapDurations = new Dictionary(); 25 | 26 | public float PlaybackTime 27 | { 28 | get { return _playbackTime; } 29 | set 30 | { 31 | _playbackTime = value; Invalidate(); 32 | } 33 | } 34 | 35 | public void AddEvent(TimelineEvent x) 36 | { 37 | PopulateBitmapCache(x); 38 | 39 | TimelineEvents.Add(x); 40 | Invalidate(); 41 | } 42 | 43 | public void DeleteEvent(TimelineEvent x) 44 | { 45 | TimelineEvents.Remove(x); 46 | Invalidate(); 47 | } 48 | 49 | public void PopulateBitmapCache(TimelineEvent x) 50 | { 51 | if (x.Action == TimelineEventAction.PlayMp3 && !WaveBitmaps.ContainsKey(x.Parameter)) 52 | { 53 | var reader = new Mp3FileReader(x.Parameter); 54 | var width = ((double)reader.Length / samplesPerPixel); 55 | var widthFloor = (int)Math.Floor(width); 56 | Bitmap b = new Bitmap(widthFloor, 32, PixelFormat.Format16bppRgb555); 57 | using (Graphics g = Graphics.FromImage(b)) 58 | { 59 | g.Clear(Color.White); 60 | 61 | ISampleProvider m = reader.ToSampleProvider(); 62 | float[] buffer = new float[reader.Length / 2]; 63 | m.Read(buffer, 0, buffer.Length); 64 | 65 | var binCt = b.Width; 66 | var bins = new float[binCt]; 67 | var samplesPerBin = (float)buffer.Length / binCt; 68 | 69 | for (int i = 0; i < buffer.Length; i++) 70 | { 71 | var bin = (int)(Math.Floor(i / (samplesPerBin + 1))); 72 | if (bins[bin] < buffer[i]) 73 | bins[bin] = buffer[i]; 74 | } 75 | 76 | for (int i = 0; i < binCt; i++) 77 | { 78 | var centre = b.Height / 2; 79 | var scaledBinValue = bins[i] * centre; 80 | g.DrawLine(Pens.Black, i, centre - scaledBinValue, i, centre + scaledBinValue); 81 | } 82 | Bitmap c = new Bitmap(b.Width, b.Height, PixelFormat.Format1bppIndexed); 83 | c.Palette.Entries[0] = Color.DarkGray; 84 | c = b.Clone(new Rectangle(0,0,b.Width,b.Height), PixelFormat.Format1bppIndexed); 85 | 86 | WaveBitmaps.Add(x.Parameter, c); 87 | b.Dispose(); 88 | WaveBitmapDurations.Add(x.Parameter, (float)reader.Length / (reader.WaveFormat.SampleRate * (reader.WaveFormat.BitsPerSample / 8) * reader.WaveFormat.Channels)); 89 | 90 | reader.Close(); 91 | reader.Dispose(); 92 | 93 | } 94 | 95 | } 96 | GC.Collect(2); 97 | } 98 | 99 | public long Duration = 10000; 100 | 101 | public Vector ViewableWindow = new Vector(0,10000); 102 | private float _playbackTime; 103 | public double ViewableWindowSize => ViewableWindow.Y - ViewableWindow.X; 104 | 105 | 106 | } 107 | } -------------------------------------------------------------------------------- /MaxLifx/Controls/Timeline/TimelineEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace MaxLifx.Controls 5 | { 6 | public class TimelineEvent 7 | { 8 | public string Uuid; 9 | public float Time { get; set; } 10 | [XmlIgnore] 11 | public bool Fired { get; set; } 12 | 13 | private TimelineEventAction _action; 14 | public TimelineEventAction Action 15 | { 16 | get { return _action; } 17 | set { _action = value; } 18 | } 19 | 20 | public string Parameter { get; set; } 21 | 22 | public TimelineEvent() 23 | { 24 | } 25 | 26 | public TimelineEvent(TimelineEventAction action, string parameter, float time) 27 | { 28 | Action = action; 29 | Parameter = parameter; 30 | Time = time; 31 | Uuid = Guid.NewGuid().ToString(); 32 | } 33 | 34 | public override string ToString() 35 | { 36 | return Action == TimelineEventAction.Unspecified ? "Unspecified" : Parameter.Substring(Parameter.LastIndexOf("\\") + 1).Replace(".mp3", "").Replace(".MaxLifx.Threadset.xml", ""); 37 | } 38 | } 39 | 40 | public enum TimelineEventAction 41 | { 42 | Unspecified, 43 | StartThreadSet, 44 | PlayMp3 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MaxLifx/LightControlThread.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Xml; 6 | using System.Xml.Serialization; 7 | using MaxLifx.Threads; 8 | 9 | namespace MaxLifx 10 | { 11 | public class LightControlThread 12 | { 13 | public LightControlThread() 14 | { 15 | } 16 | 17 | public LightControlThread(Thread thread, string name, IProcessor processor) 18 | { 19 | Thread = thread; 20 | Uuid = Guid.NewGuid().ToString(); 21 | Name = name; 22 | Processor = processor; 23 | } 24 | 25 | private Thread Thread { get; } 26 | public string Uuid { get; set; } 27 | public string Name { get; set; } 28 | 29 | [XmlIgnore] 30 | public IProcessor Processor { get; private set; } 31 | 32 | [XmlElement("Processor")] 33 | public string ProcessorSerialized 34 | { 35 | get { return Processor.SettingsAsXml; } 36 | set 37 | { 38 | var xmlDocument = new XmlDocument(); 39 | xmlDocument.LoadXml(value); 40 | 41 | var typeName = xmlDocument.DocumentElement.Name; 42 | 43 | // Create processor 44 | var processorName = "MaxLifx." + typeName.Replace("Settings", "Processor"); 45 | var processorType = Type.GetType(processorName); 46 | var processorConstructor = processorType.GetConstructor(Type.EmptyTypes); 47 | Processor = (IProcessor) (processorConstructor.Invoke(new object[] {})); 48 | 49 | Processor.SettingsAsXml = value; 50 | } 51 | } 52 | 53 | public void Abort() 54 | { 55 | Processor.TerminateThread = true; 56 | } 57 | 58 | public void Start() 59 | { 60 | Thread.Start(); 61 | //Thread.Sleep(10); 62 | //Processor.ShowUI = true; 63 | } 64 | } 65 | 66 | public class LightControlThreadCollection 67 | { 68 | public LightControlThreadCollection() 69 | { 70 | LightControlThreads = new List(); 71 | } 72 | 73 | public List LightControlThreads { get; set; } 74 | 75 | public LightControlThread AddThread(Thread thread, string name, IProcessor processor) 76 | { 77 | var lightControlThread = new LightControlThread(thread, name, processor); 78 | LightControlThreads.Add(lightControlThread); 79 | return (lightControlThread); 80 | } 81 | 82 | public LightControlThread GetThread(string threadUuid) 83 | { 84 | return (LightControlThreads.SingleOrDefault(x => x.Uuid == threadUuid)); 85 | } 86 | 87 | public void RemoveThread(string threadUuid) 88 | { 89 | LightControlThreads.Remove(LightControlThreads.Single(x => x.Uuid == threadUuid)); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /MaxLifx/Payload/GetColourZonesPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class GetColourZonesPayload : IPayload 11 | // although this is GetColourZones, we are really just calling this to get StateZone for the count of zones 12 | { 13 | private byte[] _messageType = new byte[2] { 0xF6, 0x01 }; 14 | public byte[] MessageType { get { return _messageType; } } 15 | public int Hue { get; set; } 16 | public byte start_index = 0; 17 | public byte end_index = 0; 18 | public byte[] GetPayload() 19 | { 20 | var _start_index = BitConverter.GetBytes(start_index); 21 | var _end_index = BitConverter.GetBytes(end_index); 22 | return new byte[0].Concat(_start_index).Concat(_end_index).ToArray(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MaxLifx/Payload/GetLabelPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class GetLabelPayload : IPayload 11 | { 12 | private byte[] _messageType = new byte[2] { 23, 0 }; 13 | public byte[] MessageType { get { return _messageType; } } 14 | 15 | public byte[] GetPayload() 16 | { 17 | return new byte[0]; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MaxLifx/Payload/GetServicePayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class GetServicePayload : IPayload 11 | { 12 | private byte[] _messageType = new byte[2] { 0x2, 0 }; 13 | public byte[] MessageType { get { return _messageType; } } 14 | 15 | public byte[] GetPayload() 16 | { 17 | return new byte[0]; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MaxLifx/Payload/GetVersionPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class GetVersionPayload : IPayload 11 | // getting the version info will let us know if light has zones (Beam or Z) 12 | { 13 | private byte[] _messageType = new byte[2] { 0x20, 0 }; 14 | public byte[] MessageType { get { return _messageType; } } 15 | 16 | public byte[] GetPayload() 17 | { 18 | return new byte[0]; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MaxLifx/Payload/IPayload.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 MaxLifx.Payload 8 | { 9 | public interface IPayload 10 | { 11 | byte[] MessageType { get; } 12 | byte[] GetPayload(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MaxLifx/Payload/SetColourPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class SetColourPayload : IPayload 11 | { 12 | private byte[] _messageType = new byte[2] { 0x66, 0 }; 13 | public byte[] MessageType { get { return _messageType; } } 14 | public int Hue { get; set; } 15 | public UInt16 Saturation { get; set; } 16 | public UInt16 Brightness { get; set; } 17 | public UInt16 Kelvin { get; set; } 18 | public UInt32 TransitionDuration { get; set; } 19 | 20 | public byte[] GetPayload() 21 | { 22 | if (Hue > 360 || Hue < 0) throw new NotImplementedException(); 23 | 24 | // Payload 25 | // The payload starts with a reserved field of 8 bits (1 bytes). 26 | var _payloadReserved = new byte[1]; 27 | 28 | // HSBK colour: Next up is the color described in HSBK. The HSBK format is described at the top of the light messages7 page. 29 | // It starts with a 16 bit (2 byte) integer representing the Hue. The hue of green is 120 degrees. Our scale however 30 | // goes from 1-65535 instead of the traditional 1-360 hue scale. To represent this we use a simple formula to find the 31 | // hue in our range. 120 / 360 * 65535 which yields a result of 21845. This is 0x5555 in hex. In our case it isn't important, 32 | // but remember to represent this number in little endian. 33 | 34 | // Watch out, BitConverter.GetBytes returns a little endian answer so we needn't reverse the result 35 | //var hue = r.Next(360); 36 | var _hsbkColourLE = BitConverter.GetBytes((Hue * 65535) / 360); 37 | var _hsbkColour = new byte[2] { _hsbkColourLE[0], _hsbkColourLE[1] }; 38 | 39 | // We want maximum saturation which in a 16bit (2 byte) value is represented as 0xFFFF. 40 | var _saturation = BitConverter.GetBytes(Saturation); 41 | var _brightness = BitConverter.GetBytes(Brightness); 42 | 43 | // Finally we set the Kelvin to mid-range which is 3500 in decimal or 0x0DAC. 44 | var _kelvin = BitConverter.GetBytes(Kelvin); 45 | 46 | // The final part of our payload is the number of milliseconds over which to perform the transition. Lets set it to 47 | // 1024ms because its an easy number and this is getting complicated. 1024 is 0x00000400 in hex. 48 | // var _transitionLE = BitConverter.GetBytes(1024); 49 | // is 4 bytes 50 | var _transition = BitConverter.GetBytes(TransitionDuration); 51 | 52 | var _payload = _payloadReserved.Concat(_hsbkColour) 53 | .Concat(_saturation) 54 | .Concat(_brightness) 55 | .Concat(_kelvin) 56 | .Concat(_transition) 57 | .ToArray(); 58 | return _payload; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /MaxLifx/Payload/SetColourZonesPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class SetColourZonesPayload : SetColourPayload, IPayload 11 | { 12 | private byte[] _messageType = new byte[2] { 0xF5, 0x01 }; 13 | public new byte[] MessageType { get { return _messageType; } } 14 | public byte[] start_index { get; set; } 15 | public byte[] end_index { get; set; } 16 | 17 | public byte[] apply { get; set; } 18 | 19 | public new byte[] GetPayload() { 20 | 21 | // Multizone packet example 22 | // RECALL: uses little endian(bytes reversed) 23 | // 24 | //format & size: Frame(8B *) Frame Address(16B *) Protocol Header(12B *) Payload(15B in this example) 25 | // |----------------| |---------------------------------| |------------------------| |-----------------------------------| 26 | // | | | | | | | | 27 | //decimal value: 51 1 0* False True 0* 0* 10 65535 3500 1 28 | //field: size source target S/N reserved (res_r + ack_r + reserved) rsvd e_i sat. kel. apply 29 | // |~~| |~~~~~~| |~~~~~~~~~~~~~~| |~~~~~~~~~~| || |~~| || |~~| |~~| | 30 | //bytes: 3300 0014 01000000 d073d5XXXXXXXXXX 000000000000 02 01 0000000000000000 f501 0000 0a 0a 1c47 ffff ff7f ac0d e80300000 1 31 | // |~~| || |~~~~~~~~~~~~~~| |~~| || |~~| |~~| |~~~~~~~| 32 | //field: (protocol + addressable + tagged + origin) seq. reserved pkg type s_i hue bri. duration 33 | //decimal value: 1024* True* False 0* 1 0* 501 10 10 32767 1000 34 | // 35 | //Notes: 36 | // - * indicates mandatory value/ size 37 | // - for the fields that have plus symbol, certain bits in the byte belong to different fields; need to work in binary to get value that converts to hex 38 | 39 | 40 | if (Hue < 0) 41 | Hue = Hue + 36000; 42 | Hue = Hue % 360; 43 | 44 | // Payload 45 | 46 | // HSBK colour: Next up is the color described in HSBK. The HSBK format is described at the top of the light messages7 page. 47 | // It starts with a 16 bit (2 byte) integer representing the Hue. The hue of green is 120 degrees. Our scale however 48 | // goes from 1-65535 instead of the traditional 1-360 hue scale. To represent this we use a simple formula to find the 49 | // hue in our range. 120 / 360 * 65535 which yields a result of 21845. This is 0x5555 in hex. In our case it isn't important, 50 | // but remember to represent this number in little endian. 51 | 52 | // Watch out, BitConverter.GetBytes returns a little endian answer so we needn't reverse the result 53 | //var hue = r.Next(360); 54 | var _hsbkColourLE = BitConverter.GetBytes((Hue * 65535) / 360); 55 | var _hsbkColour = new byte[2] { _hsbkColourLE[0], _hsbkColourLE[1] }; 56 | 57 | // We want maximum saturation which in a 16bit (2 byte) value is represented as 0xFFFF. 58 | var _saturation = BitConverter.GetBytes(Saturation); 59 | var _brightness = BitConverter.GetBytes(Brightness); 60 | 61 | // Finally we set the Kelvin to mid-range which is 3500 in decimal or 0x0DAC. 62 | var _kelvin = BitConverter.GetBytes(Kelvin); 63 | 64 | // The final part of our payload is the number of milliseconds over which to perform the transition. Lets set it to 65 | // 1024ms because its an easy number and this is getting complicated. 1024 is 0x00000400 in hex. 66 | // var _transitionLE = BitConverter.GetBytes(1024); 67 | // is 4 bytes 68 | var _transition = BitConverter.GetBytes(TransitionDuration); 69 | 70 | var _payload = start_index.Concat(end_index) 71 | .Concat(_hsbkColour) 72 | .Concat(_saturation) 73 | .Concat(_brightness) 74 | .Concat(_kelvin) 75 | .Concat(_transition) 76 | .Concat(apply) 77 | .ToArray(); 78 | return _payload; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /MaxLifx/Processors/CursorPosition.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Controllers; 2 | using MaxLifx.Payload; 3 | using MaxLifx.Threads; 4 | using NAudio.CoreAudioApi; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Drawing; 8 | using System.Linq; 9 | using System.Runtime.InteropServices; 10 | using System.Text; 11 | using System.Threading; 12 | using System.Threading.Tasks; 13 | using System.Windows.Forms; 14 | 15 | namespace MaxLifx 16 | { 17 | public class CursorPositionProcessor : IProcessor 18 | { 19 | private object locker = new object(); 20 | private bool _showUI; 21 | public bool ShowUI 22 | { 23 | get 24 | { 25 | lock (locker) 26 | { 27 | return _showUI; 28 | } 29 | } 30 | set 31 | { 32 | lock (locker) 33 | { 34 | _showUI = value; 35 | } 36 | } 37 | } 38 | 39 | [DllImport("user32.dll")] 40 | static extern bool GetCursorPos(ref Point lpPoint); 41 | public void CursorPosition() 42 | { 43 | MMDeviceEnumerator de = new MMDeviceEnumerator(); 44 | MMDevice device = de.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); 45 | 46 | Point cursor = new Point(); 47 | 48 | while (1 == 1) 49 | { 50 | GetCursorPos(ref cursor); 51 | 52 | try 53 | { 54 | //d.Invoke("X: " + cursor.X + " Y: " + cursor.Y, (int)(device.AudioMeterInformation.MasterPeakValue * 100) ); 55 | } 56 | catch 57 | { } 58 | 59 | Thread.Sleep(500); 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/IProcessor.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Processors.ProcessorSettings; 2 | 3 | namespace MaxLifx.Threads 4 | { 5 | public interface IProcessor 6 | { 7 | bool ShowUI { get; set; } 8 | ISettings Settings { get; set; } 9 | string SettingsAsXml { get; set; } 10 | bool TerminateThread { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/ProcessorBase.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Xml; 3 | using System.Xml.Serialization; 4 | using MaxLifx.Processors.ProcessorSettings; 5 | 6 | namespace MaxLifx.Threads 7 | { 8 | public class ProcessorBase : IProcessor 9 | { 10 | internal bool _showUI; 11 | internal object Locker = new object(); 12 | public bool TerminateThread { get; set; } 13 | public virtual ISettings Settings { get; set; } 14 | public virtual string SettingsAsXml { get; set; } 15 | 16 | public bool ShowUI 17 | { 18 | get 19 | { 20 | lock (Locker) 21 | { 22 | return _showUI; 23 | } 24 | } 25 | set 26 | { 27 | lock (Locker) 28 | { 29 | _showUI = value; 30 | } 31 | } 32 | } 33 | 34 | public static void SaveSettings(T settings, string filename) 35 | { 36 | //if (!SuspendUI) 37 | // 38 | 39 | if (string.IsNullOrEmpty(filename)) 40 | filename = typeof (T).Name + "Default.maxlifx.xml"; 41 | 42 | var xml = new XmlSerializer(typeof (T)); 43 | 44 | using (var stream = new MemoryStream()) 45 | { 46 | xml.Serialize(stream, settings); 47 | stream.Position = 0; 48 | var xmlDocument = new XmlDocument(); 49 | xmlDocument.Load(stream); 50 | xmlDocument.Save(filename); 51 | stream.Close(); 52 | } 53 | //} 54 | } 55 | 56 | public static void LoadSettings(ref T settings, string filename) 57 | { 58 | if (filename == "") 59 | filename = typeof (T).Name + "Default.maxlifx.xml"; 60 | 61 | 62 | if (!File.Exists(filename)) 63 | return; 64 | 65 | var xmlDocument = new XmlDocument(); 66 | xmlDocument.Load(filename); 67 | var xmlString = xmlDocument.OuterXml; 68 | 69 | using (var read = new StringReader(xmlString)) 70 | { 71 | var outType = typeof (T); 72 | 73 | var serializer = new XmlSerializer(outType); 74 | using (XmlReader reader = new XmlTextReader(read)) 75 | { 76 | settings = (T) serializer.Deserialize(reader); 77 | reader.Close(); 78 | } 79 | 80 | read.Close(); 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/ProcessorSettings/ISettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace MaxLifx.Processors.ProcessorSettings 4 | { 5 | public interface ISettings 6 | { 7 | List SelectedLabels { get; set; } 8 | string FileExtension { get; } 9 | string OnTimes { get; set; } 10 | string OffTimes { get; set; } 11 | bool OffOrOn(); 12 | } 13 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/ProcessorSettings/ScreenColourSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | namespace MaxLifx.Processors.ProcessorSettings 4 | { 5 | public class ScreenColourSettings : SettingsBase, ISettings 6 | { 7 | public int Brightness = 65535; 8 | public int Kelvin = 3500; 9 | public int Delay = 50; 10 | public int Fade = 150; 11 | public List BulbSettings = new List(); 12 | public int Saturation = 65535; 13 | public int MinSaturation = 0; 14 | public int MinBrightness = 0; 15 | public Point CentrePoint = new Point(0, 0); 16 | // keep track of the different number of multizone lights 17 | public HashSet MultiColourZones = new HashSet(); 18 | 19 | public int Monitor = 0; 20 | } 21 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/ProcessorSettings/SettingsBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Xml.Serialization; 6 | 7 | namespace MaxLifx.Processors.ProcessorSettings 8 | { 9 | public class SettingsBase 10 | { 11 | private string _offTimes; 12 | private string _onTimes; 13 | public List SelectedLabels { get; set; } = new List(); 14 | 15 | public string FileExtension => (GetType() + ".xml").Replace("MaxLifx.Processors.ProcessorSettings.",""); 16 | 17 | public string OnTimes 18 | { 19 | get { return _onTimes; } 20 | set 21 | { 22 | _onTimes = value; 23 | OnTimesList = GetTimeStringsFromColonSeparatedList(value).OrderBy(x => x).ToList(); 24 | } 25 | } 26 | 27 | public string OffTimes 28 | { 29 | get { return _offTimes; } 30 | set 31 | { 32 | _offTimes = value; 33 | OffTimesList = GetTimeStringsFromColonSeparatedList(value).OrderBy(x => x).ToList(); 34 | } 35 | } 36 | 37 | [XmlIgnore] 38 | public List OnTimesList { get; set; } 39 | 40 | [XmlIgnore] 41 | public List OffTimesList { get; set; } 42 | 43 | public static List GetTimeStringsFromColonSeparatedList(string timesString) 44 | { 45 | if (timesString == null) 46 | return new List(); 47 | 48 | var times = timesString.Replace(" ", "").Replace(":", "").Split(';'); 49 | 50 | var validTimeStrings = new List(); 51 | 52 | foreach (var time in times) 53 | { 54 | DateTime dateTime; 55 | 56 | if (DateTime.TryParseExact(time, "HHmm", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) 57 | { 58 | int i; 59 | int.TryParse(time, out i); 60 | validTimeStrings.Add(i); 61 | } 62 | } 63 | 64 | return validTimeStrings; 65 | } 66 | 67 | public bool OffOrOn() 68 | { 69 | try 70 | { 71 | if (OnTimesList == null || OffTimesList == null) 72 | return true; 73 | 74 | int currentTime; 75 | int.TryParse(DateTime.Now.ToString("HHmm"), out currentTime); 76 | 77 | var ons = OnTimesList.Where(x => x <= currentTime).ToList(); 78 | var offs = OffTimesList.Where(x => x <= currentTime).ToList(); 79 | 80 | if (ons.Count == 0) 81 | if (offs.Count == 0) 82 | return true; 83 | else return false; 84 | 85 | var mostRecentOn = ons.Max(); 86 | 87 | if (offs.Count == 0) 88 | return true; 89 | var mostRecentOff = offs.Max(); 90 | 91 | if (mostRecentOff > mostRecentOn) 92 | return false; 93 | 94 | return true; 95 | } 96 | catch (Exception) 97 | { 98 | return true; 99 | } 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/ProcessorSettings/SoundGeneratorSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Xml.Serialization; 5 | using MaxLifx.SoundToken; 6 | using MaxLifx.UIs; 7 | using NAudio.Wave; 8 | 9 | namespace MaxLifx.Processors.ProcessorSettings 10 | { 11 | public class SoundGeneratorSettings : SettingsBase, ISettings 12 | { 13 | private string _uuid; 14 | public List Sounds = new List(); 15 | public string Name { get; set; } 16 | public string Filename { get; set; } 17 | 18 | public string UUID 19 | { 20 | get 21 | { 22 | if (_uuid == null) 23 | _uuid = Guid.NewGuid().ToString(); 24 | return _uuid; 25 | } 26 | set { _uuid = value; } 27 | } 28 | 29 | [XmlIgnore] 30 | public WaveOut WaveOut { get; set; } 31 | 32 | [XmlIgnore] 33 | public List Messages { get; private set; } = new List(); 34 | 35 | public float Volume { get; set; } 36 | 37 | public Sound GetSoundFromUUID(string UUID) 38 | { 39 | return Sounds.Single(x => x.UUID == UUID); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /MaxLifx/Processors/ProcessorSettings/SoundResponseSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml.Serialization; 4 | 5 | namespace MaxLifx.Processors.ProcessorSettings 6 | { 7 | public class SoundResponseSettings : SettingsBase, ISettings 8 | { 9 | public bool BrightnessInvert = false; 10 | public int Delay = 90; 11 | public bool Free = true; 12 | public bool HueInvert = false; 13 | public ushort Kelvin = 3500; 14 | 15 | public bool LinkRanges = false; 16 | public bool PerBulb = true; 17 | public bool SaturationInvert = false; 18 | public long TransitionDuration = 100; 19 | public int WaveDuration = 5000; 20 | public WaveTypes WaveType = WaveTypes.Audio; 21 | 22 | [XmlIgnore] 23 | public DateTime WaveStartTime { get; set; } 24 | 25 | public List BrightnessRanges { get; set; } = new List(); 26 | public List Brightnesses { get; set; } = new List(); 27 | public List HueRanges { get; set; } = new List(); 28 | public List Hues { get; set; } = new List(); 29 | public List SaturationRanges { get; set; } = new List(); 30 | public List Saturations { get; set; } = new List(); 31 | 32 | public List LevelRanges { get; set; } = new List(); 33 | public List Levels { get; set; } = new List(); 34 | public List Bins { get; set; } = new List(); 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /MaxLifx/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace MaxLifx 5 | { 6 | internal static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | private static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new MainForm()); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /MaxLifx/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("MaxLifx-Z")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MaxLifx-Z")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 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 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | [assembly: Guid("67f98e25-20d2-45b3-a466-e210916985a9")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | 38 | [assembly: AssemblyVersion("1.0.0.0")] 39 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /MaxLifx/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 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 MaxLifx.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", "16.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("MaxLifx.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 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap ColourWheel { 67 | get { 68 | object obj = ResourceManager.GetObject("ColourWheel", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap crosshair { 77 | get { 78 | object obj = ResourceManager.GetObject("crosshair", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap m__1_ { 87 | get { 88 | object obj = ResourceManager.GetObject("m (1)", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /MaxLifx/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 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 MaxLifx.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.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 | -------------------------------------------------------------------------------- /MaxLifx/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MaxLifx/Resources/Colour Wheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/MaxLifx/Resources/Colour Wheel.png -------------------------------------------------------------------------------- /MaxLifx/Resources/crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/MaxLifx/Resources/crosshair.png -------------------------------------------------------------------------------- /MaxLifx/Resources/m (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/MaxLifx/Resources/m (1).png -------------------------------------------------------------------------------- /MaxLifx/Scheduler/SchedulerEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace MaxLifx.Scheduler 5 | { 6 | public class SchedulerEvent 7 | { 8 | public string UUID; 9 | public long Milliseconds { get; set; } 10 | [XmlIgnore] 11 | public bool Fired { get; set; } 12 | 13 | private SchedulerEventAction _action; 14 | public SchedulerEventAction Action 15 | { 16 | get { return _action; } 17 | set { _action = value; } 18 | } 19 | 20 | public string Parameter { get; set; } 21 | 22 | public SchedulerEvent() 23 | { 24 | } 25 | 26 | public SchedulerEvent(SchedulerEventAction action, string parameter, long milliseconds) 27 | { 28 | Action = action; 29 | Parameter = parameter; 30 | Milliseconds = milliseconds; 31 | UUID = Guid.NewGuid().ToString(); 32 | } 33 | 34 | public override string ToString() 35 | { 36 | return ((float) Milliseconds/1000) + "s: " + Action + " - " + Parameter; 37 | } 38 | } 39 | 40 | public enum SchedulerEventAction 41 | { 42 | Unspecified, 43 | StartThreadSet, 44 | PlayMp3 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MaxLifx/Settings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MaxLifx.Controllers; 3 | 4 | namespace MaxLifx 5 | { 6 | public class MaxLifxSettings 7 | { 8 | // Bulbs (for load and save purposes, these are passed to MaxLifxBulbController when we load to avoid having to discover every time) 9 | public List Bulbs = new List(); 10 | // Selections 11 | public List SelectedLabels = new List(); 12 | } 13 | } -------------------------------------------------------------------------------- /MaxLifx/Sound/Sound.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | using NAudio.Wave; 4 | using NAudio.Wave.SampleProviders; 5 | 6 | namespace MaxLifx.SoundToken 7 | { 8 | [Serializable] 9 | public class Sound 10 | { 11 | public enum SoundTypes 12 | { 13 | Looping, 14 | Random 15 | } 16 | 17 | private int _frequency = 30; 18 | private float _pan = .5f; 19 | private string _uuid; 20 | private float _volume = .5f; 21 | 22 | public Sound(string name, string filename, SoundTypes soundType) 23 | { 24 | Name = name; 25 | Filename = filename; 26 | SoundType = soundType; 27 | } 28 | 29 | public Sound() 30 | { 31 | } 32 | 33 | public string Name { get; set; } 34 | public string Filename { get; set; } 35 | 36 | public string UUID 37 | { 38 | get 39 | { 40 | if (_uuid == null) 41 | _uuid = Guid.NewGuid().ToString(); 42 | return _uuid; 43 | } 44 | set { _uuid = value; } 45 | } 46 | 47 | [XmlIgnore] 48 | public WaveOut WaveOut { get; set; } 49 | 50 | [XmlIgnore] 51 | public VolumeSampleProvider VolumeProvider { get; set; } 52 | 53 | [XmlIgnore] 54 | public PanningSampleProvider PanProvider { get; set; } 55 | 56 | public SoundTypes SoundType { get; set; } 57 | public bool Started { get; set; } 58 | public StartStop StartStopRequest { get; set; } 59 | 60 | public float Volume 61 | { 62 | get { return _volume; } 63 | set { _volume = value; } 64 | } 65 | 66 | public float Pan 67 | { 68 | get { return _pan; } 69 | set { _pan = value; } 70 | } 71 | 72 | public int Frequency 73 | { 74 | get { return _frequency; } 75 | set { _frequency = value; } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/About.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Diagnostics; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace MaxLifx.UIs 13 | { 14 | public partial class About : Form 15 | { 16 | public About() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | private void About_Load(object sender, EventArgs e) 22 | { 23 | } 24 | 25 | private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 26 | { 27 | Process.Start("https://naudio.codeplex.com/license"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MaxLifx/UIs/About.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 | -------------------------------------------------------------------------------- /MaxLifx/UIs/AdvancedDiscover.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx.UIs 2 | { 3 | partial class AdvancedDiscover 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.textBox1 = new System.Windows.Forms.TextBox(); 32 | this.SuspendLayout(); 33 | // 34 | // textBox1 35 | // 36 | this.textBox1.Location = new System.Drawing.Point(108, 11); 37 | this.textBox1.Name = "textBox1"; 38 | this.textBox1.Size = new System.Drawing.Size(100, 20); 39 | this.textBox1.TabIndex = 0; 40 | // 41 | // AdvancedDiscover 42 | // 43 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 44 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 45 | this.ClientSize = new System.Drawing.Size(284, 261); 46 | this.Controls.Add(this.textBox1); 47 | this.Name = "AdvancedDiscover"; 48 | this.Text = "AdvancedDiscover"; 49 | this.ResumeLayout(false); 50 | this.PerformLayout(); 51 | 52 | } 53 | 54 | #endregion 55 | 56 | private System.Windows.Forms.TextBox textBox1; 57 | } 58 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/AdvancedDiscover.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 | 11 | namespace MaxLifx.UIs 12 | { 13 | public partial class AdvancedDiscover : Form 14 | { 15 | public AdvancedDiscover() 16 | { 17 | InitializeComponent(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MaxLifx/UIs/AdvancedDiscover.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 | -------------------------------------------------------------------------------- /MaxLifx/UIs/AssignAreaToBulbForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx 2 | { 3 | partial class AssignAreaToBulbForm 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.button1 = new System.Windows.Forms.Button(); 32 | this.lbBulbs = new System.Windows.Forms.ListBox(); 33 | this.cbArea = new System.Windows.Forms.ComboBox(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.SuspendLayout(); 36 | // 37 | // button1 38 | // 39 | this.button1.Location = new System.Drawing.Point(12, 139); 40 | this.button1.Name = "button1"; 41 | this.button1.Size = new System.Drawing.Size(260, 23); 42 | this.button1.TabIndex = 0; 43 | this.button1.Text = "Close"; 44 | this.button1.UseVisualStyleBackColor = true; 45 | this.button1.Click += new System.EventHandler(this.button1_Click); 46 | // 47 | // lbBulbs 48 | // 49 | this.lbBulbs.FormattingEnabled = true; 50 | this.lbBulbs.Location = new System.Drawing.Point(12, 11); 51 | this.lbBulbs.Name = "lbBulbs"; 52 | this.lbBulbs.Size = new System.Drawing.Size(260, 95); 53 | this.lbBulbs.TabIndex = 1; 54 | this.lbBulbs.SelectedIndexChanged += new System.EventHandler(this.lbBulbs_SelectedIndexChanged); 55 | // 56 | // cbArea 57 | // 58 | this.cbArea.Enabled = false; 59 | this.cbArea.FormattingEnabled = true; 60 | this.cbArea.Location = new System.Drawing.Point(130, 112); 61 | this.cbArea.Name = "cbArea"; 62 | this.cbArea.Size = new System.Drawing.Size(142, 21); 63 | this.cbArea.TabIndex = 2; 64 | this.cbArea.SelectedIndexChanged += new System.EventHandler(this.cbArea_SelectedIndexChanged); 65 | // 66 | // label1 67 | // 68 | this.label1.AutoSize = true; 69 | this.label1.Location = new System.Drawing.Point(12, 115); 70 | this.label1.Name = "label1"; 71 | this.label1.Size = new System.Drawing.Size(112, 13); 72 | this.label1.TabIndex = 3; 73 | this.label1.Text = "Area assigned to bulb:"; 74 | // 75 | // AssignAreaToBulbForm 76 | // 77 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 79 | this.ClientSize = new System.Drawing.Size(284, 173); 80 | this.Controls.Add(this.label1); 81 | this.Controls.Add(this.cbArea); 82 | this.Controls.Add(this.lbBulbs); 83 | this.Controls.Add(this.button1); 84 | this.Name = "AssignAreaToBulbForm"; 85 | this.Text = "AssignAreaToBulbForm"; 86 | this.ResumeLayout(false); 87 | this.PerformLayout(); 88 | 89 | } 90 | 91 | #endregion 92 | 93 | private System.Windows.Forms.Button button1; 94 | private System.Windows.Forms.ListBox lbBulbs; 95 | private System.Windows.Forms.ComboBox cbArea; 96 | private System.Windows.Forms.Label label1; 97 | } 98 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/AssignAreaToBulbForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using MaxLifx.Controllers; 6 | 7 | namespace MaxLifx 8 | { 9 | public partial class AssignAreaToBulbForm : Form 10 | { 11 | public List LabelsAndLocations; 12 | public BulbSetting SelectedLabelAndLocation; 13 | private bool _suspendUi; 14 | 15 | public AssignAreaToBulbForm(List labelsAndLocations) 16 | { 17 | LabelsAndLocations = labelsAndLocations; 18 | InitializeComponent(); 19 | foreach (var l in LabelsAndLocations.OrderBy(x => x.Label)) 20 | lbBulbs.Items.Add(l.Label); 21 | 22 | foreach (var v in Enum.GetNames(typeof (ScreenLocation)).OrderBy(x => x)) 23 | cbArea.Items.Add(v); 24 | } 25 | 26 | private void button1_Click(object sender, EventArgs e) 27 | { 28 | Close(); 29 | } 30 | 31 | private void lbBulbs_SelectedIndexChanged(object sender, EventArgs e) 32 | { 33 | if (_suspendUi) return; 34 | _suspendUi = true; 35 | if (lbBulbs.SelectedItem == null) 36 | { 37 | cbArea.Enabled = false; 38 | return; 39 | } 40 | 41 | SelectedLabelAndLocation = 42 | LabelsAndLocations.Single(x => x.Label == (((ListBox) sender).SelectedItem.ToString())); 43 | 44 | foreach (var v in cbArea.Items) 45 | if (v.ToString() == Enum.GetName(typeof (ScreenLocation), SelectedLabelAndLocation.ScreenLocation)) 46 | cbArea.SelectedItem = v; 47 | 48 | cbArea.Enabled = true; 49 | 50 | _suspendUi = false; 51 | } 52 | 53 | private void cbArea_SelectedIndexChanged(object sender, EventArgs e) 54 | { 55 | if (_suspendUi) return; 56 | _suspendUi = true; 57 | 58 | LabelsAndLocations.Remove(LabelsAndLocations.Single(x => x.Label == SelectedLabelAndLocation.Label)); 59 | var l = new BulbSetting(); 60 | l.Label = SelectedLabelAndLocation.Label; 61 | l.Zones = SelectedLabelAndLocation.Zones; 62 | l.ScreenLocation = 63 | (ScreenLocation) (Enum.Parse(typeof (ScreenLocation), ((ComboBox) sender).SelectedItem.ToString())); 64 | LabelsAndLocations.Add(l); 65 | _suspendUi = false; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/AssignAreaToBulbForm.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 | -------------------------------------------------------------------------------- /MaxLifx/UIs/EditTimelineEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using MaxLifx.Controls; 6 | 7 | namespace MaxLifx.UIs 8 | { 9 | public partial class EditTimelineEvent : Form 10 | { 11 | public TimelineEvent EditEvent; 12 | 13 | public EditTimelineEvent(TimelineEvent eventToEdit, bool editMultiple) 14 | { 15 | InitializeComponent(); 16 | 17 | if (editMultiple) tbTime.Visible = false; 18 | 19 | EditEvent = eventToEdit; 20 | tbParameter.Text = eventToEdit.Parameter; 21 | tbTime.Text = (eventToEdit.Time/1000).ToString(); 22 | 23 | int ctr = 0; 24 | int selectItem = -1; 25 | foreach (var v in Enum.GetNames(typeof (TimelineEventAction)).OrderBy(x => x)) 26 | { 27 | cbEventType.Items.Add(v); 28 | if (v == eventToEdit.Action.ToString()) 29 | selectItem = ctr; 30 | 31 | ctr++; 32 | } 33 | 34 | if (selectItem > -1) 35 | cbEventType.SelectedIndex = selectItem; 36 | } 37 | 38 | private void bCancel_Click(object sender, EventArgs e) 39 | { 40 | Close(); 41 | } 42 | 43 | private void bOK_Click(object sender, EventArgs e) 44 | { 45 | DialogResult = DialogResult.OK; 46 | Close(); 47 | } 48 | 49 | private void tbTime_TextChanged(object sender, EventArgs e) 50 | { 51 | float ms; 52 | if (float.TryParse(tbTime.Text, out ms)) 53 | EditEvent.Time = (long)(ms*1000); 54 | } 55 | 56 | private void cbEventType_SelectedIndexChanged(object sender, EventArgs e) 57 | { 58 | TimelineEventAction s; 59 | if (Enum.TryParse(cbEventType.SelectedItem.ToString(), out s)) 60 | { 61 | EditEvent.Action = s; 62 | } 63 | } 64 | 65 | private void tbParameter_TextChanged(object sender, EventArgs e) 66 | { 67 | EditEvent.Parameter = tbParameter.Text; 68 | } 69 | 70 | private void bBrowse_Click(object sender, EventArgs e) 71 | { 72 | if (EditEvent.Action == TimelineEventAction.Unspecified) 73 | { 74 | MessageBox.Show("Choose an action first."); 75 | return; 76 | } 77 | 78 | var s = new OpenFileDialog(); 79 | switch (EditEvent.Action) 80 | { 81 | case TimelineEventAction.PlayMp3: 82 | s.DefaultExt = ".mp3"; 83 | s.Filter = "MP3 files (*.mp3)|*.mp3"; 84 | break; 85 | case TimelineEventAction.StartThreadSet: 86 | s.DefaultExt = ".MaxLifx.Threadset.xml"; 87 | s.Filter = "XML files (*.MaxLifx.Threadset.xml)|*.MaxLifx.Threadset.xml"; 88 | break; 89 | } 90 | 91 | s.InitialDirectory = Directory.GetCurrentDirectory(); 92 | s.AddExtension = true; 93 | 94 | if (s.ShowDialog() == DialogResult.OK) 95 | { 96 | tbParameter.Text = s.FileName; 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /MaxLifx/UIs/EditTimelineEvent.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 | -------------------------------------------------------------------------------- /MaxLifx/UIs/FakeBulb.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx.UIs 2 | { 3 | partial class FakeBulb 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.SuspendLayout(); 32 | // 33 | // FakeBulb 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.ClientSize = new System.Drawing.Size(284, 261); 38 | this.Name = "FakeBulb"; 39 | this.ShowInTaskbar = false; 40 | this.Text = "FakeBulb"; 41 | this.DoubleClick += new System.EventHandler(this.FakeBulb_DoubleClick); 42 | this.ResumeLayout(false); 43 | 44 | } 45 | 46 | #endregion 47 | } 48 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/FakeBulb.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using MaxLifx.Controllers; 4 | 5 | namespace MaxLifx.UIs 6 | { 7 | public partial class FakeBulb : Form 8 | { 9 | public string Label; 10 | 11 | public FakeBulb(MaxLifxBulbController bulbController, string label) 12 | { 13 | InitializeComponent(); 14 | Label = label; 15 | bulbController.ColourSet += SetColour; 16 | } 17 | 18 | public void SetColour(object sender, EventArgs e) 19 | { 20 | LabelAndColourPayload details = ((LabelAndColourPayload) sender); 21 | 22 | if(details.Label == Label) 23 | BackColor = Utils.HsbToRgb(details.Payload.Hue, details.Payload.Saturation/65535.0f, 24 | details.Payload.Brightness/65535.0f); 25 | } 26 | 27 | private void FakeBulb_DoubleClick(object sender, EventArgs e) 28 | { 29 | if(FormBorderStyle == FormBorderStyle.Sizable) 30 | FormBorderStyle = FormBorderStyle.None; 31 | else FormBorderStyle = FormBorderStyle.Sizable; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MaxLifx/UIs/FakeBulb.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 | -------------------------------------------------------------------------------- /MaxLifx/UIs/Form2.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx 2 | { 3 | partial class Form2 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.SuspendLayout(); 32 | // 33 | // Form2 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.BackColor = System.Drawing.Color.Red; 38 | this.BackgroundImage = global::MaxLifx.Properties.Resources.crosshair; 39 | this.ClientSize = new System.Drawing.Size(204, 75); 40 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 41 | this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); 42 | this.MaximizeBox = false; 43 | this.MinimizeBox = false; 44 | this.Name = "Form2"; 45 | this.ShowInTaskbar = false; 46 | this.Text = "Area Select"; 47 | this.TopMost = true; 48 | this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form2_MouseDown); 49 | this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Form2_MouseUp); 50 | this.ResumeLayout(false); 51 | 52 | } 53 | 54 | #endregion 55 | } 56 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/Form2.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace MaxLifx 4 | { 5 | public partial class Form2 : Form 6 | { 7 | public Form2() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | private void Form2_MouseDown(object sender, MouseEventArgs e) 13 | { 14 | } 15 | 16 | private void Form2_MouseUp(object sender, MouseEventArgs e) 17 | { 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/Form2.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 | -------------------------------------------------------------------------------- /MaxLifx/UIs/ProcessorUIs/SoundMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaxLifx.UIs 4 | { 5 | public class SoundMessage 6 | { 7 | public SoundMessageTypes SoundMessageType { get; set; } 8 | public object Parameter { get; set; } 9 | public Type ParameterType { get; set; } 10 | public string SoundUUID { get; set; } 11 | } 12 | 13 | public enum SoundMessageTypes 14 | { 15 | SetVolume, 16 | SetPan 17 | } 18 | } -------------------------------------------------------------------------------- /MaxLifx/UIs/UiFormBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Windows.Forms; 4 | using MaxLifx.Processors.ProcessorSettings; 5 | 6 | namespace MaxLifx.UIs 7 | { 8 | public class UiFormBase : Form 9 | { 10 | public List SelectedLabels { get; set; } = new List(); 11 | 12 | public void SetupLabels(ListBox lbLabels, List labels, ISettings settings) 13 | { 14 | if (labels != null) 15 | { 16 | lbLabels.Items.Clear(); 17 | 18 | foreach (var label in labels.OrderBy(x => x)) 19 | lbLabels.Items.Add(label); 20 | } 21 | else lbLabels.SelectedItems.Clear(); 22 | 23 | for (var i = 0; i < lbLabels.Items.Count; i++) 24 | { 25 | if (settings.SelectedLabels.Contains(lbLabels.Items[i].ToString())) 26 | { 27 | lbLabels.SelectedItems.Add(lbLabels.Items[i]); 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /MaxLifx/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Bulb.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace MaxLifx.Controllers 5 | { 6 | public class Bulb 7 | { 8 | public bool IsHomebrewDevice = false; 9 | 10 | private string _macAddress; 11 | public string MacAddress { get { return _macAddress; } 12 | set 13 | { 14 | _macAddress = value; 15 | if (!_macAddress.StartsWith("D0")) 16 | IsHomebrewDevice = true; 17 | else IsHomebrewDevice = false; 18 | } 19 | } 20 | public string IpAddress { get; set; } 21 | private string _label; 22 | // currently not using Version, but may be useful in the future to distinguish which type of light 23 | // in particular, gen 1 Z lights do not support the extended multizone api 24 | // as reference, the bulbs that support multizones are: 31 (Z), 32 (Z2), 38 (Beam) 25 | //public int Version { get; set; } 26 | public int Zones { get; set; } 27 | public string Label 28 | { 29 | get 30 | { 31 | if (String.IsNullOrEmpty(_label)) 32 | return MacAddress; 33 | return _label; 34 | } 35 | set { _label = value; } 36 | } 37 | 38 | 39 | 40 | // by default, the bulb is set to take average of entire screen 41 | public ScreenLocation Location = ScreenLocation.All; 42 | 43 | 44 | } 45 | 46 | public enum ScreenLocation 47 | { 48 | // None is used to allow proper multizone setup 49 | None, 50 | TopLeft, 51 | TopRight, 52 | Top, 53 | Left, 54 | Right, 55 | BottomLeft, 56 | BottomRight, 57 | Bottom, 58 | All, 59 | SurroundClockwise, 60 | SurroundCounterClockwise 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /MaxLifxBulbController/HomebrewDevicePayloadCache.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Controllers; 2 | using MaxLifx.Payload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MaxLifxBulbControllerCache 10 | { 11 | public class HomebrewDevicePayloadCache 12 | { 13 | public Dictionary<(Bulb, int), SetColourPayload> Payloads = new Dictionary<(Bulb, int), SetColourPayload>(); 14 | 15 | public void Send(Dictionary reusableHomebrewClientDictionary, MaxLifxBulbController bulbController) 16 | { 17 | if (Payloads.Any()) 18 | { 19 | 20 | foreach (var group in Payloads.GroupBy(x => (Bulb)x.Key.Item1)) 21 | { 22 | var payloads = group.Select(x => x.Value); 23 | Dictionary individualPayloads = new Dictionary(); 24 | 25 | int ctr = 0; 26 | foreach (var p in group) 27 | { 28 | individualPayloads.Add(p.Key.Item2, p.Value); 29 | 30 | if (ctr % 80 == 79 || ctr == group.Count() - 1) 31 | { 32 | if (!reusableHomebrewClientDictionary.ContainsKey(group.Key.IpAddress)) 33 | { 34 | reusableHomebrewClientDictionary.Add(group.Key.IpAddress, 35 | MaxLifxBulbController.GetPersistentClient(group.Key.MacAddress, group.Key.IpAddress)); 36 | } 37 | 38 | var payload = new SetHomebrewColourZonesPayload { IndividualPayloads = individualPayloads }; 39 | 40 | bulbController.SendPayloadToMacAddress(payload, group.Key.MacAddress, group.Key.IpAddress, reusableHomebrewClientDictionary[group.Key.IpAddress]); 41 | 42 | individualPayloads = new Dictionary(); 43 | } 44 | 45 | ctr++; 46 | } 47 | 48 | 49 | 50 | 51 | // foreach(var p in group.ToDictionary(x => x.Key.Item2, x => x.Value)) 52 | // MaxLifxBulbController.SendPayloadToMacAddress(p.Value, group.Key.MacAddress, group.Key.IpAddress); 53 | } 54 | 55 | 56 | 57 | 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /MaxLifxBulbController/MaxLifxBulbController.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {53625BB1-4234-4348-9952-2624E9BC9BA8} 8 | Library 9 | Properties 10 | MaxLifxBulbController 11 | MaxLifxBulbController 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | ..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/GetColourZonesPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class GetColourZonesPayload : IPayload 11 | // although this is GetColourZones, we are really just calling this to get StateZone for the count of zones 12 | { 13 | private byte[] _messageType = new byte[2] { 0xF6, 0x01 }; 14 | public byte[] MessageType { get { return _messageType; } } 15 | public int Hue { get; set; } 16 | public byte start_index = 0; 17 | public byte end_index = 0; 18 | public byte[] GetPayload() 19 | { 20 | var _start_index = BitConverter.GetBytes(start_index); 21 | var _end_index = BitConverter.GetBytes(end_index); 22 | return new byte[0].Concat(_start_index).Concat(_end_index).ToArray(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/GetLabelPayload.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace MaxLifx.Payload 3 | { 4 | /// 5 | /// Payload for a GetLabel message 6 | /// 7 | public class GetLabelPayload : IPayload 8 | { 9 | private byte[] _messageType = new byte[2] { 23, 0 }; 10 | public byte[] MessageType { get { return _messageType; } } 11 | 12 | public byte[] GetPayload() 13 | { 14 | return new byte[0]; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/GetServicePayload.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx.Payload 2 | { 3 | /// 4 | /// Payload for a GetService (discovery) message 5 | /// 6 | public class GetServicePayload : IPayload 7 | { 8 | private byte[] _messageType = new byte[2] { 0x2, 0 }; 9 | public byte[] MessageType { get { return _messageType; } } 10 | 11 | public byte[] GetPayload() 12 | { 13 | return new byte[0]; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/GetVersionPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class GetVersionPayload : IPayload 11 | // getting the version info will let us know if light has zones (Beam or Z) 12 | { 13 | private byte[] _messageType = new byte[2] { 0x12, 0 }; 14 | public byte[] MessageType { get { return _messageType; } } 15 | 16 | public byte[] GetPayload() 17 | { 18 | return new byte[0]; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/IPayload.cs: -------------------------------------------------------------------------------- 1 | namespace MaxLifx.Payload 2 | { 3 | public interface IPayload 4 | { 5 | byte[] MessageType { get; } 6 | byte[] GetPayload(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/SetColourPayload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace MaxLifx.Payload 5 | { 6 | /// 7 | /// Payload for a SetColour message 8 | /// 9 | public class SetColourPayload : IPayload 10 | { 11 | private byte[] _messageType = new byte[2] { 0x66, 0 }; 12 | public byte[] MessageType { get { return _messageType; } } 13 | public int Hue { get; set; } 14 | public UInt16 Saturation { get; set; } 15 | public UInt16 Brightness { get; set; } 16 | public UInt16 Kelvin { get; set; } 17 | public UInt32 TransitionDuration { get; set; } 18 | 19 | // The following is interpreted from https://community.lifx.com/t/building-a-lifx-packet/59 20 | public byte[] GetPayload() 21 | { 22 | if (Hue < 0) 23 | Hue = Hue + 36000; 24 | Hue = Hue % 360; 25 | 26 | // Payload 27 | // The payload starts with a reserved field of 8 bits (1 bytes). 28 | var _payloadReserved = new byte[1]; 29 | 30 | // HSBK colour: Next up is the color described in HSBK. The HSBK format is described at the top of the light messages7 page. 31 | // It starts with a 16 bit (2 byte) integer representing the Hue. The hue of green is 120 degrees. Our scale however 32 | // goes from 1-65535 instead of the traditional 1-360 hue scale. To represent this we use a simple formula to find the 33 | // hue in our range. 120 / 360 * 65535 which yields a result of 21845. This is 0x5555 in hex. In our case it isn't important, 34 | // but remember to represent this number in little endian. 35 | 36 | // Watch out, BitConverter.GetBytes returns a little endian answer so we needn't reverse the result 37 | //var hue = r.Next(360); 38 | var _hsbkColourLE = BitConverter.GetBytes((Hue * 65535) / 360); 39 | var _hsbkColour = new byte[2] { _hsbkColourLE[0], _hsbkColourLE[1] }; 40 | 41 | // We want maximum saturation which in a 16bit (2 byte) value is represented as 0xFFFF. 42 | var _saturation = BitConverter.GetBytes(Saturation); 43 | var _brightness = BitConverter.GetBytes(Brightness); 44 | 45 | // Finally we set the Kelvin to mid-range which is 3500 in decimal or 0x0DAC. 46 | var _kelvin = BitConverter.GetBytes(Kelvin); 47 | 48 | // The final part of our payload is the number of milliseconds over which to perform the transition. Lets set it to 49 | // 1024ms because its an easy number and this is getting complicated. 1024 is 0x00000400 in hex. 50 | // var _transitionLE = BitConverter.GetBytes(1024); 51 | // is 4 bytes 52 | var _transition = BitConverter.GetBytes(TransitionDuration); 53 | 54 | var _payload = _payloadReserved.Concat(_hsbkColour) 55 | .Concat(_saturation) 56 | .Concat(_brightness) 57 | .Concat(_kelvin) 58 | .Concat(_transition) 59 | .ToArray(); 60 | return _payload; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/SetColourZonesPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Payload; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MaxLifx.Payload 9 | { 10 | public class SetColourZonesPayload : SetColourPayload, IPayload 11 | { 12 | private byte[] _messageType = new byte[2] { 0xF5, 0x01 }; 13 | public new byte[] MessageType { get { return _messageType; } } 14 | public byte[] start_index { get; set; } 15 | public byte[] end_index { get; set; } 16 | 17 | public byte[] apply { get; set; } 18 | 19 | public new byte[] GetPayload() { 20 | 21 | // Multizone packet example 22 | // RECALL: uses little endian(bytes reversed) 23 | // 24 | //format & size: Frame(8B *) Frame Address(16B *) Protocol Header(12B *) Payload(15B in this example) 25 | // |----------------| |---------------------------------| |------------------------| |-----------------------------------| 26 | // | | | | | | | | 27 | //decimal value: 51 1 0* False True 0* 0* 10 65535 3500 1 28 | //field: size source target S/N reserved (res_r + ack_r + reserved) rsvd e_i sat. kel. apply 29 | // |~~| |~~~~~~| |~~~~~~~~~~~~~~| |~~~~~~~~~~| || |~~| || |~~| |~~| | 30 | //bytes: 3300 0014 01000000 d073d5XXXXXXXXXX 000000000000 02 01 0000000000000000 f501 0000 0a 0a 1c47 ffff ff7f ac0d e80300000 1 31 | // |~~| || |~~~~~~~~~~~~~~| |~~| || |~~| |~~| |~~~~~~~| 32 | //field: (protocol + addressable + tagged + origin) seq. reserved pkg type s_i hue bri. duration 33 | //decimal value: 1024* True* False 0* 1 0* 501 10 10 32767 1000 34 | // 35 | //Notes: 36 | // - * indicates mandatory value/ size 37 | // - for the fields that have plus symbol, certain bits in the byte belong to different fields; need to work in binary to get value that converts to hex 38 | 39 | 40 | if (Hue < 0) 41 | Hue = Hue + 36000; 42 | Hue = Hue % 360; 43 | 44 | // Payload 45 | 46 | // HSBK colour: Next up is the color described in HSBK. The HSBK format is described at the top of the light messages7 page. 47 | // It starts with a 16 bit (2 byte) integer representing the Hue. The hue of green is 120 degrees. Our scale however 48 | // goes from 1-65535 instead of the traditional 1-360 hue scale. To represent this we use a simple formula to find the 49 | // hue in our range. 120 / 360 * 65535 which yields a result of 21845. This is 0x5555 in hex. In our case it isn't important, 50 | // but remember to represent this number in little endian. 51 | 52 | // Watch out, BitConverter.GetBytes returns a little endian answer so we needn't reverse the result 53 | //var hue = r.Next(360); 54 | var _hsbkColourLE = BitConverter.GetBytes((Hue * 65535) / 360); 55 | var _hsbkColour = new byte[2] { _hsbkColourLE[0], _hsbkColourLE[1] }; 56 | 57 | // We want maximum saturation which in a 16bit (2 byte) value is represented as 0xFFFF. 58 | var _saturation = BitConverter.GetBytes(Saturation); 59 | var _brightness = BitConverter.GetBytes(Brightness); 60 | 61 | // Finally we set the Kelvin to mid-range which is 3500 in decimal or 0x0DAC. 62 | var _kelvin = BitConverter.GetBytes(Kelvin); 63 | 64 | // The final part of our payload is the number of milliseconds over which to perform the transition. Lets set it to 65 | // 1024ms because its an easy number and this is getting complicated. 1024 is 0x00000400 in hex. 66 | // var _transitionLE = BitConverter.GetBytes(1024); 67 | // is 4 bytes 68 | var _transition = BitConverter.GetBytes(TransitionDuration); 69 | 70 | var _payload = start_index.Concat(end_index) 71 | .Concat(_hsbkColour) 72 | .Concat(_saturation) 73 | .Concat(_brightness) 74 | .Concat(_kelvin) 75 | .Concat(_transition) 76 | .Concat(apply) 77 | .ToArray(); 78 | return _payload; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/SetHomebrewColourZonesPayload.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Controllers; 2 | using MaxLifx.Payload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MaxLifx.Payload 10 | { 11 | public class SetHomebrewColourZonesPayload : SetColourPayload, IPayload 12 | { 13 | private byte[] _messageType = new byte[2] { 0xF5, 0x01 }; 14 | public new byte[] MessageType { get { return _messageType; } } 15 | 16 | public List Zones { get; set; } 17 | public Dictionary IndividualPayloads { get; set; } 18 | 19 | public new byte[] GetPayload() { 20 | 21 | byte[] bytes = new byte[IndividualPayloads.Count()*10+2]; 22 | bytes[0] = 0; 23 | bytes[1] = (byte)(IndividualPayloads.Count()-1); 24 | 25 | var ctr = 0; 26 | foreach (var individualPayload in IndividualPayloads) 27 | { 28 | var payload = individualPayload.Value; 29 | if (payload.Hue < 0) 30 | payload.Hue = payload.Hue + 36000; 31 | payload.Hue = payload.Hue % 360; 32 | 33 | var _hsbkColourLE = BitConverter.GetBytes(payload.Hue * 182); 34 | //var _hsbkColour = new byte[2] { _hsbkColourLE[0], _hsbkColourLE[1] }; 35 | 36 | //bytes[ctr * 10 + 0 + 2] = (byte)individualPayload.Key ; 37 | //bytes[ctr * 10 + 1+ 2] = (byte)individualPayload.Key ; 38 | 39 | bytes[ctr * 10 + 2] = _hsbkColourLE[0]; 40 | bytes[ctr * 10 + 3] = _hsbkColourLE[1]; 41 | 42 | var _saturation = BitConverter.GetBytes(payload.Saturation); 43 | 44 | bytes[ctr * 10 + 4] = _saturation[0]; 45 | bytes[ctr * 10 + 5] = _saturation[1]; 46 | 47 | var _brightness = BitConverter.GetBytes(payload.Brightness); 48 | 49 | bytes[ctr * 10 + 6] = _brightness[0]; 50 | bytes[ctr * 10 + 7] = _brightness[1]; 51 | 52 | var _kelvin = BitConverter.GetBytes(payload.Kelvin); 53 | 54 | bytes[ctr * 10 + 8] = _kelvin[0]; 55 | bytes[ctr * 10 + 9] = _kelvin[1]; 56 | 57 | var _transition = BitConverter.GetBytes(payload.TransitionDuration); 58 | // 59 | //// faster than array.copy... 60 | bytes[ctr * 10 + 10] = _transition[0]; 61 | bytes[ctr * 10 + 11] = _transition[1]; 62 | //bytes[ctr * 14 + 12+ 2] = _transition[2]; 63 | //bytes[ctr * 14 + 13 + 2] = _transition[3]; 64 | 65 | 66 | 67 | //byte[] start_index = new byte[1] { (byte)individualPayload.Key }; 68 | //byte[] end_index = new byte[1] { (byte)individualPayload.Key }; 69 | // 70 | // 71 | // 72 | //bytes = bytes.Concat(start_index) 73 | // .Concat(end_index) 74 | // .Concat(_hsbkColour) 75 | // .Concat(_saturation) 76 | // .Concat(_brightness) 77 | // .Concat(_kelvin) 78 | // .Concat(_transition) 79 | // .ToArray(); 80 | 81 | ctr++; 82 | 83 | } 84 | //000070DC0000CBCCAC0D6400000000000000000099CFAC0D64000000 85 | return bytes; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/SetMaxLifxColourPayload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace MaxLifx.Payload 5 | { 6 | /// 7 | /// Payload for a SetColour message 8 | /// 9 | public class SetMaxLifxColourPayload : SetColourPayload, IPayload 10 | { 11 | private byte[] _messageType = new byte[2] { 0xF5, 1 }; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Payload/SetPowerPayload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace MaxLifx.Payload 5 | { 6 | /// 7 | /// Payload for a GetLabel message 8 | /// 9 | public class SetPowerPayload : IPayload 10 | { 11 | private byte[] _messageType = new byte[2] { 21, 0 }; 12 | public byte[] MessageType { get { return _messageType; } } 13 | 14 | public bool PowerState; 15 | 16 | public SetPowerPayload(bool powerState) 17 | { 18 | PowerState = powerState; 19 | } 20 | 21 | public byte[] GetPayload() 22 | { 23 | ushort x = (ushort)(PowerState ? 65535 : 0); 24 | 25 | return new byte[0].Concat(BitConverter.GetBytes(x)).ToArray(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MaxLifxBulbController/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("MaxLifxBulbController")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MaxLifxBulbController")] 13 | [assembly: AssemblyCopyright("Copyright © 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("53625bb1-4234-4348-9952-2624e9bc9ba8")] 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 | -------------------------------------------------------------------------------- /MaxLifxBulbController/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Sockets; 7 | 8 | namespace MaxLifx.Util 9 | { 10 | public static class Utils 11 | { 12 | public static IList Clone(this IList listToClone) where T : ICloneable 13 | { 14 | return listToClone.Select(item => (T)item.Clone()).ToList(); 15 | } 16 | 17 | // LocalIPAddress, patched by clarkinator 18 | public static string LocalIPAddress() 19 | { 20 | string localIP; 21 | using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0)) 22 | { 23 | socket.Connect("8.8.8.8", 65530); 24 | IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint; 25 | 26 | localIP = endPoint?.Address.ToString(); 27 | } 28 | return localIP; 29 | } 30 | 31 | public static void SetBit(ref byte[] b, int bitIndex) 32 | { 33 | var bitArray = new BitArray(b); 34 | bitArray.Set(bitIndex, true); 35 | bitArray.CopyTo(b, 0); 36 | } 37 | 38 | public static string HexToAscii(String hexString) 39 | { 40 | try 41 | { 42 | string ascii = string.Empty; 43 | for (int i = 0; i < hexString.Length; i += 2) 44 | { 45 | String hs = string.Empty; 46 | hs = hexString.Substring(i, 2); 47 | uint decval = System.Convert.ToUInt32(hs, 16); 48 | char character = System.Convert.ToChar(decval); 49 | ascii += character; 50 | } 51 | return ascii; 52 | } 53 | catch (Exception ex) { Console.WriteLine(ex.Message); } 54 | return string.Empty; 55 | } 56 | 57 | public static string ByteArrayToString(byte[] b) 58 | { 59 | return BitConverter.ToString(b.ToArray()).Replace("-", ""); 60 | } 61 | 62 | 63 | public static byte[] StringToByteArray(string hex) 64 | { 65 | return Enumerable.Range(0, hex.Length) 66 | .Where(x => x % 2 == 0) 67 | .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) 68 | .ToArray(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /MaxLifxBulbController/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /MaxLifxCmd/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MaxLifxCmd/MaxLifxCmd.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3AE2EFEB-A5DE-4626-9F8F-FC6261A3D0C2} 8 | Exe 9 | Properties 10 | MaxLifxCmd 11 | MaxLifxCmd 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {53625bb1-4234-4348-9952-2624e9bc9ba8} 56 | MaxLifxBulbController 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /MaxLifxCmd/Program.cs: -------------------------------------------------------------------------------- 1 | using MaxLifx.Controllers; 2 | using MaxLifx.Payload; 3 | using System; 4 | 5 | namespace MaxLifxCmd 6 | { 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | 12 | 13 | if (args.Length > 0 && args[0].Contains("list")) 14 | { 15 | MaxLifxBulbController bulbController = new MaxLifxBulbController(); 16 | bulbController.SetupNetwork(); 17 | bulbController.DiscoverBulbs(null); 18 | 19 | foreach (Bulb b in bulbController.Bulbs) 20 | Console.WriteLine(b.Label + " - " + b.MacAddress); 21 | } 22 | else if (args.Length > 0 && args[0].Contains("setcolour")) 23 | { 24 | if (args.Length != 7) 25 | { 26 | B0Rk("Wrong number of arguments for setcolour."); 27 | } 28 | 29 | string macAddress = args[1].ToUpper(); 30 | 31 | int hue; 32 | int.TryParse(args[2], out hue); 33 | ushort sat; 34 | ushort.TryParse(args[3], out sat); 35 | ushort bri; 36 | ushort.TryParse(args[4], out bri); 37 | ushort kel; 38 | ushort.TryParse(args[5], out kel); 39 | UInt32 tra; 40 | UInt32.TryParse(args[6], out tra); 41 | 42 | if (args[1].Length != 12) B0Rk("Mac address must be 12 characters."); 43 | 44 | MaxLifxBulbController bulbController = new MaxLifxBulbController(); 45 | bulbController.SetupNetwork(); 46 | var payload = new SetColourPayload() { Hue = hue, Brightness = bri, Kelvin = kel, Saturation = sat, TransitionDuration = tra }; 47 | //bulbController.SendPayloadToMacAddress(payload, macAddress, ip); 48 | } 49 | else 50 | { 51 | Console.WriteLine("\r\nMaxLifxCmd - a C# LAN protocol Lifx bulb controller\r\n"+ 52 | "===================================================\r\n\r\n"+ 53 | "Usage:\r\n\r\n"+ 54 | "Search for bulbs and list their labels and MAC addresses:\r\n\r\n" + 55 | "maxlifxcmd list\r\n\r\n" + 56 | "Set one or all bulb colours:\r\n\r\n" + 57 | "maxlifxcmd setcolour \r\n" + 58 | " \r\n\r\n"+ 59 | "mac address: ABCDEF012345 or 000000000000 for all bulbs\r\n"+ 60 | "hue : between 0 and 360\r\n"+ 61 | "saturation, brightness, kelvin: between 0 and 65535\r\n"+ 62 | "transition duration: between 0 and "+UInt32.MaxValue+" (ms)"); 63 | 64 | } 65 | 66 | 67 | } 68 | 69 | private static void B0Rk(string s) 70 | { 71 | Console.Write(s); 72 | Environment.Exit(-1); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /MaxLifxCmd/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("MaxLifxCmd")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MaxLifxCmd")] 13 | [assembly: AssemblyCopyright("Copyright © 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("3ae2efeb-a5de-4626-9f8f-fc6261a3d0c2")] 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 | -------------------------------------------------------------------------------- /Media/Demo1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/Media/Demo1.gif -------------------------------------------------------------------------------- /Media/Demo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/Media/Demo2.gif -------------------------------------------------------------------------------- /Media/DemoThmstec.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/Media/DemoThmstec.gif -------------------------------------------------------------------------------- /NAudio license.txt: -------------------------------------------------------------------------------- 1 | Microsoft Public License (Ms-PL) 2 | 3 | This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 4 | 5 | 1. Definitions 6 | 7 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. 8 | 9 | A "contribution" is the original software, or any additions or changes to the software. 10 | 11 | A "contributor" is any person that distributes its contribution under this license. 12 | 13 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 14 | 15 | 2. Grant of Rights 16 | 17 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 18 | 19 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 20 | 21 | 3. Conditions and Limitations 22 | 23 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 24 | 25 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 26 | 27 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 28 | 29 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 30 | 31 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. -------------------------------------------------------------------------------- /NAudio.WindowsMediaFormat.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/NAudio.WindowsMediaFormat.dll -------------------------------------------------------------------------------- /NAudio.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/NAudio.dll -------------------------------------------------------------------------------- /NAudio.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stringandstickytape/MaxLifx/3a90a105ecf2432cde30e1d763cd60f23d342a16/NAudio.pdb -------------------------------------------------------------------------------- /nAudio-readme.txt: -------------------------------------------------------------------------------- 1 | NAudio is an open source .NET audio library written by Mark Heath (mark.heath@gmail.com) 2 | For more information, visit http://naudio.codeplex.com 3 | 4 | THANKS 5 | ====== 6 | The following list includes some of the people who have contributed in various ways to NAudio, such as code contributions, 7 | bug fixes, documentation, helping out on the forums and even donations. I haven't finished compiling this list yet, so 8 | if your name should be on it but isn't please let me know and I will include it. Also, some people I only know by their forum 9 | id, so if you want me to put your full name here, please also get in touch. 10 | 11 | in alphabetical order: 12 | Alexandre Mutel 13 | AmandaTarafaMas 14 | balistof 15 | biermeester 16 | borman11 17 | bradb 18 | Brandon Hansen (kg6ypi) 19 | ChunkWare Music Software 20 | CKing 21 | DaMacc 22 | eejake52 23 | Florian Rosmann (filoe) 24 | Giawa 25 | Hfuy 26 | Iain McCowan 27 | Idael Cardaso 28 | ioctlLR 29 | jbaker8935 30 | jcameron23 31 | jonahoffmann 32 | jontdelorme 33 | Kassoul 34 | kevinxxx 35 | Lustild 36 | Lucian Wischik (ljw1004) 37 | ManuN 38 | MeelMarcel 39 | Michael Feld 40 | Michael J 41 | Nigel Redmon 42 | Nikolaos Georgiou 43 | Owen Skriloff 44 | owoudenb 45 | painmailer 46 | Pygmy 47 | Ray Molenkamp 48 | Robert Bristow-Johnson 49 | Scott Fleischman 50 | Sirish Bajpai 51 | sporn 52 | Steve Underwood 53 | Ted Murphy 54 | Tiny Simple Tools 55 | Tobias Fleming 56 | Tony Cabello 57 | TuneBlade 58 | topher3683 59 | Vladimir Rokovanov 60 | Ville Koskinen 61 | Wyatt Rice 62 | Yuval Naveh 63 | Zsb 64 | --------------------------------------------------------------------------------