Repository: ho0ber/NK2Tray Branch: master Commit: d6fdc587b24f Files: 43 Total size: 256.0 KB Directory structure: gitextract_koccivs3/ ├── .gitattributes ├── .github/ │ └── ISSUE_TEMPLATE/ │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── NK2Tray/ │ ├── App.config │ ├── AudioDevice.cs │ ├── Button.cs │ ├── ConfigSaver.cs │ ├── DevicePathMapper.cs │ ├── EasyControl.cs │ ├── Fader.cs │ ├── FodyWeavers.xml │ ├── FodyWeavers.xsd │ ├── IconExtractor.cs │ ├── MediaTools.cs │ ├── MidiDevice.cs │ ├── MixerSession.cs │ ├── NK2Tray.csproj │ ├── NanoKontrol2.cs │ ├── OP1.cs │ ├── Program.cs │ ├── Properties/ │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ ├── WindowTools.cs │ ├── XtouchMini.cs │ └── packages.config ├── NK2Tray.sln ├── NK2Tray_Display/ │ ├── BOM.md │ ├── NK2DisplayCaseA.stl │ ├── NK2DisplayCaseB.stl │ ├── NK2DisplayLatch.stl │ ├── NK2Tray_DisplayFW.ino │ ├── NK2Tray_DisplayFW_V2/ │ │ ├── NK2Tray_DisplayFW_V2.ino │ │ ├── eeprom.ino │ │ ├── logos.h │ │ ├── readme.md │ │ └── webServer.ino │ └── Readme.md ├── README.md └── license.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto ############################################################################### # Set default behavior for command prompt diff. # # This is need for earlier builds of msysgit that does not have it on by # default for csharp files. # Note: This is only used by command line ############################################################################### #*.cs diff=csharp ############################################################################### # Set the merge driver for project and solution files # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS # the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below ############################################################################### #*.sln merge=binary #*.csproj merge=binary #*.vbproj merge=binary #*.vcxproj merge=binary #*.vcproj merge=binary #*.dbproj merge=binary #*.fsproj merge=binary #*.lsproj merge=binary #*.wixproj merge=binary #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary ############################################################################### # behavior for image files # # image files are treated as binary by default. ############################################################################### #*.jpg binary #*.png binary #*.gif binary ############################################################################### # diff behavior for common document formats # # Convert binary document formats to text before diffing them. This feature # is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain #*.DOC diff=astextplain #*.docx diff=astextplain #*.DOCX diff=astextplain #*.dot diff=astextplain #*.DOT diff=astextplain #*.pdf diff=astextplain #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: "[BUG]" labels: bug assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] **Midi device:** - e.g. Behringer XTouch Mini - e.g. Korg NanoControl **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: "[feature]" labels: enhancement assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # DNX project.lock.json project.fragment.lock.json artifacts/ *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted #*.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/packages/repositories.config # NuGet v3's project.json files produces more ignoreable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings node_modules/ orleans.codegen.cs # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush .cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc NK2Tray.exe.Config Sam's\ Releases/ ================================================ FILE: NK2Tray/App.config ================================================ ================================================ FILE: NK2Tray/AudioDevice.cs ================================================ using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace NK2Tray { public class AudioDevice { public MidiDevice midiDevice; public MMDeviceCollection outputDevices; public MMDeviceCollection inputDevices; private List mixerSessionListCache; private long currentCacheDate; private int cacheExpireTime = 1500; private void UpdateDevices() { // Add audio devices to each fader menu items var deviceEnumerator = new MMDeviceEnumerator(); //device = deviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); //device.AudioSessionManager.OnSessionCreated += OnSessionCreated; //deviceVolume = device.AudioEndpointVolume; outputDevices = deviceEnumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active); inputDevices = deviceEnumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active); foreach (MMDevice mmDevice in outputDevices) { mmDevice.AudioSessionManager.OnSessionCreated += OnSessionCreated; } foreach (MMDevice mmDevice in inputDevices) { mmDevice.AudioSessionManager.OnSessionCreated += OnSessionCreated; } } public AudioEndpointVolume GetDeviceVolumeObject(String deviceIdentifier) { // Used to handle "COM object that has been separated from its underlying RCW cannot be used" issue. UpdateDevices(); return GetDeviceByIdentifier(deviceIdentifier).AudioEndpointVolume; } private void OnSessionCreated(object sender, IAudioSessionControl newSession) { Console.WriteLine("OnSessionCreated"); midiDevice.LoadAssignments(); // These correspond with the below events handlers //NAudioEventCallbacks callbacks = new NAudioEventCallbacks(); //AudioSessionEventsCallback notifications = new AudioSessionEventsCallback(callbacks); //audioSession.RegisterEventClient(callbacks); } /* // Saving these for later because I'll definitely need them. public class NAudioEventCallbacks : IAudioSessionEventsHandler { public void OnChannelVolumeChanged(uint channelCount, IntPtr newVolumes, uint channelIndex) { Console.WriteLine("OnChannelVolumeChanged"); } public void OnDisplayNameChanged(string displayName) { Console.WriteLine("OnDisplayNameChanged"); } public void OnGroupingParamChanged(ref Guid groupingId) { Console.WriteLine("OnGroupingParamChanged"); } public void OnIconPathChanged(string iconPath) { Console.WriteLine("OnIconPathChanged"); } public void OnSessionDisconnected(AudioSessionDisconnectReason disconnectReason) { Console.WriteLine("OnSessionDisconnected"); } public void OnStateChanged(AudioSessionState state) { Console.WriteLine("OnStateChanged"); } public void OnVolumeChanged(float volume, bool isMuted) { Console.WriteLine("OnVolumeChanged"); } } */ public List GetCachedMixerSessions() { if (mixerSessionListCache != null && (currentCacheDate + cacheExpireTime > DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond)) { return mixerSessionListCache; } mixerSessionListCache = GetMixerSessions(); currentCacheDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; return mixerSessionListCache; } private List GetMixerSessions() { var mixerSessions = new List(); var sessionsByIdent = new Dictionary>(); UpdateDevices(); for (int j = 0; j < outputDevices.Count; j++) { var sessions = outputDevices[j].AudioSessionManager.Sessions; for (int i = 0; i < sessions.Count; i++) { var session = sessions[i]; if (session.State != AudioSessionState.AudioSessionStateExpired) { String searchIdentifier = session.GetSessionIdentifier.Substring(session.GetSessionIdentifier.IndexOf("|") + 1, session.GetSessionIdentifier.Length - session.GetSessionIdentifier.IndexOf("|") - 1); if (!sessionsByIdent.ContainsKey(searchIdentifier)) sessionsByIdent[searchIdentifier] = new List(); sessionsByIdent[searchIdentifier].Add(session); } } } /* // Commented out Iput device code because it breaks the session lists when input and ouput is controlled at the same time for (int j = 0; j < inputDevices.Count; j++) { var sessions = inputDevices[j].AudioSessionManager.Sessions; for (int i = 0; i < sessions.Count; i++) { var session = sessions[i]; if (session.State != AudioSessionState.AudioSessionStateExpired) { String searchIdentifier = session.GetSessionIdentifier.Substring(session.GetSessionIdentifier.IndexOf("|") + 1, session.GetSessionIdentifier.Length - session.GetSessionIdentifier.IndexOf("|") - 1); if (!sessionsByIdent.ContainsKey(searchIdentifier)) sessionsByIdent[searchIdentifier] = new List(); sessionsByIdent[searchIdentifier].Add(session); } } } */ foreach (var ident in sessionsByIdent.Keys.ToList()) { var identSessions = sessionsByIdent[ident]; //.OrderBy(i => (int)Process.GetProcessById((int)i.GetProcessID).MainWindowHandle).ToList(); bool dup = identSessions.Count > 1; var process = FindLivingProcess(identSessions); string label = (process != null) ? process.ProcessName : ident; if (HasSystemSoundsSession(identSessions)) label = "System Sounds"; var mixerSession = new MixerSession(this, label, ident, identSessions, SessionType.Application); mixerSessions.Add(mixerSession); } return mixerSessions; } public MMDevice GetDeviceByIdentifier(String identifier) { UpdateDevices(); String deviceId = (identifier==null?"":identifier); if (deviceId.IndexOf("|")>-1) { //work with session identifier also deviceId = deviceId.Substring(0, deviceId.IndexOf("|")); }; for (int i = 0; i < outputDevices.Count; i++) { if (outputDevices[i].ID.Equals(deviceId)) return outputDevices[i]; } for (int i = 0; i < inputDevices.Count; i++) { if (inputDevices[i].ID.Equals(deviceId)) return inputDevices[i]; } //return default if none found (config/save retro-compatibility) var deviceEnumerator = new MMDeviceEnumerator(); return deviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); } public Process FindLivingProcess(List sessions) { Process process = null; foreach (var session in sessions) { try { process = Process.GetProcessById((int)session.GetProcessID); return process; } catch (ArgumentException e) { Console.WriteLine($@"Failed to find process {session.GetProcessID}"); } } return process; } public bool HasSystemSoundsSession(List sessions) { foreach (var session in sessions) if (session.IsSystemSoundsSession) return true; return false; } public MixerSession FindMixerSession(string sessionIdentifier) { var mixerSessions = GetCachedMixerSessions(); foreach (var mixerSession in mixerSessions) { foreach (var session in mixerSession.audioSessions) { if (session.GetSessionIdentifier.Contains(sessionIdentifier)) return mixerSession; } } return null; } private struct ProcessCache { public Process process; public int id; public ProcessCache(Process process, int id) { this.process = process; this.id = id; } } private ProcessCache processCache = new ProcessCache(null, -1); public MixerSession FindMixerSession(int pid) { var mixerSessions = GetCachedMixerSessions(); foreach (var mixerSession in mixerSessions) foreach (var session in mixerSession.audioSessions) if (session.GetProcessID == pid) return mixerSession; // if mixer session was not found becuase the pid does not match the pid of any audio session try finding it by process name // this is necessary since chrome and some other applications have some weired process structure if (processCache.id != pid) { processCache = new ProcessCache(Process.GetProcessById(pid), pid); } Process process = processCache.process; foreach (var mixerSession in mixerSessions) { if (mixerSession.label.Equals(process.ProcessName)) { return mixerSession; } } return null; } } } ================================================ FILE: NK2Tray/Button.cs ================================================ using NAudio.Midi; using System; namespace NK2Tray { public enum ButtonType { MediaPlay, MediaStop, MediaPrevious, MediaNext, MediaRecord } public class Button { private bool activeHandling = false; private bool light = false; public ButtonType buttonType; public int controller; public MidiCommandCode commandCode; public int channel; public MidiOut midiOut; public Button(ref MidiOut midiOutRef, ButtonType butType, int cont, bool initialState, MidiCommandCode code=MidiCommandCode.ControlChange) { commandCode = code; channel = 1; buttonType = butType; controller = cont; midiOut = midiOutRef; SetLight(initialState); } public void SetLight(bool state) { light = state; if (commandCode == MidiCommandCode.ControlChange) midiOut.Send(new ControlChangeEvent(0, channel, (MidiController)(controller), state ? 127 : 0).GetAsShortMessage()); else if (commandCode == MidiCommandCode.NoteOn) midiOut.Send(new NoteOnEvent(0, 1, controller, state ? 127 : 0, 0).GetAsShortMessage()); } public bool HandleEvent(MidiInMessageEventArgs e, MidiDevice device) { if (!IsHandling()) { SetHandling(true); if (e.MidiEvent.CommandCode != commandCode) return false; int c; if (commandCode == MidiCommandCode.ControlChange) { var me = (ControlChangeEvent)e.MidiEvent; if (me.Channel != channel || me.ControllerValue != 127) // Only on correct channel and button-down (127) return false; c = (int)me.Controller; } else if (commandCode == MidiCommandCode.NoteOn) { var me = (NoteEvent)e.MidiEvent; if (me.Channel != channel || me.Velocity != 127) // Only on correct channel and button-down (127) return false; c = me.NoteNumber; } else return false; if (c == controller) { switch (buttonType) { case ButtonType.MediaNext: MediaTools.Next(); break; case ButtonType.MediaPrevious: MediaTools.Previous(); break; case ButtonType.MediaStop: MediaTools.Stop(); break; case ButtonType.MediaPlay: MediaTools.Play(); break; case ButtonType.MediaRecord: device.LightShow(); break; default: break; } return true; } } return false; } public bool IsHandling() { return activeHandling; } public void SetHandling(bool handling) { activeHandling = handling; } public bool GetLight() { return light; } } } ================================================ FILE: NK2Tray/ConfigSaver.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Configuration; namespace NK2Tray { class ConfigSaver { public static void AddOrUpdateAppSettings(string key, string value) { try { var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var settings = configFile.AppSettings.Settings; if (settings[key] == null) { settings.Add(key, value); } else { settings[key].Value = value; } configFile.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name); } catch (ConfigurationErrorsException) { Console.WriteLine("Error writing app settings"); } } public static string GetAppSettings(string key) { try { var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var settings = configFile.AppSettings.Settings; if (settings[key] != null) return settings[key].Value; else return null; } catch { Console.WriteLine("Error getting app settings"); } return null; } } } ================================================ FILE: NK2Tray/DevicePathMapper.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace NK2Tray { public static class DevicePathMapper { [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)] private static extern uint QueryDosDevice([In] string lpDeviceName, [Out] StringBuilder lpTargetPath, [In] int ucchMax); public static string FromDevicePath(string devicePath) { var drive = Array.Find(DriveInfo.GetDrives(), d => devicePath.StartsWith(d.GetDevicePath(), StringComparison.InvariantCultureIgnoreCase)); return drive != null ? devicePath.ReplaceFirst(drive.GetDevicePath(), drive.GetDriveLetter()) : null; } private static string GetDevicePath(this DriveInfo driveInfo) { var devicePathBuilder = new StringBuilder(128); return QueryDosDevice(driveInfo.GetDriveLetter(), devicePathBuilder, devicePathBuilder.Capacity + 1) != 0 ? devicePathBuilder.ToString() : null; } private static string GetDriveLetter(this DriveInfo driveInfo) { return driveInfo.Name.Substring(0, 2); } private static string ReplaceFirst(this string text, string search, string replace) { int pos = text.IndexOf(search); if (pos < 0) { return text; } return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); } } } ================================================ FILE: NK2Tray/EasyControl.cs ================================================ using NAudio.Midi; using System.Collections.Generic; using System.Linq; namespace NK2Tray { public class EasyControl : MidiDevice { public override string SearchString => "easy"; public FaderDef FirstFourFaderDef => new FaderDef( false, // delta 127f, // range 1, // channel false, // selectPresent true, // mutePresent false, // recordPresent false, // subfaderPresent 14, // faderOffset 0, // selectOffset 23, // muteOffset 0, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef SecondFiveFaderDef => new FaderDef( false, // delta 127f, // range 1, // channel false, // selectPresent true, // mutePresent false, // recordPresent false, // subfaderPresent 14, // faderOffset 0, // selectOffset 24, // muteOffset 0, // recordOffset 0, // subfaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef KnobFaderDef => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent false, // recordPresent false, // subfaderPresent 1, // faderOffset 55, // selectOffset 58, // muteOffset 0, // recordOffset 0, // subfaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef HorizontalFaderDef => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent true, // recordPresent false, // subfaderPresent -1, // faderOffset -8, // selectOffset -9, // muteOffset 17, // recordOffset 0, // subfaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public EasyControl(AudioDevice audioDev) { audioDevices = audioDev; FindMidiIn(); FindMidiOut(); if (Found) { ResetAllLights(); InitFaders(); InitButtons(); LoadAssignments(); ListenForMidi(); } } public override void ResetAllLights() { foreach (var i in Enumerable.Range(0, 128)) midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)i, 0).GetAsShortMessage()); } public override void SetLight(int controller, bool state) { midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)(controller), state ? 127 : 0).GetAsShortMessage()); } public override void InitFaders() { faders = new List(); foreach (var i in Enumerable.Range(0, 11)) { Fader fader = new Fader(this, i, SelectFaderDef(i)); fader.ResetLights(); faders.Add(fader); } } public FaderDef SelectFaderDef(int faderNum) { if (faderNum < 4) return FirstFourFaderDef; if (faderNum < 9) return SecondFiveFaderDef; if (faderNum == 9) return KnobFaderDef; return HorizontalFaderDef; } public override void InitButtons() { buttons = new List(); buttons.Add(new Button(ref midiOut, ButtonType.MediaPrevious, 34, true)); buttons.Add(new Button(ref midiOut, ButtonType.MediaNext, 35, true)); buttons.Add(new Button(ref midiOut, ButtonType.MediaStop, 36, false)); buttons.Add(new Button(ref midiOut, ButtonType.MediaPlay, 37, true)); buttons.Add(new Button(ref midiOut, ButtonType.MediaRecord, 38, false)); } } } ================================================ FILE: NK2Tray/Fader.cs ================================================ using NAudio.Midi; using System; using System.Collections.Generic; using System.Linq; namespace NK2Tray { public class FaderDef { public bool delta; public float faderRange; public int channel; public bool selectPresent; public bool mutePresent; public bool recordPresent; public bool subFaderPresent; public int faderOffset; public int selectOffset; public int muteOffset; public int recordOffset; public int subFaderOffset; public MidiCommandCode faderCode; public MidiCommandCode selectCode; public MidiCommandCode muteCode; public MidiCommandCode recordCode; public MidiCommandCode subFaderCode; public int faderChannelOverride; public int selectChannelOverride; public int muteChannelOverride; public int recordChannelOverride; public int subFaderChannelOverride; public FaderDef( bool _delta, float _faderRange, int _channel, bool _selectPresent, bool _mutePresent, bool _recordPresent, bool _subFaderPresent, int _faderOffset, int _selectOffset, int _muteOffset, int _recordOffset, int _subFaderOffset, MidiCommandCode _faderCode, MidiCommandCode _selectCode, MidiCommandCode _muteCode, MidiCommandCode _recordCode, MidiCommandCode _subFaderCode, int _faderChannelOverride = -1, int _selectChannelOverride = -1, int _muteChannelOverride = -1, int _recordChannelOverride = -1, int _subFaderChannelOverride = -1) { delta = _delta; faderRange = _faderRange; channel = _channel; selectPresent = _selectPresent; mutePresent = _mutePresent; recordPresent = _recordPresent; subFaderPresent = _subFaderPresent; faderOffset = _faderOffset; selectOffset = _selectOffset; muteOffset = _muteOffset; recordOffset = _recordOffset; subFaderOffset = _subFaderOffset; faderCode = _faderCode; selectCode = _selectCode; muteCode = _muteCode; recordCode = _recordCode; subFaderCode = _subFaderCode; faderChannelOverride = _faderChannelOverride; selectChannelOverride = _selectChannelOverride; muteChannelOverride = _muteChannelOverride; recordChannelOverride = _recordChannelOverride; subFaderChannelOverride = _subFaderChannelOverride; } } public class Fader { private bool activeHandling = false; private bool selectLight = false; private bool muteLight = false; private bool recordLight = false; public int faderNumber; public FaderDef faderDef; public MixerSession assignment; public bool assigned; public MidiOut midiOut; public MidiDevice parent; public string identifier; public string applicationPath; public string applicationName; public float[] steps; public float pow; public float faderPositionMultiplier; private int primaryFaderHardwareValue; public Fader(MidiDevice midiDevice, int faderNum) { parent = midiDevice; midiOut = midiDevice.midiOut; faderNumber = faderNum; faderDef = parent.DefaultFaderDef; SetCurve(1f); } public Fader(MidiDevice midiDevice, int faderNum, FaderDef _faderDef) { parent = midiDevice; midiOut = midiDevice.midiOut; faderNumber = faderNum; faderDef = _faderDef; SetCurve(1f); } public void SetCurve(float _pow) { pow = _pow; steps = calculateSteps(); parent.SetVolumeIndicator(faderNumber, assignment != null ? assignment.GetVolume() : -1); } private float[] calculateSteps() { if (!faderDef.delta) return new float[0]; return Enumerable.Range(0, (int)faderDef.faderRange + 1).Select(stage => getVolumeFromHardwarePositionUsingMultiplier(stage)).ToArray(); } public float getVolumeFromHardwarePositionUsingMultiplier(float position) { var virtualPosition = position * faderPositionMultiplier; return (float)Math.Pow(virtualPosition / faderDef.faderRange, pow); } public float getVolFromStage(int stage) { return (float)Math.Pow((double)stage / faderDef.faderRange, pow); } private int inputController => faderNumber + faderDef.faderOffset; private int selectController => faderNumber + faderDef.selectOffset; private int muteController => faderNumber + faderDef.muteOffset; private int recordController => faderNumber + faderDef.recordOffset; public void ResetLights() { SetSelectLight(false); SetMuteLight(false); SetRecordLight(false); } public void Assign(MixerSession mixerSession) { assigned = true; assignment = mixerSession; identifier = mixerSession.sessionIdentifier; convertToApplicationPath(identifier); applicationName = mixerSession.label; SetSelectLight(true); SetRecordLight(false); SetMuteLight(mixerSession.GetMute()); if (faderDef.delta) parent.SetVolumeIndicator(faderNumber, mixerSession.GetVolume()); } public void AssignInactive(string ident) { identifier = ident; convertToApplicationPath(identifier); assigned = false; SetSelectLight(true); SetRecordLight(true); SetMuteLight(false); } public void Unassign() { assigned = false; assignment = null; SetSelectLight(false); SetRecordLight(false); SetMuteLight(false); identifier = ""; if (faderDef.delta) parent.SetVolumeIndicator(faderNumber, -1); } private void convertToApplicationPath(string ident) { if ( ident != null && ident != "" && !ident.StartsWith("#") && !ident.Substring(0, Math.Min(10, ident.Length)).Equals("__MASTER__") && ident != "__FOCUS__" ) // TODO cleaner handling of special fader types { //"{0.0.0.00000000}.{...}|\\Device\\HarddiskVolume8\\Users\\Dr. Locke\\AppData\\Roaming\\Spotify\\Spotify.exe%b{00000000-0000-0000-0000-000000000000}" int deviceIndex = ident.IndexOf("\\Device"); int endIndex = ident.IndexOf("%b{"); ident = ident.Substring(deviceIndex, endIndex - deviceIndex); applicationPath = DevicePathMapper.FromDevicePath(ident); } } public void SetSelectLight(bool state) { selectLight = state; parent.SetLight(selectController, state); } public void SetMuteLight(bool state) { muteLight = state; parent.SetLight(muteController, state); } public void SetRecordLight(bool state) { recordLight = state; parent.SetLight(recordController, state); } public bool GetSelectLight() { return selectLight; } public bool GetMuteLight() { return muteLight; } public bool GetRecordLight() { return recordLight; } public bool Match(int faderNumber, MidiEvent midiEvent, MidiCommandCode code, int offset, int channel = -1) { if (channel < 0) channel = faderDef.channel; if (midiEvent.Channel != channel) return false; if (midiEvent.CommandCode != code) return false; if (code == MidiCommandCode.ControlChange) { var me = (ControlChangeEvent)midiEvent; if ((int)me.Controller == faderNumber + offset) return true; } else if (code == MidiCommandCode.NoteOn) { var me = (NoteEvent)midiEvent; if (me.NoteNumber == faderNumber + offset) return true; } else if (code == MidiCommandCode.PitchWheelChange) { return true; } return false; } public int GetValue(MidiEvent midiEvent) { if (midiEvent.CommandCode == MidiCommandCode.ControlChange) { var me = (ControlChangeEvent)midiEvent; return me.ControllerValue; } else if (midiEvent.CommandCode == MidiCommandCode.NoteOn) { var me = (NoteEvent)midiEvent; return me.Velocity; } else if (midiEvent.CommandCode == MidiCommandCode.PitchWheelChange) { var me = (PitchWheelChangeEvent)midiEvent; return me.Pitch; } return 0; } public List GetMatchingFaders() { MixerSession focusMixerSession = null; bool haveFocusSlider = parent.faders.Any(fader => ( fader.assignment != null && fader.assignment.sessionType == SessionType.Focus )); if (haveFocusSlider) { int pid = WindowTools.GetForegroundPID(); focusMixerSession = assignment.devices.FindMixerSession(pid); } if (assignment == null) return parent.faders.FindAll(fader => fader.assignment == null); if (assignment.sessionType == SessionType.Master) { return parent.faders.FindAll(fader => { if (fader == this) return true; if (fader.assignment == null) return false; if (fader.assignment.sessionType != SessionType.Master) return false; return fader.assignment.parentDeviceIdentifier == assignment.parentDeviceIdentifier; }); } if (assignment.sessionType == SessionType.Focus) { return parent.faders.FindAll(fader => { if (fader == this) return true; if (fader.assignment == null) return false; if (fader.assignment.sessionType == SessionType.Focus) return true; return fader.assignment.HasCrossoverProcesses(focusMixerSession); }); } if (assignment.sessionType == SessionType.Application) { return parent.faders.FindAll(fader => { if (fader == this) return true; if (fader.assignment == null) return false; if (fader.assignment.sessionType == SessionType.Application) return fader.assignment.HasCrossoverProcesses(assignment); if (fader.assignment.sessionType == SessionType.Focus) return assignment.HasCrossoverProcesses(focusMixerSession); return false; }); } if (assignment.sessionType == SessionType.SystemSounds) { return parent.faders.FindAll(fader => ( fader.assignment != null && fader.assignment.sessionType == SessionType.SystemSounds )); } return new List(); } public bool HandleEvent(MidiInMessageEventArgs e) { if (!IsHandling()) { SetHandling(true); //if loaded inactive, search again if (!assigned && identifier != null && !identifier.Equals("")) { assignment = parent.audioDevices.FindMixerSession(identifier); if (assignment != null) { assigned = true; } } // Fader match if (assigned && Match(faderNumber, e.MidiEvent, faderDef.faderCode, faderDef.faderOffset, faderDef.faderChannelOverride)) { var hardwareValue = GetValue(e.MidiEvent); primaryFaderHardwareValue = hardwareValue; return SetVolume(hardwareValue); } // SubFader Match if ( faderDef.subFaderPresent && assigned && Match(faderNumber, e.MidiEvent, faderDef.subFaderCode, faderDef.subFaderOffset, faderDef.subFaderChannelOverride)) { this.faderPositionMultiplier = GetValue(e.MidiEvent) / faderDef.faderRange; this.steps = calculateSteps(); return SetVolume(primaryFaderHardwareValue); } // Select match if ( faderDef.selectPresent && Match(faderNumber, e.MidiEvent, faderDef.selectCode, faderDef.selectOffset, faderDef.selectChannelOverride) ) { if (GetValue(e.MidiEvent) != 127) // Only on button-down return true; Console.WriteLine($@"Attempting to assign current window to fader {faderNumber}"); if (assigned) { Unassign(); parent.SaveAssignments(); } else { var pid = WindowTools.GetForegroundPID(); var mixerSession = parent.audioDevices.FindMixerSession(pid); if (mixerSession != null) { Assign(mixerSession); parent.SaveAssignments(); } else Console.WriteLine($@"MixerSession not found for pid {pid}"); } return true; } // Mute match if ( faderDef.mutePresent && assigned && Match(faderNumber, e.MidiEvent, faderDef.muteCode, faderDef.muteOffset, faderDef.muteChannelOverride) ) { if (GetValue(e.MidiEvent) != 127) // Only on button-down return true; var muteStatus = assignment.ToggleMute(); SetMuteLight(muteStatus); if (assignment.IsDead()) { SetRecordLight(true); return true; } List fadersToAffect = GetMatchingFaders(); fadersToAffect.ForEach(fader => fader.SetMuteLight(muteStatus)); return true; } // Record match if ( faderDef.recordPresent && assigned && applicationPath != null && Match(faderNumber, e.MidiEvent, faderDef.recordCode, faderDef.recordOffset, faderDef.recordChannelOverride) ) { if (GetValue(e.MidiEvent) != 127) // Only on button-down return true; if (WindowTools.IsProcessByNameRunning(applicationName)) SetRecordLight(false); else { WindowTools.StartApplication(applicationPath); } return true; } } return false; } /// /// This method sets the volume of the assigned ( if any ) application. /// It utilises the "hardwarePosition" passed as a parameter but in sub calls it will /// augment that value with the value of "faderPositionMultiplier" which is set elsewhere /// /// Position of the primary fader as reported by the MidiDevice /// private bool SetVolume(int hardwarePosition) { if (assignment.sessionType == SessionType.Application) { MixerSession newAssignment = assignment.devices.FindMixerSession(assignment .sessionIdentifier); //update list for re-routered app, but only overrides if (newAssignment == null) //if there is new assignments, otherwise, there is no more a inactive { //MixerSession to hold the label SetRecordLight(true); return true; } assignment = newAssignment; } float newVol; if (faderDef.delta) { var val = hardwarePosition; var volNow = assignment.GetVolume(); var nearestStep = steps.Select((x, i) => new { Index = i, Distance = Math.Abs(volNow - x) }) .OrderBy(x => x.Distance).First().Index; int nextStepIndex; var volumeGoingDown = val > faderDef.faderRange / 2; if (volumeGoingDown) nextStepIndex = Math.Max(nearestStep - 1, 0); else nextStepIndex = Math.Min(nearestStep + 1, steps.Length - 1); newVol = steps[nextStepIndex]; assignment.SetVolume(newVol); } else { newVol = getVolumeFromHardwarePositionUsingMultiplier(hardwarePosition); assignment.SetVolume(newVol); } if (assignment.IsDead()) { SetRecordLight(true); return true; } List fadersToAffect = GetMatchingFaders(); fadersToAffect.ForEach(fader => fader.parent.SetVolumeIndicator(fader.faderNumber, newVol)); return true; } public bool IsHandling() { return activeHandling; } public void SetHandling(bool handling) { activeHandling = handling; } } } ================================================ FILE: NK2Tray/FodyWeavers.xml ================================================ ================================================ FILE: NK2Tray/FodyWeavers.xsd ================================================ A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. A list of unmanaged 32 bit assembly names to include, delimited with line breaks. A list of unmanaged 64 bit assembly names to include, delimited with line breaks. The order of preloaded assemblies, delimited with line breaks. This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. Controls if .pdbs for reference assemblies are also embedded. Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. A list of unmanaged 32 bit assembly names to include, delimited with |. A list of unmanaged 64 bit assembly names to include, delimited with |. The order of preloaded assemblies, delimited with |. 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. A comma-separated list of error codes that can be safely ignored in assembly verification. 'false' to turn off automatic generation of the XML Schema file. ================================================ FILE: NK2Tray/IconExtractor.cs ================================================ using System; using System.Drawing; using System.Runtime.InteropServices; namespace NK2Tray { public class IconExtractor { public static Icon Extract(string file, int number, bool largeIcon) { IntPtr large; IntPtr small; ExtractIconEx(file, number, out large, out small, 1); try { return Icon.FromHandle(largeIcon ? large : small); } catch { return null; } } [DllImport("Shell32.dll")] private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons); } } ================================================ FILE: NK2Tray/MediaTools.cs ================================================ using System; using System.Runtime.InteropServices; namespace NK2Tray { class MediaTools { [DllImport("user32.dll", SetLastError = true)] public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo); public const int VK_MEDIA_NEXT_TRACK = 0xB0; public const int VK_MEDIA_PLAY_PAUSE = 0xB3; public const int VK_MEDIA_PREV_TRACK = 0xB1; public const int VK_MEDIA_STOP = 0xB2; public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag public static void Play() { keybd_event(VK_MEDIA_PLAY_PAUSE, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero); keybd_event(VK_MEDIA_PLAY_PAUSE, 0, KEYEVENTF_KEYUP, IntPtr.Zero); } public static void Stop() { keybd_event(VK_MEDIA_STOP, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero); keybd_event(VK_MEDIA_STOP, 0, KEYEVENTF_KEYUP, IntPtr.Zero); } public static void Next() { keybd_event(VK_MEDIA_NEXT_TRACK, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero); keybd_event(VK_MEDIA_NEXT_TRACK, 0, KEYEVENTF_KEYUP, IntPtr.Zero); } public static void Previous() { keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero); keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_KEYUP, IntPtr.Zero); } } } ================================================ FILE: NK2Tray/MidiDevice.cs ================================================ using NAudio.CoreAudioApi; using NAudio.Midi; using System; using System.Collections; using System.Collections.Generic; using System.Collections; using System.Collections.Generic; using System.Configuration; using System.Linq; namespace NK2Tray { public enum SendEvent { AssignedState, MuteState, ErrorState, MediaPlay, MediaStop, MediaPrevious, MediaNext, MediaRecord } public class MidiDevice { public MidiIn midiIn; public MidiOut midiOut; public List faders; public List buttons; public Hashtable buttonsMappingTable; public AudioDevice audioDevices; public virtual string SearchString => "wobbo"; public virtual FaderDef DefaultFaderDef => new FaderDef( false, 1f, 1, true, true, true, true, 0, 0, 0, 0, 0, MidiCommandCode.ControlChange, MidiCommandCode.ControlChange, MidiCommandCode.ControlChange, MidiCommandCode.ControlChange, MidiCommandCode.ControlChange); public MidiDevice() { Console.WriteLine($@"Initializing Midi Device {SearchString}"); } public bool Found => (midiIn != null && midiOut != null); public void FindMidiIn() { for (int i = 0; i < MidiIn.NumberOfDevices; i++) { Console.WriteLine("MIDI IN: " + MidiIn.DeviceInfo(i).ProductName); if (MidiIn.DeviceInfo(i).ProductName.ToLower().Contains(SearchString)) { midiIn = new MidiIn(i); Console.WriteLine($@"Assigning MidiIn: {MidiIn.DeviceInfo(i).ProductName}"); break; } } } public void FindMidiOut() { for (int i = 0; i < MidiOut.NumberOfDevices; i++) { Console.WriteLine("MIDI OUT: " + MidiOut.DeviceInfo(i).ProductName); if (MidiOut.DeviceInfo(i).ProductName.ToLower().Contains(SearchString)) { midiOut = new MidiOut(i); Console.WriteLine($@"Assigning MidiOut: {MidiOut.DeviceInfo(i).ProductName}"); break; } } } public void ListenForMidi() { midiIn.MessageReceived += midiIn_MessageReceived; midiIn.ErrorReceived += midiIn_ErrorReceived; midiIn.Start(); } public void midiIn_ErrorReceived(object sender, MidiInMessageEventArgs e) { Console.WriteLine(String.Format("Time {0} Message 0x{1:X8} Event {2}", e.Timestamp, e.RawMessage, e.MidiEvent)); } public virtual void midiIn_MessageReceived(object sender, MidiInMessageEventArgs e) { //WindowTools.Dump(e.MidiEvent); foreach (var fader in faders) { fader.HandleEvent(e); fader.SetHandling(false); } //ControlChangeEvent midiController = null; // //try //{ // midiController = (ControlChangeEvent)e.MidiEvent; //} //catch (System.InvalidCastException exc) //{ // return; //} // //if (midiController == null) // return; ////key UP...! //if (midiController.ControllerValue == 0) // return; // //var obj = buttonsMappingTable[(int)midiController.Controller]; //if (obj != null) //{ // Button button = (Button)obj; // button.HandleEvent(e, this); // button.SetHandling(false); //} //else { foreach (var button in buttons) { button.HandleEvent(e, this); button.SetHandling(false); } } } public virtual void ResetAllLights() { } public virtual void LightShow() { } public virtual void SetVolumeIndicator(int fader, float level) { } public virtual void SetLight(int controller, bool state) {} public virtual void InitFaders() { faders = new List(); } public virtual void InitButtons() { buttons = new List(); } public void SetCurve(float pow) { faders.ForEach(fader => fader.SetCurve(pow)); } public void LoadAssignments() { bool foundAssignments = false; foreach (var fader in faders) { Console.WriteLine("Getting setting: " + fader.faderNumber.ToString()); var ident = ConfigSaver.GetAppSettings(fader.faderNumber.ToString()); Console.WriteLine("Got setting: " + ident); if (ident != null) { if (ident.Equals("__FOCUS__")) { foundAssignments = true; fader.Assign(new MixerSession("", audioDevices, "Focus", SessionType.Focus)); } else if (ident.Equals("__MASTER__") || (ident.Substring(0, Math.Min(10, ident.Length)).Equals("__MASTER__"))) { foundAssignments = true; MMDevice mmDevice = audioDevices.GetDeviceByIdentifier(ident.IndexOf("|") >= 0 ? ident.Substring(ident.IndexOf("|")+1) : ""); fader.Assign(new MixerSession(mmDevice.ID, audioDevices, "Master", SessionType.Master)); } else if (ident.Length > 0) { foundAssignments = true; var matchingSession = audioDevices.FindMixerSession(ident); if (matchingSession != null) fader.Assign(matchingSession); else fader.AssignInactive(ident); } else { fader.Unassign(); } } var savedSubFaderPosition = ConfigSaver.GetAppSettings(fader.faderNumber.ToString() + "m"); fader.faderPositionMultiplier = savedSubFaderPosition != null ? float.Parse(savedSubFaderPosition) : 1; } // Load fader 8 as master volume control as default if no faders are set if (!foundAssignments) { if (faders.Count > 0) { faders.Last().Assign(new MixerSession(audioDevices.GetDeviceByIdentifier("").ID, audioDevices, "Master", SessionType.Master)); SaveAssignments(); } } } public void SaveAssignments() { Console.WriteLine("Saving Assignments"); foreach (var fader in faders) { if (fader.assigned) { if (fader.assignment.sessionType == SessionType.Master) ConfigSaver.AddOrUpdateAppSettings(fader.faderNumber.ToString(), "__MASTER__|" + fader.assignment.parentDeviceIdentifier ); else if (fader.assignment.sessionType == SessionType.Focus) ConfigSaver.AddOrUpdateAppSettings(fader.faderNumber.ToString(), "__FOCUS__"); else ConfigSaver.AddOrUpdateAppSettings(fader.faderNumber.ToString(), fader.assignment.sessionIdentifier); } else { ConfigSaver.AddOrUpdateAppSettings(fader.faderNumber.ToString(), ""); } ConfigSaver.AddOrUpdateAppSettings(fader.faderNumber.ToString() + "m", fader.faderPositionMultiplier.ToString()); } } } } ================================================ FILE: NK2Tray/MixerSession.cs ================================================ using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; using System; using System.Collections.Generic; using System.Linq; namespace NK2Tray { public enum SessionType { Application, SystemSounds, Master, Focus } /// /// A MixerSession represents a running application and all audio sessions belonging to it. /// public class MixerSession { public string label; public string sessionIdentifier; public List audioSessions; public SessionType sessionType; public AudioDevice devices; public String parentDeviceIdentifier; public MixerSession(AudioDevice devices, string labl, string identifier, List sessions, SessionType sesType) { this.devices = devices; sessionIdentifier = identifier; audioSessions = sessions; sessionType = sesType; label = labl; } public MixerSession(String deviceIdentifier, AudioDevice devices, string labl, SessionType sesType) { this.devices = devices; sessionIdentifier = ""; audioSessions = new List(); sessionType = sesType; parentDeviceIdentifier = deviceIdentifier; if (sesType == SessionType.Focus) label = "Focus"; else label = devices.GetDeviceByIdentifier(deviceIdentifier).FriendlyName + ": " + labl; } public bool IsDead() { bool alive = false; if (sessionType == SessionType.Application) { foreach (var session in audioSessions) if (session.State != AudioSessionState.AudioSessionStateExpired) alive = true; } else alive = true; return !alive; } public void SetVolume(float volume) { if (sessionType == SessionType.Application) { foreach (var session in audioSessions) session.SimpleAudioVolume.Volume = volume; } else if (sessionType == SessionType.Master) { try { devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.MasterVolumeLevelScalar = volume; } catch (System.Runtime.InteropServices.InvalidComObjectException e) { // This catch handles the "COM object that has been separated from its underlying RCW cannot be used" issue. // I believe this happens when we refresh the device when opening the menu, but this is fine for now. Console.WriteLine($@"Error when setting master volume: {e.Message}"); AudioEndpointVolume deviceVolume = devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume; deviceVolume.MasterVolumeLevelScalar = volume; Console.WriteLine($@"RETRY: Setting master volume to {volume}"); } catch (System.Runtime.InteropServices.COMException e) { //TODO find out where this exception comes from and actually fix it Console.WriteLine("COM Execption" + e); } catch (System.InvalidCastException e) { Console.WriteLine("InvalidCastException Exeception" + e); } } else if (sessionType == SessionType.Focus) { var pid = WindowTools.GetForegroundPID(); var mixerSession = devices.FindMixerSession(pid); // Check if null since mixer session might not exist for currently focused window if (mixerSession != null) { foreach (var session in mixerSession.audioSessions) { session.SimpleAudioVolume.Volume = volume; } } } } public float GetVolume() { if (sessionType == SessionType.Application) { foreach (var session in audioSessions) { var curVol = session.SimpleAudioVolume.Volume; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; return curVol; } } else if (sessionType == SessionType.Master) { try { var curVol = devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.MasterVolumeLevelScalar; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; return curVol; } catch (System.Runtime.InteropServices.InvalidComObjectException e) { // This catch handles the "COM object that has been separated from its underlying RCW cannot be used" issue. // I believe this happens when we refresh the device when opening the menu, but this is fine for now. Console.WriteLine($@"Error when getting master volume: {e.Message}"); var curVol = devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.MasterVolumeLevelScalar; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; return curVol; } } else if (sessionType == SessionType.Focus) { var pid = WindowTools.GetForegroundPID(); var mixerSession = devices.FindMixerSession(pid); if (mixerSession != null) { foreach (var session in mixerSession.audioSessions) { var curVol = session.SimpleAudioVolume.Volume; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; return curVol; } } } return -1; } public float ChangeVolume(float change) { float retVol = -1; if (sessionType == SessionType.Application) { foreach (var session in audioSessions) { if (retVol < 0) { var curVol = session.SimpleAudioVolume.Volume; curVol += change; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; session.SimpleAudioVolume.Volume = curVol; retVol = curVol; } { session.SimpleAudioVolume.Volume = retVol; } } } else if (sessionType == SessionType.Master) { try { var curVol = devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.MasterVolumeLevelScalar; curVol += change; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.MasterVolumeLevelScalar = curVol; retVol = curVol; } catch (System.Runtime.InteropServices.InvalidComObjectException e) { // This catch handles the "COM object that has been separated from its underlying RCW cannot be used" issue. // I believe this happens when we refresh the device when opening the menu, but this is fine for now. Console.WriteLine($@"Error when setting master volume: {e.Message}"); AudioEndpointVolume deviceVolume = devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume; var curVol = deviceVolume.MasterVolumeLevelScalar; curVol += change; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; deviceVolume.MasterVolumeLevelScalar = curVol; Console.WriteLine($@"RETRY: Setting master volume by {change}"); } } else if (sessionType == SessionType.Focus) { var pid = WindowTools.GetForegroundPID(); var mixerSession = devices.FindMixerSession(pid); if( mixerSession != null) { foreach (var session in mixerSession.audioSessions) { var curVol = session.SimpleAudioVolume.Volume; curVol += change; if (curVol < 0) curVol = 0; if (curVol > 1) curVol = 1; session.SimpleAudioVolume.Volume = curVol; retVol = curVol; } } } return retVol; } public bool ToggleMute() { if (sessionType == SessionType.Application) { var muted = !audioSessions.First().SimpleAudioVolume.Mute; foreach (var session in audioSessions) session.SimpleAudioVolume.Mute = muted; return muted; } else if (sessionType == SessionType.Master) { try { var muted = !devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.Mute; devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.Mute = muted; return muted; } catch (System.Runtime.InteropServices.InvalidComObjectException e) { // This catch handles the "COM object that has been separated from its underlying RCW cannot be used" issue. // I believe this happens when we refresh the device when opening the menu, but this is fine for now. Console.WriteLine($@"Error when toggling mute on master volume: {e.Message}"); AudioEndpointVolume deviceVolume = devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume; var muted = !deviceVolume.Mute; deviceVolume.Mute = muted; Console.WriteLine("RETRY: toggling mute on master volume"); return muted; } } else if (sessionType == SessionType.Focus) { var pid = WindowTools.GetForegroundPID(); var mixerSession = devices.FindMixerSession(pid); if (mixerSession != null) { var muted = !mixerSession.audioSessions.First().SimpleAudioVolume.Mute; foreach (var session in mixerSession.audioSessions) session.SimpleAudioVolume.Mute = muted; return muted; } } return false; } public bool GetMute() { if (sessionType == SessionType.Master) return devices.GetDeviceByIdentifier(parentDeviceIdentifier).AudioEndpointVolume.Mute; var targetAudioSessions = audioSessions; if (sessionType == SessionType.Focus) { var pid = WindowTools.GetForegroundPID(); var mixerSession = devices.FindMixerSession(pid); if (mixerSession == null) return false; targetAudioSessions = mixerSession.audioSessions; } return targetAudioSessions.First().SimpleAudioVolume.Mute; } public bool HasCrossoverProcesses(MixerSession other) { if (other == null) return false; return audioSessions.Any(session => other.audioSessions.Any(otherSession => session.GetProcessID == otherSession.GetProcessID ) ); } } } ================================================ FILE: NK2Tray/NK2Tray.csproj ================================================ Debug AnyCPU {F88D8F42-CC15-40AE-9301-043313764C4C} WinExe NK2Tray NK2Tray v4.6.1 512 true true publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 nk2tray.ico ..\packages\Costura.Fody.3.3.0\lib\net40\Costura.dll True ..\packages\NAudio.1.8.5\lib\net35\NAudio.dll Form ResXFileCodeGenerator Resources.Designer.cs Designer True Resources.resx True SettingsSingleFileGenerator Settings.Designer.cs True Settings.settings True False Microsoft .NET Framework 4.6.1 %28x86 und x64%29 true False .NET Framework 3.5 SP1 false This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: NK2Tray/NanoKontrol2.cs ================================================ using NAudio.Midi; using System.Collections; using System.Collections.Generic; using System.Linq; namespace NK2Tray { public class NanoKontrol2 : MidiDevice { public override string SearchString => "nano"; public override FaderDef DefaultFaderDef => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent true, // recordPresent true, // subFaderPresent 0, // faderOffset 32, // selectOffset 48, // muteOffset 64, // recordOffset 16, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public NanoKontrol2(AudioDevice audioDev) { audioDevices = audioDev; FindMidiIn(); FindMidiOut(); if (Found) { ResetAllLights(); InitFaders(); InitButtons(); LightShow(); LoadAssignments(); ListenForMidi(); } } public override void ResetAllLights() { foreach (var i in Enumerable.Range(0, 128)) midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)i, 0).GetAsShortMessage()); } public override void SetLight(int controller, bool state) { midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)(controller), state ? 127 : 0).GetAsShortMessage()); } public override void InitFaders() { faders = new List(); foreach (var i in Enumerable.Range(0, 8)) { Fader fader = new Fader(this, i); fader.ResetLights(); faders.Add(fader); } } public override void InitButtons() { buttons = new List(); buttons.Add(new Button(ref midiOut, ButtonType.MediaPrevious, 43, true)); buttons.Add(new Button(ref midiOut, ButtonType.MediaNext, 44, true)); buttons.Add(new Button(ref midiOut, ButtonType.MediaStop, 42, false)); buttons.Add(new Button(ref midiOut, ButtonType.MediaPlay, 41, true)); buttons.Add(new Button(ref midiOut, ButtonType.MediaRecord, 45, false)); buttonsMappingTable = new Hashtable(); foreach (var button in buttons) { buttonsMappingTable.Add(button.controller, button); } } public override void LightShow() { List lightBackups = new List(); //backup settings and turn them all off foreach (var fader in faders) { lightBackups.Add(new LightShowBackup(fader)); fader.SetSelectLight(false); fader.SetSelectLight(false); fader.SetMuteLight(false); fader.SetRecordLight(false); } foreach (var button in buttons) { lightBackups.Add(new LightShowBackup(button)); button.SetLight(false); } //do light show int travelSpeed = 50; foreach (var button in buttons) { button.SetLight(true); System.Threading.Thread.Sleep(travelSpeed); button.SetLight(false); } foreach (var fader in faders) { fader.SetSelectLight(true); fader.SetMuteLight(true); fader.SetRecordLight(true); System.Threading.Thread.Sleep(travelSpeed); fader.SetSelectLight(false); fader.SetMuteLight(false); fader.SetRecordLight(false); } //reverse for (int i = faders.Count - 1; i >= 0; i--) { var fader = faders[i]; fader.SetSelectLight(true); fader.SetMuteLight(true); fader.SetRecordLight(true); System.Threading.Thread.Sleep(travelSpeed); } for (int i = buttons.Count - 1; i >= 0; i--) { var button = buttons[i]; button.SetLight(true); System.Threading.Thread.Sleep(travelSpeed); } //flash /* for (int i = 2; i > 0; i--) { System.Threading.Thread.Sleep(travelSpeed * 2); if (i != 3) { foreach (var button in buttons) { button.SetLight(true); } foreach (var fader in faders) { fader.SetSelectLight(true); fader.SetMuteLight(true); fader.SetRecordLight(true); } } System.Threading.Thread.Sleep(travelSpeed * 2); foreach (var button in buttons) { button.SetLight(false); } foreach (var fader in faders) { fader.SetSelectLight(false); fader.SetMuteLight(false); fader.SetRecordLight(false); } } foreach (var button in buttons) { button.SetLight(true); } */ //reset settings foreach (var lightBackup in lightBackups) { lightBackup.reset(); } } private class LightShowBackup { private bool[] lightSettings; private Fader fader = null; private Button button = null; public LightShowBackup(Fader inFader) { lightSettings = new bool[3]; lightSettings[0] = inFader.GetSelectLight(); lightSettings[1] = inFader.GetMuteLight(); lightSettings[2] = inFader.GetRecordLight(); fader = inFader; } public LightShowBackup(Button inButton) { lightSettings = new bool[1]; lightSettings[0] = inButton.GetLight(); button = inButton; } public void reset() { if (fader != null) { fader.SetSelectLight(lightSettings[0]); fader.SetMuteLight(lightSettings[1]); fader.SetRecordLight(lightSettings[2]); } else if (button != null) { button.SetLight(lightSettings[0]); } } } } } ================================================ FILE: NK2Tray/OP1.cs ================================================ using NAudio.Midi; using System.Collections; using System.Collections.Generic; using System.Linq; namespace NK2Tray { public class OP1 : MidiDevice { public override string SearchString => "op-1"; public FaderDef FirstFader => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent true, // recordPresent false, // subFaderPresent 1, // faderOffset 64, // selectOffset 50, // muteOffset 51, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef SecondFader => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent true, // recordPresent false, // subFaderPresent 1, // faderOffset 64, // selectOffset 51, // muteOffset 20, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef ThirdFader => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent true, // recordPresent false, // subFaderPresent 1, // faderOffset 64, // selectOffset 20, // muteOffset 21, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef FourthFader => new FaderDef( false, // delta 127f, // range 1, // channel true, // selectPresent true, // mutePresent true, // recordPresent false, // subFaderPresent 1, // faderOffset 64, // selectOffset 21, // muteOffset 22, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.ControlChange, // selectCode MidiCommandCode.ControlChange, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public OP1(AudioDevice audioDev) { audioDevices = audioDev; FindMidiIn(); FindMidiOut(); if (Found) { InitFaders(); InitButtons(); LoadAssignments(); ListenForMidi(); } } public override void InitFaders() { faders = new List { new Fader(this, 0, FirstFader), new Fader(this, 1, SecondFader), new Fader(this, 2, ThirdFader), new Fader(this, 3, FourthFader) }; } public override void InitButtons() { buttons = new List { new Button(ref midiOut, ButtonType.MediaPlay, 39, true), new Button(ref midiOut, ButtonType.MediaStop, 40, false), new Button(ref midiOut, ButtonType.MediaNext, 16, true), new Button(ref midiOut, ButtonType.MediaPrevious, 15, true) }; // is this still needed? buttonsMappingTable = new Hashtable(); foreach (var button in buttons) { buttonsMappingTable.Add(button.controller, button); } } } } ================================================ FILE: NK2Tray/Program.cs ================================================ using NAudio.CoreAudioApi; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Threading; using System.Windows.Forms; using System.Windows.Threading; using NAudio; namespace NK2Tray { public class SysTrayApp : Form { [STAThread] public static void Main() => Application.Run(new SysTrayApp()); private NotifyIcon trayIcon; public MidiDevice midiDevice; public AudioDevice audioDevices; public bool logarithmic; private Dispatcher _workerDispatcher; private Thread _workerThread; public SysTrayApp() { System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; Console.WriteLine($@"NK2 Tray {DateTime.Now}"); // Set up a worker thread to always run SetupDevice and PopUp inside of _workerThread = new Thread(new ThreadStart(() => { _workerDispatcher = Dispatcher.CurrentDispatcher; Dispatcher.Run(); })); _workerThread.Start(); trayIcon = new NotifyIcon { Text = "NK2 Tray", Icon = new Icon(Properties.Resources.nk2tray, 40, 40), ContextMenu = new ContextMenu() }; trayIcon.ContextMenu.Popup += (object sender, EventArgs e) => _workerDispatcher.Invoke(() => OnPopup(sender, e)); trayIcon.Visible = true; while (_workerDispatcher == null) { /* * weird threading situation. * _workerDispatcher = Dispatcher.CurrentDispatcher; and Dispatcher.Run(); must be set in another thread otherwise the gui doesn't work or the program doesn't exit cleanly. * but on faster machines we race to Invoke(SetupDevice); before the other thread has instantiated the _workerDispatcher * easy way to solve is to just wait here until _workerDispatcher is set */ Thread.Sleep(10); } _workerDispatcher.Invoke(SetupDevice); } private Boolean SetupDevice() { audioDevices = new AudioDevice(); midiDevice = new NanoKontrol2(audioDevices); if (!midiDevice.Found) midiDevice = new XtouchMini(audioDevices); if (!midiDevice.Found) midiDevice = new OP1(audioDevices); if (!midiDevice.Found) midiDevice = new EasyControl(audioDevices); audioDevices.midiDevice = midiDevice; logarithmic = System.Convert.ToBoolean(ConfigSaver.GetAppSettings("logarithmic")); SaveLogarithmic(); return midiDevice.Found; } private void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine(e.ExceptionObject.ToString()); MessageBox.Show(e.ExceptionObject.ToString(), "NK2 Tray Error", MessageBoxButtons.OK); if (midiDevice != null) { try { midiDevice.ResetAllLights(); midiDevice.faders.Last().SetRecordLight(true); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } Application.Exit(); } private String getProgramLabel(Fader fader) { if (fader.assigned) return fader.assignment.label; if(fader.identifier != null && fader.identifier.Length > 0 && fader.identifier.Contains(".exe")) { String identifier = fader.identifier; int lastBackSlash = identifier.LastIndexOf('\\') + 1; int programNameLength = identifier.IndexOf(".exe") - lastBackSlash; String progamName = identifier.Substring(lastBackSlash, programNameLength); return progamName; } return ""; } private void OnPopup(object sender, EventArgs e) { ContextMenu trayMenu = (ContextMenu)sender; // Clean old menu items out var oldMenuItems = trayMenu.MenuItems.Cast().ToArray(); foreach (var item in oldMenuItems) item.Dispose(); trayMenu.MenuItems.Clear(); var mixerSessions = audioDevices.GetCachedMixerSessions(); var masterMixerSessionList = new List(); foreach(MMDevice mmDevice in audioDevices.outputDevices) { masterMixerSessionList.Add(new MixerSession(mmDevice.ID, audioDevices, "Master", SessionType.Master)); } /* // Commented out Iput device code because it breaks the session lists when input and ouput is controlled at the same time var micMixerSessionList = new List(); foreach (MMDevice mmDevice in audioDevices.inputDevices) { micMixerSessionList.Add(new MixerSession(mmDevice.ID, audioDevices, "Microphone", SessionType.Master)); } */ MixerSession focusMixerSession; focusMixerSession = new MixerSession("", audioDevices, "Focus", SessionType.Focus); // Dont create context menu if no midi device is connected if(!midiDevice.Found) { if (!SetupDevice()) // This setup call can be removed once proper lifecycle management is implemented, for now this also adds a nice way to reconnect the controller { MessageBox.Show("No midi device detected. Are you sure your device is plugged in correctly?"); return; } } foreach (var fader in midiDevice.faders) { MenuItem faderMenu = new MenuItem($@"Fader {fader.faderNumber + 1} - " + getProgramLabel(fader)); trayMenu.MenuItems.Add(faderMenu); // Add master mixerSession to menu foreach(MixerSession mixerSession in masterMixerSessionList) { MenuItem masterItem = new MenuItem(mixerSession.label, AssignFader); masterItem.Tag = new object[] { fader, mixerSession }; faderMenu.MenuItems.Add(masterItem); } /* // Commented out Iput device code because it breaks the session lists when input and ouput is controlled at the same time faderMenu.MenuItems.Add("-"); foreach (MixerSession mixerSession in micMixerSessionList) { MenuItem micItem = new MenuItem(mixerSession.label, AssignFader); micItem.Tag = new object[] { fader, mixerSession }; faderMenu.MenuItems.Add(micItem); } */ faderMenu.MenuItems.Add("-"); // Add focus mixerSession to menu MenuItem focusItem = new MenuItem(focusMixerSession.label, AssignFader); focusItem.Tag = new object[] { fader, focusMixerSession }; faderMenu.MenuItems.Add(focusItem); faderMenu.MenuItems.Add("-"); // Add application mixer sessions to each fader foreach (var mixerSession in mixerSessions) { MenuItem si = new MenuItem(mixerSession.label, AssignFader); si.Tag = new object[] { fader, mixerSession }; faderMenu.MenuItems.Add(si); } faderMenu.MenuItems.Add("-"); // Add unassign option MenuItem unassignItem = new MenuItem("Unassign", UnassignFader); unassignItem.Tag = new object[] { fader }; faderMenu.MenuItems.Add(unassignItem); } trayMenu.MenuItems.Add("-"); // Add toggle option for logarithmic volume curve MenuItem logCheck = new MenuItem("Logarithmic", ToggleLogarithmic); logCheck.Checked = logarithmic; trayMenu.MenuItems.Add(logCheck); trayMenu.MenuItems.Add("-"); trayMenu.MenuItems.Add("Exit", OnExit); } private void ToggleLogarithmic(object sender, EventArgs e) { logarithmic = !logarithmic; ConfigSaver.AddOrUpdateAppSettings("logarithmic", System.Convert.ToString(logarithmic)); SaveLogarithmic(); } private void SaveLogarithmic() { midiDevice.SetCurve(logarithmic ? 2f : 1f); } private void AssignFader(object sender, EventArgs e) { var fader = (Fader)((object[])((MenuItem)sender).Tag)[0]; var mixerSession = (MixerSession)((object[])((MenuItem)sender).Tag)[1]; fader.Assign(mixerSession); midiDevice.SaveAssignments(); } private void UnassignFader(object sender, EventArgs e) { var fader = (Fader)((object[])((MenuItem)sender).Tag)[0]; fader.Unassign(); midiDevice.SaveAssignments(); } protected override void OnLoad(EventArgs e) { Visible = false; // Hide form window. ShowInTaskbar = false; // Remove from taskbar. base.OnLoad(e); } private void OnExit(object sender, EventArgs e) { try { midiDevice.ResetAllLights(); midiDevice.SaveAssignments(); } catch (MmException ex) { if (ex.Message.StartsWith("InvalidHandle calling midiOutShortMsg")) { // Exit program safely if device was already disconnected } } Application.Exit(); _workerDispatcher.InvokeShutdown(); } } } ================================================ FILE: NK2Tray/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("NK2Tray")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("NK2Tray")] [assembly: AssemblyCopyright("Copyright © 2019")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("f88d8f42-cc15-40ae-9301-043313764c4c")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.16.0")] [assembly: AssemblyFileVersion("0.0.16.0")] ================================================ FILE: NK2Tray/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace NK2Tray.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NK2Tray.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// internal static System.Drawing.Icon nk2tray { get { object obj = ResourceManager.GetObject("nk2tray", resourceCulture); return ((System.Drawing.Icon)(obj)); } } } } ================================================ FILE: NK2Tray/Properties/Resources.resx ================================================ text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ..\nk2tray.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ================================================ FILE: NK2Tray/Properties/Settings.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace NK2Tray.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } public string SavedAssignments { get; internal set; } } } ================================================ FILE: NK2Tray/Properties/Settings.settings ================================================ ================================================ FILE: NK2Tray/WindowTools.cs ================================================ using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace NK2Tray { class WindowTools { [DllImport("user32.dll")] public static extern IntPtr FindWindow(string strClassName, string strWindowName); [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError = true)] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); public static int GetPidByName(string name) { Process[] processes = Process.GetProcessesByName(name); int pid = 0; int maxHandleCount = 0; foreach (Process process in processes) { if (process.Id != 0 && process.HandleCount > maxHandleCount) { maxHandleCount = process.HandleCount; pid = process.Id; } } return pid; /*{ var hWnd = FindWindow(name, ""); if (hWnd == IntPtr.Zero) return 0; uint pID; GetWindowThreadProcessId(hWnd, out pID); if (pID == 0) return 0; Console.WriteLine(pID); return Convert.ToInt32(pID); }*/ } public static int GetForegroundPID() { var hWnd = GetForegroundWindow(); if (hWnd == IntPtr.Zero) return 0; uint pID; GetWindowThreadProcessId(hWnd, out pID); if (pID == 0) return 0; return Convert.ToInt32(pID); } public static bool ProcessExists(uint processId) { try { var process = Process.GetProcessById((int)processId); return true; } catch (ArgumentException) { return false; } } public static void Dump(object ob) { Console.WriteLine("================"); foreach (var prop in ob.GetType().GetProperties()) Console.WriteLine($@"{prop.Name} = {prop.GetValue(ob, null)}"); } public static bool IsProcessByNameRunning(string processName) { return GetPidByName(processName) != 0; } public static void StartApplication(string applicationPath) { try { Process.Start(new ProcessStartInfo(applicationPath)); } catch (InvalidOperationException) { // Application cannot be started for this button } } } } ================================================ FILE: NK2Tray/XtouchMini.cs ================================================ using NAudio.Midi; using System; using System.Collections.Generic; using System.Linq; using System.Collections; namespace NK2Tray { public class XtouchMini : MidiDevice { public override string SearchString => "x-touch mini"; public override FaderDef DefaultFaderDef => new FaderDef( true, // delta 64f, // range 1, // channel true, // selectPresent true, // mutePresent false, // recordPresent false, // subFaderPresent 16, // faderOffset 32, // selectOffset 38, // muteOffset 0, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.NoteOn, // selectCode MidiCommandCode.NoteOn, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef FirstTwoFaderDef => new FaderDef( true, // delta 64f, // range 1, // channel true, // selectPresent true, // mutePresent false, // recordPresent false, // subFaderPresent 16, // faderOffset 32, // selectOffset 89, // muteOffset 0, // recordOffset 0, // subFaderOffset MidiCommandCode.ControlChange, // faderCode MidiCommandCode.NoteOn, // selectCode MidiCommandCode.NoteOn, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange // subFaderCode ); public FaderDef MasterFaderDef => new FaderDef( false, // delta 16256f, // range 1, // channel true, // selectPresent true, // mutePresent false, // recordPresent false, // subFaderPresent 0, // faderOffset 76, // selectOffset 77, // muteOffset 0, // recordOffset 0, // subFaderOffset MidiCommandCode.PitchWheelChange, // faderCode MidiCommandCode.NoteOn, // selectCode MidiCommandCode.NoteOn, // muteCode MidiCommandCode.ControlChange, // recordCode MidiCommandCode.ControlChange, // subFaderCode 9 // faderChannelOverride ); public XtouchMini(AudioDevice audioDev) { audioDevices = audioDev; FindMidiIn(); FindMidiOut(); if (Found) { ResetAllLights(); InitFaders(); InitButtons(); LoadAssignments(); ListenForMidi(); } } public override void SetVolumeIndicator(int faderNum, float level) { if (level >= 0) { var usedLevel = level; var fader = faders[faderNum]; if (fader.faderDef.delta) { var nearestStep = fader.steps.Select((x, i) => new { Index = i, Distance = Math.Abs(level - x) }).OrderBy(x => x.Distance).First().Index; usedLevel = (float)nearestStep / (fader.steps.Length - 1); } var val = (int)Math.Round(usedLevel * 12) + 1 + 16 * 2; Console.WriteLine($@"Setting fader {fader} display to {usedLevel} ({val})"); midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)(faderNum + 48), val).GetAsShortMessage()); } else midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)(faderNum + 48), 0).GetAsShortMessage()); } public override void ResetAllLights() { foreach (var i in Enumerable.Range(48, 8)) midiOut.Send(new ControlChangeEvent(0, 1, (MidiController)i, 0).GetAsShortMessage()); foreach (var i in Enumerable.Range(0, 128)) midiOut.Send(new NoteOnEvent(0, 1, i, 0, 0).GetAsShortMessage()); } public override void SetLight(int controller, bool state) { midiOut.Send(new NoteOnEvent(0, 1, controller, state ? 127 : 0, 0).GetAsShortMessage()); } public override void InitFaders() { faders = new List(); foreach (var i in Enumerable.Range(0, 9)) { Fader fader = new Fader(this, i, SelectFaderDef(i)); fader.ResetLights(); faders.Add(fader); } } public FaderDef SelectFaderDef(int faderNum) { if (faderNum < 2) return FirstTwoFaderDef; else if (faderNum == 8) return MasterFaderDef; else return DefaultFaderDef; } public override void InitButtons() { buttons = new List(); buttons.Add(new Button(ref midiOut, ButtonType.MediaPrevious, 91, true, MidiCommandCode.NoteOn)); buttons.Add(new Button(ref midiOut, ButtonType.MediaNext, 92, true, MidiCommandCode.NoteOn)); buttons.Add(new Button(ref midiOut, ButtonType.MediaStop, 93, false, MidiCommandCode.NoteOn)); buttons.Add(new Button(ref midiOut, ButtonType.MediaPlay, 94, true, MidiCommandCode.NoteOn)); buttons.Add(new Button(ref midiOut, ButtonType.MediaRecord, 95, false, MidiCommandCode.NoteOn)); buttonsMappingTable = new Hashtable(); foreach (var button in buttons) { buttonsMappingTable.Add(button.controller, button); } } } } ================================================ FILE: NK2Tray/packages.config ================================================ ================================================ FILE: NK2Tray.sln ================================================ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.28307.168 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NK2Tray", "NK2Tray\NK2Tray.csproj", "{F88D8F42-CC15-40AE-9301-043313764C4C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F88D8F42-CC15-40AE-9301-043313764C4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F88D8F42-CC15-40AE-9301-043313764C4C}.Debug|Any CPU.Build.0 = Debug|Any CPU {F88D8F42-CC15-40AE-9301-043313764C4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {F88D8F42-CC15-40AE-9301-043313764C4C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1808D8FF-F1C2-4A1F-A929-E9F148BFA9A1} EndGlobalSection EndGlobal ================================================ FILE: NK2Tray_Display/BOM.md ================================================ ## Bill of materials for the NK2Tray_Display ### Printed Parts: 1x NK2DisplayCaseA.stl 1x NK2DisplayCaseB.stl 3x NK2DisplayLatch.stl As the case and the latches do not bear any load, you can use a low infill. 25% is more than enough. Use 2-3 perimeter walls The case is designed to be printed with the face on the print bed, that should get you a nice surface to look at. Print the latches as they are designed and use supports under the overhang. Use at least 3 perimeter walls, again infill doesn´t matter that much. ### Electronic Parts: 8x OLED Display 0.96 inch, 128X64, I2C (get the white OR blue ones, not yellow&blue) https://www.aliexpress.com/item/32713614136.html?spm=a2g0s.9042311.0.0.27424c4dUOH4Fo 1x Wemos D1 Mini V3 https://www.aliexpress.com/item/32855727444.html?spm=a2g0s.9042311.0.0.27424c4dq7waX2 1x Adafruit TCA9548A I2C Multiplexer https://www.amazon.de/gp/product/B017C09ETS/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1 1x Custom PCB Gerber_PCB_NK2Tray_Display.zip ### Fastener: 3x M3x8 Hex Socket screw or similar ### Firmware: NK2Tray_DisplayFW.ino ================================================ FILE: NK2Tray_Display/NK2Tray_DisplayFW.ino ================================================ // Display Firmware V2 // I2C Adressen: // Oled: 0x3C // Multi:0x70 #include "Wire.h" // Hmmm? #include "ssd1306.h" // 128x64 Display Ansteuerung #define MUX_Address 0x70 // TCA9548A Multiplexer Adresse #include // Include the Wi-Fi library #include // Include the Ping library const char* ssid = "Skynet Apocalypse"; // The SSID (name) of the Wi-Fi network you want to connect to const char* password = "chaotisch"; // The password of the Wi-Fi network const IPAddress remote_ip(192, 168, 178, 69); // Zieladresse // Anzuzeigende Bilder: const unsigned char WinLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x03, 0x00, 0x00, 0x00, 0xF0, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x38, 0x3F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0xFF, 0x0F, 0x03, 0x00, 0x00, 0x80, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0xFC, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x3F, 0x07, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char ChromeLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x3C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7E, 0x7C, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0, 0x81, 0x07, 0x1F, 0x3F, 0xFF, 0x7F, 0x1F, 0x0F, 0x83, 0xC1, 0xF1, 0xF0, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF0, 0xC0, 0x80, 0x04, 0x1C, 0x7C, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xC0, 0x80, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xF0, 0xE3, 0xC3, 0xC7, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x07, 0x03, 0x03, 0xC0, 0xE0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x07, 0x81, 0xE0, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x03, 0x00, 0x00, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char DiscordLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0x70, 0x70, 0x38, 0x38, 0x18, 0x18, 0x18, 0x9C, 0x8C, 0x88, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x88, 0x8C, 0x9C, 0x18, 0x18, 0x18, 0x38, 0x38, 0x70, 0x70, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xC7, 0x8F, 0x8F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x8F, 0x8F, 0xC7, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3E, 0x3E, 0x1E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1E, 0x3E, 0x3E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char MumbleLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x20, 0x90, 0xD0, 0xC0, 0xC8, 0xE8, 0xE0, 0xE4, 0xC4, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xC4, 0xE0, 0xE0, 0xE8, 0xC0, 0xC0, 0x90, 0x80, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x10, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x03, 0x0F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x1F, 0x3C, 0x38, 0x30, 0x30, 0x30, 0x38, 0x1C, 0x1F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFA, 0x02, 0x32, 0x22, 0x02, 0xFE, 0x02, 0x02, 0xFE, 0xFE, 0xFE, 0x02, 0x02, 0x32, 0x32, 0x32, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x30, 0xC0, 0x80, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0x7F, 0x40, 0x67, 0x66, 0x60, 0x79, 0x66, 0x40, 0x47, 0x47, 0x47, 0x78, 0x40, 0x46, 0x47, 0x47, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x8F, 0xC0, 0x30, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x11, 0x23, 0x63, 0x47, 0x87, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x78, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x90, 0x93, 0xCF, 0x47, 0x67, 0x23, 0x13, 0x19, 0x0C, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char TeamspeakLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0x78, 0x78, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x78, 0x78, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF4, 0xFE, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0xFE, 0xF4, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xFC, 0xFF, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0xFF, 0xFC, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF8, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1E, 0x08, 0x00, 0x00, 0x00, 0x18, 0x1C, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0x7F, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char SpotifyLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xC1, 0xC1, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC1, 0xC1, 0xC1, 0x81, 0x83, 0x83, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xC1, 0xC1, 0xC3, 0x83, 0x83, 0x87, 0x07, 0x0F, 0x0F, 0x1F, 0x3F, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xE3, 0xE3, 0xE1, 0xE1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xE1, 0xE1, 0xE3, 0xE3, 0xC3, 0xC7, 0x87, 0x8F, 0x8F, 0x1F, 0xBF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Initialize I2C buses using TCA9548A I2C Multiplexer void tcaselect(uint8_t i2c_bus) { if (i2c_bus > 7) return; Wire.beginTransmission(MUX_Address); Wire.write(1 << i2c_bus); Wire.endTransmission(); } // Einmallaufender Code void setup() { Serial.begin(9600); delay(10); Serial.println('\n'); WiFi.begin(ssid, password); // Connect to the network Serial.print("Verbinde mit "); Serial.print(ssid); Serial.println(" ..."); int i = 0; while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect delay(1000); Serial.print(++i); Serial.print(' '); } Serial.println('\n'); Serial.println("Verbindung hergestellt!"); Serial.print("IP Addresse:\t"); Serial.println(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer } //Schleifencode void loop() { if(Ping.ping(remote_ip)) { Serial.println("Monolith ONLINE!"); Serial.println(); bool ret = Ping.ping(remote_ip); Serial.print ("Status: "); Serial.println(ret); int avg_time_ms = Ping.averageTime(); Serial.print("Ping: "); Serial.print(avg_time_ms); Serial.println("ms"); Serial.println(); tcaselect(0); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(45, 56, "Chrome", STYLE_NORMAL); Serial.print("Chrome anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, ChromeLogo); Serial.print("ChromeLogo anzeigen"); Serial.println(""); Serial.println(""); tcaselect(0); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(45, 56, "Chrome", STYLE_NORMAL); Serial.print("Chrome anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, ChromeLogo); Serial.print("ChromeLogo anzeigen"); Serial.println(""); Serial.println(""); tcaselect(2); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(38, 56, "Teamspeak", STYLE_NORMAL); Serial.print("Teamspeak anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, TeamspeakLogo); Serial.print("TeamspeakLogo anzeigen"); Serial.println(""); Serial.println(""); tcaselect(3); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(45, 56, "Mumble", STYLE_NORMAL); Serial.print("Mumble anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, MumbleLogo); Serial.print("MumbleLogo anzeigen"); Serial.println(""); Serial.println(""); tcaselect(4); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(42, 56, "Discord", STYLE_NORMAL); Serial.print("Discord anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, DiscordLogo); Serial.print("DiscordLogo anzeigen"); Serial.println(""); Serial.println(""); tcaselect(6); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(42, 56, "Spotify", STYLE_NORMAL); Serial.print("Spotify anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, SpotifyLogo); Serial.print("SpotifyLogo anzeigen"); Serial.println(""); Serial.println(""); tcaselect(7); ssd1306_128x64_i2c_init(); ssd1306_setFixedFont(ssd1306xled_font6x8); ssd1306_clearScreen(); ssd1306_printFixed(23, 56, "Master Volume", STYLE_NORMAL); Serial.print("Master Volume anzeigen"); Serial.println(""); ssd1306_drawBitmap(32, 0, 64, 56, WinLogo); Serial.print("WinLogo anzeigen"); Serial.println(""); Serial.println("----------------"); while(Ping.ping(remote_ip)) { Serial.println("Warteschleife"); delay (60000); } } else { Serial.println("Monolith nicht ONLINE"); Serial.println("Clearscreen"); Serial.println(); tcaselect(0); ssd1306_clearScreen(); tcaselect(1); ssd1306_clearScreen(); tcaselect(2); ssd1306_clearScreen(); tcaselect(3); ssd1306_clearScreen(); tcaselect(4); ssd1306_clearScreen(); tcaselect(5); ssd1306_clearScreen(); tcaselect(6); ssd1306_clearScreen(); tcaselect(7); ssd1306_clearScreen(); } Serial.println("Verbindung unterbrochen"); Serial.println("Clearscreen"); Serial.println(); tcaselect(0); ssd1306_clearScreen(); tcaselect(1); ssd1306_clearScreen(); tcaselect(2); ssd1306_clearScreen(); tcaselect(3); ssd1306_clearScreen(); tcaselect(4); ssd1306_clearScreen(); tcaselect(5); ssd1306_clearScreen(); tcaselect(6); ssd1306_clearScreen(); tcaselect(7); ssd1306_clearScreen(); delay(5000); } ================================================ FILE: NK2Tray_Display/NK2Tray_DisplayFW_V2/NK2Tray_DisplayFW_V2.ino ================================================ // Display Firmware V2, made by piLo, tweaked by ZeeuwsGamertje // I2C Adressen: // Oled: 0x78 // Multi:0x70 // Directive for Serial Debugging //#define VERBOSE #include "Wire.h" // Wire.h for I2c #include // 128x64 Display Ansteuerung, https://github.com/lexus2k/ssd1306 #include // Include the Wi-Fi library #include // Include the Ping library, https://github.com/dancol90/ESP8266Ping #include // For WiFi Manager #include // For Settings from Webinterface #include // WiFiManager for AP and Client related Stuff #include // For flashing over the Air #include // EEPROM Stuff #include "logos.h" #define MUX_Address 0x70 // TCA9548A Multiplexer Adresse ESP8266WebServer webServer(80); // Init Webserver WiFiManager wifiManager; // Init WiFiManager IPAddress remote_ip(192, 168, 178, 69); // Default value for Remote Host bool rem_host_online; // Online Status Remote Host unsigned long previousMillis = 0; // For periodically Checking Host long interval = 10000; // default value for checking host in s bool always_on = true; // Default value for Always On mode bool refresh_displays = false; // Flag for refreshing displays String local_ip; // String for esp8266 IP String MAC_address; // String for MAC-Address uint8_t MAC_array[6]; // Char Array for MAC Adress char chartmp[50]; // CharTemp for converting Strings to CharArrays int display[] = { 0,0,0,0,0,0,0,0}; // Which Disp show what - default value String icons[] = { "Chrome", "Discord", "Edge", "Empty", "Firefox", "Focus", "Gaming", "Master", "Mic", "Miscellaneous", "Mumble", "OperaGX", "Plex", "Safari", "Spotify", "System Sounds", "Teams", "Teamspeak", "Unassigned", "World of Warcraft", "YT-Music" }; //Possible Values for Icons // Function for initializing I2C buses using TCA9548A I2C Multiplexer void tcaselect(uint8_t i2c_bus) { if (i2c_bus > 7) return; Wire.beginTransmission(MUX_Address); Wire.write(1 << i2c_bus); Wire.endTransmission(); } // Function to set specified display to icon void set_display(int display, int icon) { tcaselect(display); switch (icon) { case 0: ssd1306_printFixed(45, 56, "Chrome", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, chromeLogo); break; case 1: ssd1306_printFixed(42, 56, "Discord", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, discordLogo); break; case 2: ssd1306_printFixed(50, 56, "Edge", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, edgeLogo); break; case 3: ssd1306_printFixed(62, 56, "", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, noLogo); break; case 4: ssd1306_printFixed(42, 56, "Firefox", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, firefoxLogo); break; case 5: ssd1306_printFixed(49, 56, "Focus", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, focusLogo); break; case 6: ssd1306_printFixed(45, 56, "Gaming", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, gamingLogo); break; case 7: ssd1306_printFixed(45, 56, "Master", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, masterLogo); break; case 8: ssd1306_printFixed(54, 56, "Mic", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, micLogo); break; case 9: ssd1306_printFixed(26, 56, "Miscellaneous", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, miscLogo); break; case 10: ssd1306_printFixed(45, 56, "Mumble", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, mumbleLogo); break; case 11: ssd1306_printFixed(42, 56, "OperaGX", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, operagxLogo); break; case 12: ssd1306_printFixed(50, 56, "Plex", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, plexLogo); break; case 13: ssd1306_printFixed(45, 56, "Safari", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, safariLogo); break; case 14: ssd1306_printFixed(42, 56, "Spotify", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, spotifyLogo); break; case 15: ssd1306_printFixed(23, 56, "System Sounds", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, windowsLogo); break; case 16: ssd1306_printFixed(49, 56, "Teams", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, teamsLogo); break; case 17: ssd1306_printFixed(38, 56, "Teamspeak", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, teamspeakLogo); break; case 18: ssd1306_printFixed(36, 56, "Unassigned", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, unassignedLogo); break; case 19: ssd1306_printFixed(54, 56, "WoW", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, wowLogo); break; case 20: ssd1306_printFixed(40, 56, "YT-Music", STYLE_NORMAL); ssd1306_drawBitmap(32, 0, 64, 56, ytmusicLogo); break; } } // function to clear all screens void clear_screens() { for (int i = 0; i <= 7; i++) { tcaselect(i); ssd1306_clearScreen(); } } // function for checking remote host bool check_remote_host() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; if (Ping.ping(remote_ip)) { #ifdef VERBOSE Serial.println("Host ONLINE!"); Serial.println(); int avg_time_ms = Ping.averageTime(); Serial.print("Ping: "); Serial.print(avg_time_ms); Serial.println("ms"); Serial.println(); #endif rem_host_online = true; } else { #ifdef VERBOSE Serial.println("Host offline!"); #endif rem_host_online=false; } } } // function for getting mac address void getMac() { char MAC_char[30] = ""; WiFi.macAddress(MAC_array); // Format the MAC address into string sprintf(MAC_char, "%02X", MAC_array[0]); for (int i = 1; i < 6; ++i) { sprintf(MAC_char, "%s : %02X", MAC_char, MAC_array[i]); } MAC_address = String(MAC_char); } // Setup Code void setup() { EEPROM.begin(512); #ifdef VERBOSE Serial.begin(9600); Serial.println("Setup Started"); #endif wifiManager.autoConnect("NK2Tray_Display"); local_ip = WiFi.localIP().toString(); local_ip.toCharArray(chartmp, 50); getMac(); startWebServer(); ArduinoOTA.setHostname("NK2Tray-Display"); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { for ( int i = 0; i <= 7; i++) { tcaselect(i); ssd1306_drawBitmap(32, 0, 64, 64, firmwareLogo); ssd1306_printFixed(14, 56, "updating firmware", STYLE_NORMAL); #ifdef VERBOSE Serial.printf("Progress: %u%%\r", (progress / (total / 100))); #endif } }); ArduinoOTA.begin(); loadSettings(); for (int i = 0; i <= 7; i++) { tcaselect(i); delay(10); ssd1306_128x64_i2c_init(); delay(10); ssd1306_setFixedFont(ssd1306xled_font6x8); } clear_screens(); tcaselect(0); delay(10); ssd1306_128x64_i2c_init(); delay(10); ssd1306_drawBitmap(0, 0, 128, 64, piloLogo); tcaselect(1); ssd1306_printFixed(34, 32, "Booting...", STYLE_NORMAL); tcaselect(2); ssd1306_printFixed(54, 32, "IP: ", STYLE_NORMAL); tcaselect(3); ssd1306_printFixed(20, 32, chartmp, STYLE_NORMAL); tcaselect(4); ssd1306_printFixed(20, 32, "NK2Tray-Display", STYLE_NORMAL); tcaselect(5); ssd1306_printFixed(15, 32, "Firmware by piLo", STYLE_NORMAL); tcaselect(6); ssd1306_printFixed(0, 30, "Tweaked by", STYLE_NORMAL); ssd1306_printFixed(0, 40, "ZeeuwsGamertje", STYLE_NORMAL); tcaselect(7); ssd1306_drawBitmap(0, 0, 128, 64, zeeuwsLogo); delay(10000); clear_screens(); refresh_displays = true; } //Schleifencode void loop() { if(always_on == true) { if(refresh_displays) { clear_screens(); for (int i = 0; i <= 7; i++) { set_display(i, display[i]); } refresh_displays = false; } } else if (rem_host_online) { if (refresh_displays) { clear_screens(); for (int i = 0; i <= 7; i++) { set_display(i, display[i]); } refresh_displays = false; } } else { clear_screens(); refresh_displays=true; } if(!always_on) { check_remote_host(); } webServer.handleClient(); ArduinoOTA.handle(); } ================================================ FILE: NK2Tray_Display/NK2Tray_DisplayFW_V2/eeprom.ino ================================================ // function to save our variables into EEPROM // Writes OK to 500 & 501 - use this to verify a write bool saveSettings() { #ifdef VERBOSE Serial.print("Saving Settings... "); #endif // Wipe our OK and check EEPROM.write(500, '\0'); EEPROM.write(501, '\0'); EEPROM.commit(); if(EEPROM.read(500) != '\0'|| EEPROM.read(501) != '\0') { #ifdef VERBOSE Serial.println("fail!"); #endif return false; } delay(100); EEPROM.write(100, remote_ip[0]); EEPROM.write(101, remote_ip[1]); EEPROM.write(102, remote_ip[2]); EEPROM.write(103, remote_ip[3]); if (always_on) { EEPROM.write(104, 1); } else { EEPROM.write(104, 0); } for (int i = 0; i <= 7; i++) { EEPROM.write(105+i, display[i]); } EEPROM.write(115, interval/1000); EEPROM.write(500, 'O'); EEPROM.write(501, 'K'); delay(100); EEPROM.commit(); delay (100); // Verify our OK was written & return false if not if(EEPROM.read(500) != 'O' || EEPROM.read(501) != 'K') { #ifdef VERBOSE Serial.println("fail!"); #endif return false; } #ifdef VERBOSE Serial.println("success!"); #endif // Return true if all went well return true; } // Function to load our settings from EEPROM to our variables. bool loadSettings() { #ifdef VERBOSE Serial.print("Loading Settings... "); #endif // Check if we have previous saves. If not, return false if(EEPROM.read(500) != 'O' || EEPROM.read(501) != 'K') { #ifdef VERBOSE Serial.println("No previous saves."); #endif return false; } remote_ip[0] = EEPROM.read(100); remote_ip[1] = EEPROM.read(101); remote_ip[2] = EEPROM.read(102); remote_ip[3] = EEPROM.read(103); if (EEPROM.read(104) == 0) { always_on = false; } else { always_on = true; } for (int i = 0; i <= 7; i++) { display[i] = EEPROM.read(105+i); } interval = EEPROM.read(115) * 1000; #ifdef VERBOSE Serial.println("success!"); #endif // Return return true; } ================================================ FILE: NK2Tray_Display/NK2Tray_DisplayFW_V2/logos.h ================================================ // Anzuzeigende Bilder: // Windows Logo const unsigned char windowsLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x03, 0x00, 0x00, 0x00, 0xF0, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x38, 0x3F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0xFF, 0x0F, 0x03, 0x00, 0x00, 0x80, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0xFC, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x3F, 0x07, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Chrome Logo const unsigned char chromeLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x3C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7E, 0x7C, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0, 0x81, 0x07, 0x1F, 0x3F, 0xFF, 0x7F, 0x1F, 0x0F, 0x83, 0xC1, 0xF1, 0xF0, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF0, 0xC0, 0x80, 0x04, 0x1C, 0x7C, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xC0, 0x80, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xF0, 0xE3, 0xC3, 0xC7, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x07, 0x03, 0x03, 0xC0, 0xE0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x07, 0x81, 0xE0, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x03, 0x00, 0x00, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Discord Logo const unsigned char discordLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0x70, 0x70, 0x38, 0x38, 0x18, 0x18, 0x18, 0x9C, 0x8C, 0x88, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x88, 0x8C, 0x9C, 0x18, 0x18, 0x18, 0x38, 0x38, 0x70, 0x70, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xC7, 0x8F, 0x8F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x8F, 0x8F, 0xC7, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3E, 0x3E, 0x1E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x1E, 0x3E, 0x3E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Mumble Logo const unsigned char mumbleLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x20, 0x90, 0xD0, 0xC0, 0xC8, 0xE8, 0xE0, 0xE4, 0xC4, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0xC4, 0xE0, 0xE0, 0xE8, 0xC0, 0xC0, 0x90, 0x80, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x10, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x03, 0x0F, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x1F, 0x3C, 0x38, 0x30, 0x30, 0x30, 0x38, 0x1C, 0x1F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFA, 0x02, 0x32, 0x22, 0x02, 0xFE, 0x02, 0x02, 0xFE, 0xFE, 0xFE, 0x02, 0x02, 0x32, 0x32, 0x32, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x30, 0xC0, 0x80, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0x7F, 0x40, 0x67, 0x66, 0x60, 0x79, 0x66, 0x40, 0x47, 0x47, 0x47, 0x78, 0x40, 0x46, 0x47, 0x47, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x8F, 0xC0, 0x30, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x11, 0x23, 0x63, 0x47, 0x87, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x78, 0x78, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x90, 0x93, 0xCF, 0x47, 0x67, 0x23, 0x13, 0x19, 0x0C, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Teamspeak Logo const unsigned char teamspeakLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0x78, 0x78, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x78, 0x78, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF4, 0xFE, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0xFE, 0xF4, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xFC, 0xFF, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0xFF, 0xFC, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF8, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1E, 0x08, 0x00, 0x00, 0x00, 0x18, 0x1C, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0x7F, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Spotify Logo const unsigned char spotifyLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xC1, 0xC1, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC1, 0xC1, 0xC1, 0x81, 0x83, 0x83, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xC1, 0xC1, 0xC3, 0x83, 0x83, 0x87, 0x07, 0x0F, 0x0F, 0x1F, 0x3F, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xE3, 0xE3, 0xE1, 0xE1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xE1, 0xE1, 0xE3, 0xE3, 0xC3, 0xC7, 0x87, 0x8F, 0x8F, 0x1F, 0xBF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Plex Logo const unsigned char plexLogo [] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0f, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf8, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xf0, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x1f, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // Focus Logo const unsigned char focusLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0x78, 0x7c, 0x3c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c, 0x3c, 0x7c, 0xf8, 0xf0, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfc, 0xfe, 0xff, 0x1f, 0x0f, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x1f, 0xff, 0xfe, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3f, 0x7f, 0xff, 0xf8, 0xf0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf0, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xff, 0x7f, 0x3f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x0f, 0x1f, 0x1e, 0x3c, 0x3c, 0x78, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x78, 0x3c, 0x3c, 0x3e, 0x1f, 0x0f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Microphone Logo const unsigned char micLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfc, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfc, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x1f, 0x3f, 0x3e, 0x7c, 0x78, 0x78, 0x79, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0x79, 0x78, 0x7c, 0x3c, 0x3f, 0x1f, 0x0f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Speaker Logo const unsigned char masterLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf0, 0xe0, 0x80, 0x03, 0x07, 0x1f, 0x3f, 0xff, 0xfe, 0xfc, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0xf8, 0xfc, 0xfc, 0xf0, 0xc0, 0x00, 0x01, 0x07, 0x7f, 0xff, 0xff, 0xfe, 0xf8, 0x00, 0x00, 0x01, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0x7f, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x80, 0xf8, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0x3f, 0x3f, 0x0f, 0x07, 0x01, 0x80, 0xe0, 0xf8, 0xfe, 0xff, 0xff, 0x3f, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Misc Logo const unsigned char miscLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Gaming Logo const unsigned char gamingLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xfe, 0xfe, 0xfe, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf0, 0xf8, 0x78, 0x3c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1f, 0x1f, 0x1f, 0x1e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1e, 0x1f, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x3c, 0x7c, 0xf8, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xfc, 0xfc, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x7f, 0x7f, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 0x30, 0x70, 0x30, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x1f, 0x3f, 0x3c, 0x78, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x78, 0x78, 0x3f, 0x1f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // pilo logo const unsigned char piloLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x78, 0x3c, 0x3c, 0xfe, 0xfe, 0xfe, 0xe0, 0x00, 0x01, 0x1f, 0xff, 0xff, 0xff, 0xe7, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0xf0, 0x00, 0x01, 0x1f, 0xff, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xe0, 0xe0, 0xf0, 0xf0, 0xf3, 0xf3, 0xf9, 0xf9, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0x1f, 0x01, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf1, 0x63, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x07, 0x00, 0xe0, 0xc6, 0xc7, 0xc7, 0xc7, 0x8f, 0x8f, 0x8f, 0x9e, 0x1e, 0x1e, 0x1e, 0x3c, 0x3c, 0x3c, 0x7f, 0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x7c, 0xfc, 0xf0, 0xf0, 0xf8, 0x7c, 0x3e, 0x1f, 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0xf8, 0xfc, 0x7e, 0x3e, 0x1e, 0x0c, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x07, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x0f, 0xcf, 0xef, 0xfe, 0x7e, 0x3e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x18, 0x3c, 0x3e, 0x7f, 0x7f, 0xff, 0xe7, 0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // firmware update logo const unsigned char firmwareLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xf0, 0x70, 0x78, 0x38, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x1c, 0x1c, 0x3c, 0x38, 0x78, 0x70, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf0, 0xfc, 0x3e, 0x1f, 0x07, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3c, 0xf8, 0xf0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfe, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0xf8, 0xfc, 0x0d, 0xcd, 0xec, 0xec, 0xec, 0xed, 0xec, 0xec, 0xec, 0x0d, 0x0c, 0xf8, 0x00, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1f, 0xff, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x23, 0x22, 0x00, 0x7f, 0xff, 0x80, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x1f, 0xdf, 0xdf, 0xc0, 0xf8, 0x7b, 0x70, 0x70, 0x7c, 0x7c, 0xf0, 0xf0, 0xf8, 0xf8, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x7f, 0xff, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xcc, 0xff, 0xff, 0xff, 0xf0, 0xf8, 0xf0, 0xe0, 0xc1, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xdc, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf8, 0xff, 0x3f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0f, 0x1f, 0x3c, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x07, 0x03, 0x07, 0x07, 0x04, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0x3e, 0x1f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0e, 0x1e, 0x1c, 0x1c, 0x38, 0x38, 0x38, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x60, 0x60, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x0e, 0x0f, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // unassigned logo const unsigned char unassignedLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0x7c, 0x7c, 0x3e, 0x3e, 0x3e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1e, 0x3e, 0x3e, 0x3e, 0x7c, 0x7c, 0xfc, 0xf8, 0xf8, 0xf0, 0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xf8, 0xfc, 0xfe, 0x7f, 0x3f, 0x1f, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf9, 0xff, 0xff, 0x7f, 0x3f, 0x3f, 0x7f, 0xfe, 0xfc, 0xf8, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xff, 0xff, 0xff, 0x3f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x3f, 0xff, 0xff, 0xff, 0xf8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xfc, 0xff, 0xff, 0xff, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1f, 0x3f, 0x7f, 0xfe, 0xfc, 0xfc, 0xfe, 0xff, 0xff, 0x9f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf8, 0xfc, 0xfe, 0x7f, 0x3f, 0x1f, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x1f, 0x3f, 0x3e, 0x3e, 0x7c, 0x7c, 0x7c, 0x78, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x78, 0x7c, 0x7c, 0x7c, 0x3e, 0x3e, 0x3f, 0x1f, 0x1f, 0x0f, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // teams logo const unsigned char teamsLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xf0, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f, 0x9f, 0x8f, 0x8f, 0x8f, 0x87, 0x83, 0x80, 0x80, 0x80, 0x80, 0x83, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x1f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // operaGX logo const unsigned char operagxLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0x78, 0x3c, 0x3c, 0x3e, 0x1e, 0x1e, 0x0f, 0x0f, 0x8f, 0xcf, 0xcf, 0xe7, 0xe7, 0xf7, 0xf7, 0xf7, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf0, 0xfc, 0xfe, 0x7f, 0x1f, 0x0f, 0x03, 0x03, 0x01, 0x00, 0x00, 0x80, 0xc0, 0xf0, 0xf8, 0xfe, 0x3e, 0x1f, 0x0f, 0x07, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x1c, 0x38, 0xf0, 0xf0, 0xe0, 0xc0, 0x80, 0x01, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x7e, 0xfe, 0xfc, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfe, 0xff, 0xff, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x7f, 0xff, 0xfe, 0xf0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1f, 0xff, 0xff, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x7f, 0xff, 0xff, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x7f, 0xff, 0xff, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xfe, 0xff, 0x7f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf8, 0xff, 0xff, 0x3f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x3f, 0x7f, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x01, 0x03, 0x0f, 0x1f, 0x3f, 0x7c, 0xfc, 0xf0, 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x1c, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x80, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0x7e, 0x7f, 0x3f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0f, 0x0f, 0x1e, 0x1e, 0x3c, 0x7c, 0x78, 0x78, 0xf0, 0xf0, 0xf1, 0xf3, 0xf3, 0xf7, 0xe7, 0xef, 0xef, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x7e, 0x7e, 0x7e, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // WoW logo const unsigned char wowLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfe, 0xfe, 0x3e, 0x3f, 0x3f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x3e, 0x7e, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xf0, 0xfc, 0xfe, 0xff, 0x7f, 0x3f, 0x6f, 0x67, 0xe3, 0xe3, 0xe1, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe3, 0xe3, 0xef, 0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf8, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0x1f, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x80, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1f, 0x3f, 0x7f, 0xff, 0xfe, 0xfc, 0xf0, 0xe0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x61, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x63, 0x00, 0x67, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x73, 0x40, 0x80, 0x80, 0xc0, 0xc0, 0xe0, 0xf8, 0xfc, 0xff, 0xff, 0x7f, 0x1f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x07, 0x0f, 0x0f, 0x1f, 0x1f, 0x3f, 0x7e, 0x7e, 0xfc, 0xfc, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfc, 0x7c, 0x7c, 0x7e, 0x3f, 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // empty no logo const unsigned char noLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // ytmusic logo const unsigned char ytmusicLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0xfc, 0xf8, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xdf, 0xe7, 0xf7, 0xfb, 0xfd, 0xfd, 0x3e, 0x7e, 0x7e, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xf9, 0xfb, 0xf7, 0xef, 0x9f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0x81, 0xc1, 0xc3, 0xe3, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf9, 0xf7, 0xef, 0xdf, 0xdf, 0xbf, 0xbe, 0x3e, 0x7f, 0x7f, 0x7f, 0x7f, 0xbf, 0xbf, 0xbf, 0xdf, 0xcf, 0xef, 0xf3, 0xf9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0f, 0x1f, 0x3f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // edge logo const unsigned char edgeLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xfc, 0xfc, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xf8, 0xfc, 0x7e, 0x7f, 0xbf, 0xbf, 0xbf, 0xbf, 0xff, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xbf, 0xbf, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf8, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf7, 0xfb, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1e, 0x1e, 0x1d, 0x3b, 0x27, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xbf, 0xcf, 0xf3, 0xfd, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xcf, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, 0x78, 0x3c, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x7e, 0x7c, 0x79, 0x7b, 0xf7, 0xf7, 0xef, 0xcf, 0xdf, 0xdf, 0xbf, 0xbf, 0xbf, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //firefox logo const unsigned char firefoxLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0xf8, 0xf0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfc, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x60, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0xf8, 0xe0, 0xc0, 0x80, 0x20, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf8, 0xf0, 0xe1, 0xe0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x63, 0xe7, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x0f, 0x0f, 0x0f, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xf0, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0x7f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //safari logo const unsigned char safariLogo [] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x60, 0x30, 0x18, 0x18, 0x08, 0x0c, 0x0c, 0x86, 0x06, 0x06, 0x02, 0x03, 0x03, 0x03, 0x03, 0xe3, 0xe3, 0x03, 0x03, 0x03, 0x03, 0x02, 0x06, 0x06, 0x86, 0x0c, 0x0c, 0x08, 0x18, 0x18, 0x30, 0x60, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x38, 0x1c, 0x0e, 0x03, 0x03, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0x20, 0x10, 0x00, 0x00, 0x01, 0x03, 0x0e, 0x1c, 0x38, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf8, 0x3e, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8, 0xfc, 0x7e, 0x3e, 0x0f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x00, 0x00, 0x07, 0x3e, 0xf8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x0c, 0x06, 0x07, 0x0f, 0x9f, 0xbf, 0x7f, 0x3f, 0x1f, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1f, 0x7c, 0xe0, 0x00, 0x00, 0x00, 0x10, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xf0, 0xd8, 0x46, 0x23, 0x30, 0x18, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0xe0, 0xfc, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x1c, 0x38, 0x70, 0xc0, 0x80, 0x00, 0x00, 0x08, 0x04, 0x03, 0x03, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x80, 0xc0, 0x70, 0x38, 0x1c, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x0c, 0x18, 0x18, 0x10, 0x30, 0x30, 0x61, 0x60, 0x60, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc7, 0xc7, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x60, 0x60, 0x63, 0x30, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //zeeuws' logo const unsigned char zeeuwsLogo [] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x03, 0x03, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0f, 0x0f, 0x0f, 0x0f, 0x1f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x13, 0x1f, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xef, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x80, 0xf0, 0x00, 0xf8, 0xfe, 0xff, 0xff, 0xff, 0xef, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0x00, 0x00, 0x00, 0x07, 0xcf, 0x8f, 0x1f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0x80, 0x00, 0x3f, 0x7c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x06, 0xee, 0xce, 0xce, 0xce, 0x66, 0x66, 0x72, 0x78, 0xfc, 0xf3, 0xcb, 0xc2, 0xe0, 0xf8, 0xf2, 0xe2, 0xe6, 0xee, 0xce, 0xce, 0xce, 0xce, 0xc6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3f, 0x1f, 0x8f, 0x60, 0x3f, 0x3f, 0xff, 0x7f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f, 0xff, 0xff, 0xf8, 0xe0, 0xc0, 0xd0, 0xd0, 0xd0, 0xd0, 0xc0, 0xe0, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x1f, 0x81, 0xc0, 0xe0, 0xf8, 0xf8, 0xfc, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x60, 0x48, 0x40, 0x20, 0x97, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf9, 0x09, 0x03, 0x03, 0x03, 0x03, 0x03, 0x09, 0x19, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1f, 0xff, 0x7f, 0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x06, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ================================================ FILE: NK2Tray_Display/NK2Tray_DisplayFW_V2/readme.md ================================================ # NK2Tray_Display Firmware Upgrade ### Almost complete rewrite of the firmware, addressing some points by chaosgabe ## New Features: - WiFi Connection Manager added (no need to edit things like wifi settings in the code) - Webinterface added (you can choose which display should show which icon) - Always on mode added (displays are always on, can be disabled in order to get the old "ping style") - Firmware Update OTA implemented - Settings are stored on chip - Old "Ping style" got a timeout feature (variable seconds without Ping response will disable the displays) - more Icons added - even more Icons added ## Using After first flashing of this firmware, the device will set up his own ssid (NK2Tray-Display) to configure the connection to wifi. When connected, you should get pointed to the config page. if not, navigate to http://192.168.4.1 after setting up the wifi, the device will restart and show its IP address on the displays. The booting up screen will disappear after 10 seconds. After that, you can access the webinterface by opening the ip via browser. Here you can do all your settings. after pressing "save changes", all settings will be stored to the eeprom. The stored settings are loaded on every bootup. If you experience bugs, please let me know. ## All Icons: - Chrome - Discord - Edge - Empty (literally empty, all pixels off) - Firefox - Focus (for focussed windows) - Gaming - Master (for Master volume) - Mic - Misc - Mumble - Opera GX - Plex - Safari - Spotify - System Sounds (Windows Logo) - Teams - Teamspeak - Unassigned - World of Warcraft - YT-Music ================================================ FILE: NK2Tray_Display/NK2Tray_DisplayFW_V2/webServer.ino ================================================ /* ESP8266_ArtNetNode_DMX - webServer.ino Copyright (c) 2015, Matthew Tong https://github.com/mtongnz/ESP8266_ArtNetNode_DMX This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ */ ///////// Web Page & CSS - stored to flash memory //////////// const char css[] PROGMEM = "body {text-align:center;background:#333;}\n" "table {margin-left:auto;margin-right:auto;max-width:500px;width:100%;border-collapse:collapse;border:none;}\n" "th {height:40px;background:#666;color:white;font-weight:bold;border:none;}\n" ".mini_head {height:20px;background:#999;}\n" "td {padding:6px;border:1px solid #ccc;background:#eee;text-align:left;border:none; position: relative;}\n" ".left {width:120px;text-align:right;vertical-align:top;}\n" ".centre {text-align: center;}\n" "input:not(.button) {float: left;}\n" "input:not(.number):not(.radio):not(.button):not(.checkbox) {width: 100%;}\n" "#viewWifiPass {width:18px, height:18px; position: absolute; top: 7px; right: 10px; }\n" ".number {width:50px;}\n" ".button {width:150px;margin:10px;}\n" ".smallButton {width:80px;}\n" ".static_table {border-collapse:collapse;}\n" "p {padding:0px;margin:0px;font-size:14px; clear: both;}\n" "a {color:#00A;text-decoration:none;}\n" "a:hover {color:#00F;text-decoration:underline;}\n" ".bigLink {color: white;}\n" ".round-button {display:block; float: left; margin-right: 7px; width:14px; height:14px; font-size:14px; line-height:14px; border-radius: 50%; color:#ffffff; text-align:center; text-decoration:none; background: #5555ff; box-shadow: 0 0 2px #9999ff; font-weight:bold; font-family: 'Comic Sans', serif;}"; const char page_head[] PROGMEM = "NK2Tray Display\n" "\n" "" "\n" "\n"; const char home_top[] PROGMEM = "Home" "\n"; const char save_top[] PROGMEM = "Home"; const char save_tail[] PROGMEM = ""; const char form_tail[] PROGMEM = "\n" "\n" "\n" "\n" "