diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs index 10500499a..85e66818f 100644 --- a/Artemis/Artemis/Managers/LoopManager.cs +++ b/Artemis/Artemis/Managers/LoopManager.cs @@ -52,8 +52,8 @@ namespace Artemis.Managers //TODO DarthAffe 14.01.2017: A stop-condition and a real cleanup instead of just aborting might be better while (true) { -// try -// { + try + { long preUpdateTicks = DateTime.Now.Ticks; Render(); @@ -61,11 +61,11 @@ namespace Artemis.Managers int sleep = (int)(40f - ((DateTime.Now.Ticks - preUpdateTicks) / 10000f)); if (sleep > 0) Thread.Sleep(sleep); -// } -// catch (Exception e) -// { -// _logger.Warn(e, "Exception in render loop"); -// } + } + catch (Exception e) + { + _logger.Warn(e, "Exception in render loop"); + } } // ReSharper disable once FunctionNeverReturns } @@ -157,10 +157,11 @@ namespace Artemis.Managers var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList(); var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList(); var mousemats = _deviceManager.MousematProviders.Where(m => m.CanUse).ToList(); + var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any(); // Setup the frame for this tick - using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard)) + using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard, mice.Any(), headsets.Any(), generics.Any(), mousemats.Any())) { if (renderModule.IsInitialized) renderModule.Render(frame, keyboardOnly); @@ -202,45 +203,53 @@ namespace Artemis.Managers public class RenderFrame : IDisposable { - public RenderFrame(KeyboardProvider keyboard) - { + public RenderFrame(KeyboardProvider keyboard, bool renderMice, bool renderHeadsets, bool renderGenerics, bool renderMousemats) + { if (keyboard == null) return; KeyboardBitmap = keyboard.KeyboardBitmap(); - KeyboardBitmap.SetResolution(96, 96); - - MouseBitmap = new Bitmap(10, 10); - MouseBitmap.SetResolution(96, 96); - - HeadsetBitmap = new Bitmap(10, 10); - HeadsetBitmap.SetResolution(96, 96); - - GenericBitmap = new Bitmap(10, 10); - GenericBitmap.SetResolution(96, 96); - - MousematBitmap = new Bitmap(10, 10); - MousematBitmap.SetResolution(96, 96); - + KeyboardBitmap.SetResolution(96, 96); using (var g = Graphics.FromImage(KeyboardBitmap)) { g.Clear(Color.Black); } - using (var g = Graphics.FromImage(MouseBitmap)) + + if (renderMice) { - g.Clear(Color.Black); + MouseBitmap = new Bitmap(10, 10); + MouseBitmap.SetResolution(96, 96); + using (var g = Graphics.FromImage(MouseBitmap)) + { + g.Clear(Color.Black); + } } - using (var g = Graphics.FromImage(HeadsetBitmap)) + if (renderHeadsets) { - g.Clear(Color.Black); + HeadsetBitmap = new Bitmap(10, 10); + HeadsetBitmap.SetResolution(96, 96); + using (var g = Graphics.FromImage(HeadsetBitmap)) + { + g.Clear(Color.Black); + } } - using (var g = Graphics.FromImage(GenericBitmap)) + if (renderGenerics) { - g.Clear(Color.Black); + GenericBitmap = new Bitmap(10, 10); + GenericBitmap.SetResolution(96, 96); + using (var g = Graphics.FromImage(GenericBitmap)) + { + g.Clear(Color.Black); + } } - using (var g = Graphics.FromImage(MousematBitmap)) + if (renderMousemats) { - g.Clear(Color.Black); + MousematBitmap = new Bitmap(10, 10); + MousematBitmap.SetResolution(96, 96); + using (var g = Graphics.FromImage(MousematBitmap)) + { + g.Clear(Color.Black); + } } } diff --git a/Artemis/Artemis/Modules/Abstract/ModuleModel.cs b/Artemis/Artemis/Modules/Abstract/ModuleModel.cs index 9320684b6..299421c01 100644 --- a/Artemis/Artemis/Modules/Abstract/ModuleModel.cs +++ b/Artemis/Artemis/Modules/Abstract/ModuleModel.cs @@ -164,26 +164,38 @@ namespace Artemis.Modules.Abstract } // Render mice layer-by-layer var devRec = new Rect(0, 0, 10, 10); - using (var g = Graphics.FromImage(frame.MouseBitmap)) + if (frame.MouseBitmap != null) { - ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, preview); + using (var g = Graphics.FromImage(frame.MouseBitmap)) + { + ProfileModel?.DrawLayers(g, layers, DrawType.Mouse, DataModel, devRec, preview); + } } // Render headsets layer-by-layer - using (var g = Graphics.FromImage(frame.HeadsetBitmap)) + if (frame.HeadsetBitmap != null) { - ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, preview); + using (var g = Graphics.FromImage(frame.HeadsetBitmap)) + { + ProfileModel?.DrawLayers(g, layers, DrawType.Headset, DataModel, devRec, preview); + } } // Render generic devices layer-by-layer - using (var g = Graphics.FromImage(frame.GenericBitmap)) + if (frame.GenericBitmap != null) { - ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, preview); + using (var g = Graphics.FromImage(frame.GenericBitmap)) + { + ProfileModel?.DrawLayers(g, layers, DrawType.Generic, DataModel, devRec, preview); + } } // Render mousemats layer-by-layer - using (var g = Graphics.FromImage(frame.MousematBitmap)) + if (frame.MousematBitmap != null) { - ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, preview); + using (var g = Graphics.FromImage(frame.MousematBitmap)) + { + ProfileModel?.DrawLayers(g, layers, DrawType.Mousemat, DataModel, devRec, preview); + } } - + // Trace debugging if (DateTime.Now.AddSeconds(-2) <= _lastTrace || Logger == null) return; diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs index e0c0a5e60..ecb0e0873 100644 --- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs +++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs @@ -75,17 +75,23 @@ namespace Artemis.Modules.General.GeneralProfile private MMDevice _defaultRecording; private MMDevice _defaultPlayback; + private AudioMeterInformation _recordingInfo; + private AudioMeterInformation _playbackInfo; private void SetupAudio() { - _defaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); _defaultRecording = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); + _recordingInfo = AudioMeterInformation.FromDevice(_defaultRecording); + _defaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); + _playbackInfo = AudioMeterInformation.FromDevice(_defaultPlayback); } private void AudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e) { _defaultRecording = e.DefaultRecording; + _recordingInfo = AudioMeterInformation.FromDevice(_defaultRecording); _defaultPlayback = e.DefaultPlayback; + _playbackInfo = AudioMeterInformation.FromDevice(_defaultPlayback); } private void UpdateAudio(GeneralProfileDataModel dataModel) @@ -93,8 +99,8 @@ namespace Artemis.Modules.General.GeneralProfile // Update microphone, only bother with OverallPeak if (_defaultRecording != null) { - var recording = AudioMeterInformation.FromDevice(_defaultRecording); - dataModel.Audio.Recording.OverallPeak = recording.PeakValue; + + dataModel.Audio.Recording.OverallPeak = _recordingInfo.PeakValue; } if (_defaultPlayback == null) @@ -105,9 +111,8 @@ namespace Artemis.Modules.General.GeneralProfile // Update speakers, only do overall, left and right for now // TODO: When adding list support lets do all channels - var playback = AudioMeterInformation.FromDevice(_defaultPlayback); - var peakValues = playback.GetChannelsPeakValues(); - dataModel.Audio.Playback.OverallPeak = playback.PeakValue; + var peakValues = _playbackInfo.GetChannelsPeakValues(); + dataModel.Audio.Playback.OverallPeak = _playbackInfo.PeakValue; dataModel.Audio.Playback.LeftPeak = peakValues[0]; dataModel.Audio.Playback.LeftPeak = peakValues[1]; } diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs index f7e0a5c16..56da983ab 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioType.cs @@ -1,202 +1,202 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; -using System.Windows; -using System.Windows.Media; -using Artemis.Events; -using Artemis.Managers; -using Artemis.Modules.Abstract; -using Artemis.Profiles.Layers.Abstract; -using Artemis.Profiles.Layers.Animations; -using Artemis.Profiles.Layers.Interfaces; -using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Layers.Types.Audio.AudioCapturing; -using Artemis.Properties; -using Artemis.Utilities; -using Artemis.ViewModels; -using Artemis.ViewModels.Profiles; -using CSCore.CoreAudioAPI; - -namespace Artemis.Profiles.Layers.Types.Audio -{ - public class AudioType : ILayerType - { - private readonly AudioCaptureManager _audioCaptureManager; - private const GeometryCombineMode CombineMode = GeometryCombineMode.Union; - private AudioCapture _audioCapture; - private int _lines; - private LineSpectrum _lineSpectrum; - private List _lineValues; - private int _drawCount; - - public AudioType(AudioCaptureManager audioCaptureManager) - { - _audioCaptureManager = audioCaptureManager; - - // TODO: Setup according to settings - _audioCapture = _audioCaptureManager.GetAudioCapture(MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia)); - _audioCaptureManager.AudioDeviceChanged += OnAudioDeviceChanged; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Windows; +using System.Windows.Media; +using Artemis.Events; +using Artemis.Managers; +using Artemis.Modules.Abstract; +using Artemis.Profiles.Layers.Abstract; +using Artemis.Profiles.Layers.Animations; +using Artemis.Profiles.Layers.Interfaces; +using Artemis.Profiles.Layers.Models; +using Artemis.Profiles.Layers.Types.Audio.AudioCapturing; +using Artemis.Properties; +using Artemis.Utilities; +using Artemis.ViewModels; +using Artemis.ViewModels.Profiles; +using CSCore.CoreAudioAPI; + +namespace Artemis.Profiles.Layers.Types.Audio +{ + public class AudioType : ILayerType + { + private readonly AudioCaptureManager _audioCaptureManager; + private const GeometryCombineMode CombineMode = GeometryCombineMode.Union; + private AudioCapture _audioCapture; + private int _lines; + private LineSpectrum _lineSpectrum; + private List _lineValues; + private int _drawCount; + + public AudioType(AudioCaptureManager audioCaptureManager) + { + _audioCaptureManager = audioCaptureManager; + + // TODO: Setup according to settings + _audioCapture = _audioCaptureManager.GetAudioCapture(MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia)); + _audioCaptureManager.AudioDeviceChanged += OnAudioDeviceChanged; } - private void OnAudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e) - { - // TODO: Check if layer must use default - // TODO: Check recording type - _audioCapture = _audioCaptureManager.GetAudioCapture(e.DefaultPlayback); - _lines = 0; - } - - public string Name => "Keyboard - Audio visualization"; - public bool ShowInEdtor => true; - public DrawType DrawType => DrawType.Keyboard; - - public ImageSource DrawThumbnail(LayerModel layer) - { - var thumbnailRect = new Rect(0, 0, 18, 18); - var visual = new DrawingVisual(); - using (var c = visual.RenderOpen()) - { - c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.audio), thumbnailRect); - } - - var image = new DrawingImage(visual.Drawing); - return image; - } - - public void Draw(LayerModel layerModel, DrawingContext c) - { - _drawCount++; - if (_lineValues == null) - return; - - var parentX = layerModel.X; - var parentY = layerModel.Y; - var direction = ((AudioPropertiesModel) layerModel.Properties).Direction; - - // Create a geometry that will be formed by all the bars - Geometry barGeometry = new RectangleGeometry(); - - switch (direction) - { - case Direction.TopToBottom: - for (var index = 0; index < _lineValues.Count; index++) - { - var clipRect = new Rect((parentX + index)*4, parentY*4, 4, _lineValues[index]*4); - var barRect = new RectangleGeometry(clipRect); - barGeometry = Geometry.Combine(barGeometry, barRect, CombineMode, Transform.Identity); - } - break; - case Direction.BottomToTop: - for (var index = 0; index < _lineValues.Count; index++) - { - var clipRect = new Rect((parentX + index)*4, parentY*4, 4, _lineValues[index]*4); - clipRect.Y = clipRect.Y + layerModel.Height*4 - clipRect.Height; - var barRect = new RectangleGeometry(clipRect); - barGeometry = Geometry.Combine(barGeometry, barRect, CombineMode, Transform.Identity); - } - break; - case Direction.LeftToRight: - for (var index = 0; index < _lineValues.Count; index++) - { - var clipRect = new Rect((parentX + index)*4, parentY*4, 4, _lineValues[index]*4); - var barRect = new RectangleGeometry(clipRect); - barGeometry = Geometry.Combine(barGeometry, barRect, CombineMode, Transform.Identity); - } - break; - default: - for (var index = 0; index < _lineValues.Count; index++) - { - var clipRect = new Rect((parentX + index)*4, parentY*4, 4, _lineValues[index]*4); - var barRect = new RectangleGeometry(clipRect); - barGeometry = Geometry.Combine(barGeometry, barRect, CombineMode, Transform.Identity); - } - break; - } - - // Push the created geometry - c.PushClip(barGeometry); - BrushDraw(layerModel, c); - c.Pop(); - } - - public void Update(LayerModel layerModel, ModuleDataModel dataModel, bool isPreview = false) - { - layerModel.ApplyProperties(true); - _audioCapture.Pulse(); - - var direction = ((AudioPropertiesModel) layerModel.Properties).Direction; - - int currentLines; - double currentHeight; - if (direction == Direction.BottomToTop || direction == Direction.TopToBottom) - { - currentLines = (int) layerModel.Width; - currentHeight = layerModel.Height; - } - else - { - currentLines = (int) layerModel.Height; - currentHeight = layerModel.Width; - } - - if (_lines != currentLines || _lineSpectrum == null) - { - _lines = currentLines; - _lineSpectrum = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel); - } - - var newLineValues = _lineSpectrum?.GetLineValues(currentHeight); - if (newLineValues != null) - _lineValues = newLineValues; - } - - public void SetupProperties(LayerModel layerModel) - { - if (layerModel.Properties is AudioPropertiesModel) - return; - - layerModel.Properties = new AudioPropertiesModel(layerModel.Properties) - { - DeviceType = MmDeviceType.Ouput, - Device = "Default", - Direction = Direction.BottomToTop, - ScalingStrategy = ScalingStrategy.Decibel - }; - } - - public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel, - LayerPropertiesViewModel layerPropertiesViewModel) - { - if (layerPropertiesViewModel is AudioPropertiesViewModel) - return layerPropertiesViewModel; - return new AudioPropertiesViewModel(layerEditorViewModel); - } - - public void BrushDraw(LayerModel layerModel, DrawingContext c) - { - // If an animation is present, let it handle the drawing - if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation)) - { - layerModel.LayerAnimation.Draw(layerModel, c); - return; - } - - // Otherwise draw the rectangle with its layer.AppliedProperties dimensions and brush - var rect = layerModel.Properties.Contain - ? layerModel.LayerRect() - : new Rect(layerModel.Properties.X*4, layerModel.Properties.Y*4, - layerModel.Properties.Width*4, layerModel.Properties.Height*4); - - var clip = layerModel.LayerRect(); - - // Can't meddle with the original brush because it's frozen. - var brush = layerModel.Brush.Clone(); - brush.Opacity = layerModel.Opacity; - - c.PushClip(new RectangleGeometry(clip)); - c.DrawRectangle(brush, null, rect); - c.Pop(); - } - } + private void OnAudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e) + { + // TODO: Check if layer must use default + // TODO: Check recording type + _audioCapture = _audioCaptureManager.GetAudioCapture(e.DefaultPlayback); + _lines = 0; + } + + public string Name => "Keyboard - Audio visualization"; + public bool ShowInEdtor => true; + public DrawType DrawType => DrawType.Keyboard; + + public ImageSource DrawThumbnail(LayerModel layer) + { + var thumbnailRect = new Rect(0, 0, 18, 18); + var visual = new DrawingVisual(); + using (var c = visual.RenderOpen()) + { + c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.audio), thumbnailRect); + } + + var image = new DrawingImage(visual.Drawing); + return image; + } + + public void Draw(LayerModel layerModel, DrawingContext c) + { + _drawCount++; + if (_lineValues == null) + return; + + var parentX = layerModel.X; + var parentY = layerModel.Y; + var direction = ((AudioPropertiesModel) layerModel.Properties).Direction; + + // Create a geometry that will be formed by all the bars + GeometryGroup barGeometry = new GeometryGroup(); + + switch (direction) + { + case Direction.TopToBottom: + for (var index = 0; index < _lineValues.Count; index++) + { + var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4); + var barRect = new RectangleGeometry(clipRect); + barGeometry.Children.Add(barRect); + } + break; + case Direction.BottomToTop: + for (var index = 0; index < _lineValues.Count; index++) + { + var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4); + clipRect.Y = clipRect.Y + layerModel.Height * 4 - clipRect.Height; + var barRect = new RectangleGeometry(clipRect); + barGeometry.Children.Add(barRect); + } + break; + case Direction.LeftToRight: + for (var index = 0; index < _lineValues.Count; index++) + { + var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4); + var barRect = new RectangleGeometry(clipRect); + barGeometry.Children.Add(barRect); + } + break; + default: + for (var index = 0; index < _lineValues.Count; index++) + { + var clipRect = new Rect((parentX + index) * 4, parentY * 4, 4, _lineValues[index] * 4); + var barRect = new RectangleGeometry(clipRect); + barGeometry.Children.Add(barRect); + } + break; + } + + // Push the created geometry + c.PushClip(barGeometry); + BrushDraw(layerModel, c); + c.Pop(); + } + + public void Update(LayerModel layerModel, ModuleDataModel dataModel, bool isPreview = false) + { + layerModel.ApplyProperties(true); + _audioCapture.Pulse(); + + var direction = ((AudioPropertiesModel) layerModel.Properties).Direction; + + int currentLines; + double currentHeight; + if (direction == Direction.BottomToTop || direction == Direction.TopToBottom) + { + currentLines = (int) layerModel.Width; + currentHeight = layerModel.Height; + } + else + { + currentLines = (int) layerModel.Height; + currentHeight = layerModel.Width; + } + + if (_lines != currentLines || _lineSpectrum == null) + { + _lines = currentLines; + _lineSpectrum = _audioCapture.GetLineSpectrum(_lines, ScalingStrategy.Decibel); + } + + var newLineValues = _lineSpectrum?.GetLineValues(currentHeight); + if (newLineValues != null) + _lineValues = newLineValues; + } + + public void SetupProperties(LayerModel layerModel) + { + if (layerModel.Properties is AudioPropertiesModel) + return; + + layerModel.Properties = new AudioPropertiesModel(layerModel.Properties) + { + DeviceType = MmDeviceType.Ouput, + Device = "Default", + Direction = Direction.BottomToTop, + ScalingStrategy = ScalingStrategy.Decibel + }; + } + + public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel, + LayerPropertiesViewModel layerPropertiesViewModel) + { + if (layerPropertiesViewModel is AudioPropertiesViewModel) + return layerPropertiesViewModel; + return new AudioPropertiesViewModel(layerEditorViewModel); + } + + public void BrushDraw(LayerModel layerModel, DrawingContext c) + { + // If an animation is present, let it handle the drawing + if (layerModel.LayerAnimation != null && !(layerModel.LayerAnimation is NoneAnimation)) + { + layerModel.LayerAnimation.Draw(layerModel, c); + return; + } + + // Otherwise draw the rectangle with its layer.AppliedProperties dimensions and brush + var rect = layerModel.Properties.Contain + ? layerModel.LayerRect() + : new Rect(layerModel.Properties.X*4, layerModel.Properties.Y*4, + layerModel.Properties.Width*4, layerModel.Properties.Height*4); + + var clip = layerModel.LayerRect(); + + // Can't meddle with the original brush because it's frozen. + var brush = layerModel.Brush.Clone(); + brush.Opacity = layerModel.Opacity; + + c.PushClip(new RectangleGeometry(clip)); + c.DrawRectangle(brush, null, rect); + c.Pop(); + } + } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/DebugViewModel.cs b/Artemis/Artemis/ViewModels/DebugViewModel.cs index 43cb16d5b..6a27a94a8 100644 --- a/Artemis/Artemis/ViewModels/DebugViewModel.cs +++ b/Artemis/Artemis/ViewModels/DebugViewModel.cs @@ -6,20 +6,19 @@ using System.Windows.Media; using Artemis.Managers; using Artemis.Utilities; using Caliburn.Micro; -using Action = System.Action; namespace Artemis.ViewModels { public class DebugViewModel : Screen { private readonly DeviceManager _deviceManager; - - private DrawingImage _razerDisplay; + private DrawingImage _generic; + private DrawingImage _headset; private DrawingImage _keyboard; private DrawingImage _mouse; - private DrawingImage _headset; private DrawingImage _mousemat; - private DrawingImage _generic; + + private DrawingImage _razerDisplay; public DebugViewModel(DeviceManager deviceManager) { @@ -116,8 +115,8 @@ namespace Artemis.ViewModels { dc.PushClip(new RectangleGeometry(new Rect(0, 0, 22, 6))); for (var y = 0; y < 6; y++) - for (var x = 0; x < 22; x++) - dc.DrawRectangle(new SolidColorBrush(colors[y, x]), null, new Rect(x, y, 1, 1)); + for (var x = 0; x < 22; x++) + dc.DrawRectangle(new SolidColorBrush(colors[y, x]), null, new Rect(x, y, 1, 1)); } var drawnDisplay = new DrawingImage(visual.Drawing); drawnDisplay.Freeze(); @@ -137,10 +136,14 @@ namespace Artemis.ViewModels Keyboard = ImageUtilities.BitmapToDrawingImage(frame.KeyboardBitmap, rect); } - Mouse = ImageUtilities.BitmapToDrawingImage(frame.MouseBitmap, new Rect(0, 0, 10, 10)); - Headset = ImageUtilities.BitmapToDrawingImage(frame.HeadsetBitmap, new Rect(0, 0, 10, 10)); - Mousemat = ImageUtilities.BitmapToDrawingImage(frame.MousematBitmap, new Rect(0, 0, 10, 10)); - Generic = ImageUtilities.BitmapToDrawingImage(frame.GenericBitmap, new Rect(0, 0, 10, 10)); + if (frame.MouseBitmap != null) + Mouse = ImageUtilities.BitmapToDrawingImage(frame.MouseBitmap, new Rect(0, 0, 10, 10)); + if (frame.HeadsetBitmap != null) + Headset = ImageUtilities.BitmapToDrawingImage(frame.HeadsetBitmap, new Rect(0, 0, 10, 10)); + if (frame.MousematBitmap != null) + Mousemat = ImageUtilities.BitmapToDrawingImage(frame.MousematBitmap, new Rect(0, 0, 10, 10)); + if (frame.GenericBitmap != null) + Generic = ImageUtilities.BitmapToDrawingImage(frame.GenericBitmap, new Rect(0, 0, 10, 10)); } } } \ No newline at end of file