Fixed: send initial values when device connects
Implemented various TODO's
This commit is contained in:
parent
de27a6ccee
commit
cd1ab91f23
@ -6,7 +6,7 @@ namespace MassiveKnob.Plugin.CoreAudio.Base
|
||||
{
|
||||
public Guid? DeviceId { get; set; }
|
||||
|
||||
// TODO more options, like positioning and style
|
||||
// TODO (nice to have) more options, like positioning and style
|
||||
public bool OSD { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace MassiveKnob.Plugin.CoreAudio.Base
|
||||
namespace MassiveKnob.Plugin.CoreAudio.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BaseDeviceSettingsView.xaml
|
||||
/// </summary>
|
||||
public partial class BaseDeviceSettingsView : UserControl
|
||||
public partial class BaseDeviceSettingsView
|
||||
{
|
||||
public BaseDeviceSettingsView()
|
||||
{
|
||||
|
@ -6,8 +6,6 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MassiveKnob.Plugin.CoreAudio.GetMuted
|
||||
{
|
||||
// TODO send out initial muted state after proper initialization
|
||||
|
||||
public class DeviceGetMutedAction : IMassiveKnobAction
|
||||
{
|
||||
public Guid ActionId { get; } = new Guid("86646ca7-f472-4c5a-8d0f-7e5d2d162ab9");
|
||||
@ -54,6 +52,9 @@ namespace MassiveKnob.Plugin.CoreAudio.GetMuted
|
||||
|
||||
deviceChanged?.Dispose();
|
||||
deviceChanged = playbackDevice?.MuteChanged.Subscribe(MuteChanged);
|
||||
|
||||
if (playbackDevice != null)
|
||||
actionContext.SetDigitalOutput(settings.Inverted ? !playbackDevice.IsMuted : playbackDevice.IsMuted);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,8 +6,6 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace MassiveKnob.Plugin.CoreAudio.GetVolume
|
||||
{
|
||||
// TODO send out initial volume after proper initialization
|
||||
|
||||
public class DeviceGetVolumeAction : IMassiveKnobAction
|
||||
{
|
||||
public Guid ActionId { get; } = new Guid("6ebf91af-8240-4a75-9729-c6a1eb60dcba");
|
||||
@ -54,6 +52,9 @@ namespace MassiveKnob.Plugin.CoreAudio.GetVolume
|
||||
|
||||
deviceChanged?.Dispose();
|
||||
deviceChanged = playbackDevice?.VolumeChanged.Subscribe(VolumeChanged);
|
||||
|
||||
if (playbackDevice != null)
|
||||
actionContext.SetAnalogOutput((byte)playbackDevice.Volume);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
using MassiveKnob.Plugin.CoreAudio.SetMuted;
|
||||
|
||||
namespace MassiveKnob.Plugin.CoreAudio.GetVolume
|
||||
namespace MassiveKnob.Plugin.CoreAudio.GetVolume
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for DeviceGetVolumeActionSettingsView.xaml
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.RightsManagement;
|
||||
using System.Windows;
|
||||
using AudioSwitcher.AudioApi;
|
||||
|
||||
|
@ -14,34 +14,35 @@
|
||||
x:Key="SpeakerIcon"
|
||||
d:DataContext="{d:DesignInstance osd:OSDWindowViewModel}">
|
||||
<Canvas Width="256" Height="256">
|
||||
<Polygon Visibility="{Binding IsNotMutedVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Points=" 133.5,215.101 61.75,168 8.75,168 8.75,88 61.75,88 133.5,40.899 " Name="Speaker_1_" FillRule="NonZero" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round"/>
|
||||
<Path Visibility="{Binding VolumeLowVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="Low" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
|
||||
<Polygon Visibility="{Binding IsNotMutedVisibility}"
|
||||
Points=" 133.5,215.101 61.75,168 8.75,168 8.75,88 61.75,88 133.5,40.899 " Name="Speaker_1_" FillRule="NonZero" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round"/>
|
||||
<Path Visibility="{Binding VolumeLowVisibility}" Name="Low" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures=" M166.806 86c0 0 12.528 15.833 12.528 40.167s-12.528 43.823-12.528 43.823" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Visibility="{Binding VolumeMediumVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="Medium" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
|
||||
<Path Visibility="{Binding VolumeMediumVisibility}" Name="Medium" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures=" M188.479 57c0 0 21.183 26.769 21.183 67.91c0 41.141-21.183 74.089-21.183 74.089" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Visibility="{Binding VolumeHighVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="High" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
|
||||
<Path Visibility="{Binding VolumeHighVisibility}" Name="High" StrokeThickness="12" Stroke="#FFFFFFFF" StrokeMiterLimit="10" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures=" M216.737 35.517c0 0 27.944 35.316 27.944 89.593s-27.944 97.75-27.944 97.75" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
|
||||
<Path Visibility="{Binding IsMutedVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4561" Fill="#FFFFFFFF">
|
||||
<Path Visibility="{Binding IsMutedVisibility}" Name="path4561" Fill="#FFFFFFFF">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures="M160.503 221.101c-1.717 0-3.421-0.732-4.608-2.153L10.395 44.746c-2.125-2.543-1.785-6.327 0.759-8.451 c2.544-2.125 6.328-1.784 8.451 0.759l145.5 174.201c2.124 2.544 1.784 6.327-0.759 8.452 C163.224 220.644 161.859 221.101 160.503 221.101z" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Visibility="{Binding IsMutedVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4563" Fill="#FFFFFFFF">
|
||||
<Path Visibility="{Binding IsMutedVisibility}" Name="path4563" Fill="#FFFFFFFF">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures="M127.5 203.984l-62.458-41C64.064 162.342 62.92 162 61.75 162h-47V94h28.967L33.694 82H8.75c-3.313 0-6 2.687-6 6v80 c0 3.313 2.687 6 6 6h51.207l70.25 46.116c0.997 0.654 2.144 0.984 3.293 0.984c0.979 0 1.958-0.238 2.85-0.72 c1.94-1.048 3.15-3.075 3.15-5.28v-6.423l-12-14.367V203.984z" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
</Path>
|
||||
<Path Visibility="{Binding IsMutedVisibility}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path4565" Fill="#FFFFFFFF">
|
||||
<Path Visibility="{Binding IsMutedVisibility}" Name="path4565" Fill="#FFFFFFFF">
|
||||
<Path.Data>
|
||||
<PathGeometry Figures="M127.5 52.016v104.856l12 14.367V40.899c0-2.205-1.21-4.232-3.15-5.28c-1.939-1.047-4.299-0.947-6.143 0.264L63.19 79.877 l7.744 9.271L127.5 52.016z" FillRule="NonZero"/>
|
||||
</Path.Data>
|
||||
|
@ -4,6 +4,5 @@ namespace MassiveKnob.Plugin.CoreAudio.SetVolume
|
||||
{
|
||||
public class DeviceSetVolumeActionSettings : BaseDeviceSettings
|
||||
{
|
||||
// TODO OSD
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
@ -73,7 +73,7 @@ namespace MassiveKnob.Plugin.SerialDevice.Settings
|
||||
|
||||
serialPorts = SerialPort.GetPortNames();
|
||||
|
||||
// TODO subscribe to device notification to refresh list
|
||||
// TODO (must have - port from old source) subscribe to device notification to refresh list
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,10 @@ namespace MassiveKnob.Plugin
|
||||
/// <summary>
|
||||
/// Called right after this instance is created.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Do not perform anything but basic initialization until this method is called, as the action
|
||||
/// instance will be created temporarily at startup to verify it is correctly implemented!
|
||||
/// </remarks>
|
||||
/// <param name="context">Provides an interface to the Massive Knob settings and device. Can be stored until the action instance is disposed.</param>
|
||||
void Initialize(IMassiveKnobActionContext context);
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable UnusedMember.Global - public API
|
||||
|
||||
namespace MassiveKnob.Plugin
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EOF/@EntryIndexedValue">EOF</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MIN/@EntryIndexedValue">MIN</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OSD/@EntryIndexedValue">OSD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SOF/@EntryIndexedValue">SOF</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
|
||||
|
@ -5,7 +5,6 @@ using System.Reactive.Subjects;
|
||||
using MassiveKnob.Helpers;
|
||||
using MassiveKnob.Plugin;
|
||||
using MassiveKnob.Settings;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serilog.Extensions.Logging;
|
||||
using ILogger = Serilog.ILogger;
|
||||
@ -30,6 +29,9 @@ namespace MassiveKnob.Model
|
||||
private readonly List<ActionMapping> analogOutputs = new List<ActionMapping>();
|
||||
private readonly List<ActionMapping> digitalOutputs = new List<ActionMapping>();
|
||||
|
||||
private readonly Dictionary<int, byte> analogOutputValues = new Dictionary<int, byte>();
|
||||
private readonly Dictionary<int, bool> digitalOutputValues = new Dictionary<int, bool>();
|
||||
|
||||
|
||||
public MassiveKnobDeviceInfo ActiveDevice
|
||||
{
|
||||
@ -58,17 +60,22 @@ namespace MassiveKnob.Model
|
||||
{
|
||||
activeDevice?.Instance?.Dispose();
|
||||
|
||||
void DisposeMappings(IEnumerable<ActionMapping> mappings)
|
||||
void DisposeMappings(ICollection<ActionMapping> mappings)
|
||||
{
|
||||
foreach (var mapping in mappings)
|
||||
mapping?.ActionInfo.Instance?.Dispose();
|
||||
|
||||
mappings.Clear();
|
||||
}
|
||||
|
||||
|
||||
DisposeMappings(analogInputs);
|
||||
DisposeMappings(digitalInputs);
|
||||
DisposeMappings(analogOutputs);
|
||||
DisposeMappings(digitalOutputs);
|
||||
lock (settingsLock)
|
||||
{
|
||||
DisposeMappings(analogInputs);
|
||||
DisposeMappings(digitalInputs);
|
||||
DisposeMappings(analogOutputs);
|
||||
DisposeMappings(digitalOutputs);
|
||||
}
|
||||
|
||||
activeDeviceInfoSubject?.Dispose();
|
||||
}
|
||||
@ -101,24 +108,29 @@ namespace MassiveKnob.Model
|
||||
|
||||
public MassiveKnobActionInfo GetAction(MassiveKnobActionType actionType, int index)
|
||||
{
|
||||
var list = GetActionMappingList(actionType);
|
||||
return index >= list.Count ? null : list[index]?.ActionInfo;
|
||||
lock (settingsLock)
|
||||
{
|
||||
var list = GetActionMappingList(actionType);
|
||||
return index >= list.Count ? null : list[index]?.ActionInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MassiveKnobActionInfo SetAction(MassiveKnobActionType actionType, int index, IMassiveKnobAction action)
|
||||
{
|
||||
var list = GetActionMappingList(actionType);
|
||||
if (index >= list.Count)
|
||||
return null;
|
||||
|
||||
if (list[index]?.ActionInfo.Info == action)
|
||||
return list[index].ActionInfo;
|
||||
|
||||
list[index]?.ActionInfo.Instance?.Dispose();
|
||||
List<ActionMapping> list;
|
||||
|
||||
lock (settingsLock)
|
||||
{
|
||||
list = GetActionMappingList(actionType);
|
||||
if (index >= list.Count)
|
||||
return null;
|
||||
|
||||
if (list[index]?.ActionInfo.Info == action)
|
||||
return list[index].ActionInfo;
|
||||
|
||||
list[index]?.ActionInfo.Instance?.Dispose();
|
||||
|
||||
var settingsList = GetActionSettingsList(actionType);
|
||||
while (index >= settingsList.Count)
|
||||
settingsList.Add(null);
|
||||
@ -139,7 +151,11 @@ namespace MassiveKnob.Model
|
||||
initializeAfterRegistration = () => actionInstance.Initialize(actionContext);
|
||||
});
|
||||
|
||||
list[index] = mapping;
|
||||
lock (settingsLock)
|
||||
{
|
||||
list[index] = mapping;
|
||||
}
|
||||
|
||||
initializeAfterRegistration?.Invoke();
|
||||
|
||||
return mapping?.ActionInfo;
|
||||
@ -225,15 +241,15 @@ namespace MassiveKnob.Model
|
||||
|
||||
protected T GetActionSettings<T>(IMassiveKnobActionContext context, IMassiveKnobAction action, int index) where T : class, new()
|
||||
{
|
||||
var list = GetActionMappingList(action.ActionType);
|
||||
if (index >= list.Count)
|
||||
return new T();
|
||||
|
||||
if (list[index]?.Context != context)
|
||||
throw new InvalidOperationException("Caller must be the active action to retrieve the settings");
|
||||
|
||||
lock (settingsLock)
|
||||
{
|
||||
var list = GetActionMappingList(action.ActionType);
|
||||
if (index >= list.Count)
|
||||
return new T();
|
||||
|
||||
if (list[index]?.Context != context)
|
||||
throw new InvalidOperationException("Caller must be the active action to retrieve the settings");
|
||||
|
||||
var settingsList = GetActionSettingsList(action.ActionType);
|
||||
if (index >= settingsList.Count)
|
||||
return new T();
|
||||
@ -245,15 +261,15 @@ namespace MassiveKnob.Model
|
||||
|
||||
protected void SetActionSettings<T>(IMassiveKnobActionContext context, IMassiveKnobAction action, int index, T actionSettings) where T : class, new()
|
||||
{
|
||||
var list = GetActionMappingList(action.ActionType);
|
||||
if (index >= list.Count)
|
||||
return;
|
||||
|
||||
if (list[index]?.Context != context)
|
||||
throw new InvalidOperationException("Caller must be the active action to retrieve the settings");
|
||||
|
||||
lock (settingsLock)
|
||||
{
|
||||
var list = GetActionMappingList(action.ActionType);
|
||||
if (index >= list.Count)
|
||||
return;
|
||||
|
||||
if (list[index]?.Context != context)
|
||||
throw new InvalidOperationException("Caller must be the active action to retrieve the settings");
|
||||
|
||||
var settingsList = GetActionSettingsList(action.ActionType);
|
||||
|
||||
while (index >= settingsList.Count)
|
||||
@ -272,19 +288,29 @@ namespace MassiveKnob.Model
|
||||
}
|
||||
|
||||
|
||||
// TODO store output values for when the device connects and should receive initial values
|
||||
|
||||
protected void AnalogChanged(IMassiveKnobDeviceContext context, int analogInputIndex, byte value)
|
||||
{
|
||||
if (context != activeDeviceContext)
|
||||
return;
|
||||
|
||||
var mapping = GetActionMappingList(MassiveKnobActionType.InputAnalog);
|
||||
if (mapping == null || analogInputIndex >= mapping.Count || mapping[analogInputIndex] == null)
|
||||
return;
|
||||
IMassiveKnobAnalogAction analogAction;
|
||||
|
||||
if (mapping[analogInputIndex].ActionInfo.Instance is IMassiveKnobAnalogAction analogAction)
|
||||
analogAction.AnalogChanged(value);
|
||||
lock (settingsLock)
|
||||
{
|
||||
if (analogOutputValues.TryGetValue(analogInputIndex, out var currentValue) && currentValue == value)
|
||||
return;
|
||||
|
||||
analogOutputValues[analogInputIndex] = value;
|
||||
|
||||
var mapping = GetActionMappingList(MassiveKnobActionType.InputAnalog);
|
||||
if (mapping == null || analogInputIndex >= mapping.Count || mapping[analogInputIndex] == null)
|
||||
return;
|
||||
|
||||
|
||||
analogAction = mapping[analogInputIndex].ActionInfo.Instance as IMassiveKnobAnalogAction;
|
||||
}
|
||||
|
||||
analogAction?.AnalogChanged(value);
|
||||
}
|
||||
|
||||
|
||||
@ -293,44 +319,70 @@ namespace MassiveKnob.Model
|
||||
if (context != activeDeviceContext)
|
||||
return;
|
||||
|
||||
var mapping = GetActionMappingList(MassiveKnobActionType.InputDigital);
|
||||
if (mapping == null || digitalInputIndex >= mapping.Count || mapping[digitalInputIndex] == null)
|
||||
return;
|
||||
IMassiveKnobDigitalAction digitalAction;
|
||||
|
||||
if (mapping[digitalInputIndex].ActionInfo.Instance is IMassiveKnobDigitalAction digitalAction)
|
||||
digitalAction.DigitalChanged(on);
|
||||
lock (settingsLock)
|
||||
{
|
||||
if (digitalOutputValues.TryGetValue(digitalInputIndex, out var currentValue) && currentValue == on)
|
||||
return;
|
||||
|
||||
digitalOutputValues[digitalInputIndex] = on;
|
||||
|
||||
|
||||
var mapping = GetActionMappingList(MassiveKnobActionType.InputDigital);
|
||||
if (mapping == null || digitalInputIndex >= mapping.Count || mapping[digitalInputIndex] == null)
|
||||
return;
|
||||
|
||||
digitalAction = mapping[digitalInputIndex].ActionInfo.Instance as IMassiveKnobDigitalAction;
|
||||
}
|
||||
|
||||
digitalAction?.DigitalChanged(on);
|
||||
}
|
||||
|
||||
|
||||
public void SetAnalogOutput(IMassiveKnobActionContext context, IMassiveKnobAction action, int index, byte value)
|
||||
public void SetAnalogOutput(IMassiveKnobActionContext context, int index, byte value)
|
||||
{
|
||||
if (activeDevice == null)
|
||||
return;
|
||||
|
||||
var list = GetActionMappingList(action.ActionType);
|
||||
if (index >= list.Count)
|
||||
return;
|
||||
IMassiveKnobDeviceInstance deviceInstance;
|
||||
|
||||
if (list[index]?.Context != context)
|
||||
return;
|
||||
lock (settingsLock)
|
||||
{
|
||||
var list = GetActionMappingList(MassiveKnobActionType.OutputAnalog);
|
||||
if (index >= list.Count)
|
||||
return;
|
||||
|
||||
activeDevice.Instance.SetAnalogOutput(index, value);
|
||||
if (context != null && list[index]?.Context != context)
|
||||
return;
|
||||
|
||||
deviceInstance = activeDevice.Instance;
|
||||
}
|
||||
|
||||
deviceInstance.SetAnalogOutput(index, value);
|
||||
}
|
||||
|
||||
|
||||
public void SetDigitalOutput(IMassiveKnobActionContext context, IMassiveKnobAction action, int index, bool on)
|
||||
public void SetDigitalOutput(IMassiveKnobActionContext context, int index, bool on)
|
||||
{
|
||||
if (activeDevice == null)
|
||||
return;
|
||||
|
||||
var list = GetActionMappingList(action.ActionType);
|
||||
if (index >= list.Count)
|
||||
return;
|
||||
IMassiveKnobDeviceInstance deviceInstance;
|
||||
|
||||
if (list[index]?.Context != context)
|
||||
return;
|
||||
lock (settingsLock)
|
||||
{
|
||||
var list = GetActionMappingList(MassiveKnobActionType.OutputDigital);
|
||||
if (index >= list.Count)
|
||||
return;
|
||||
|
||||
activeDevice.Instance.SetDigitalOutput(index, on);
|
||||
if (context != null && list[index]?.Context != context)
|
||||
return;
|
||||
|
||||
deviceInstance = activeDevice.Instance;
|
||||
}
|
||||
|
||||
deviceInstance.SetDigitalOutput(index, on);
|
||||
}
|
||||
|
||||
|
||||
@ -424,6 +476,14 @@ namespace MassiveKnob.Model
|
||||
ActiveDevice.Info,
|
||||
ActiveDevice.Instance,
|
||||
specs);
|
||||
|
||||
|
||||
// Send out all cached values to initialize the device's outputs
|
||||
foreach (var pair in analogOutputValues.Where(pair => pair.Key < specs.AnalogOutputCount))
|
||||
SetAnalogOutput(null, pair.Key, pair.Value);
|
||||
|
||||
foreach (var pair in digitalOutputValues.Where(pair => pair.Key < specs.DigitalOutputCount))
|
||||
SetDigitalOutput(null, pair.Key, pair.Value);
|
||||
}
|
||||
|
||||
|
||||
@ -520,14 +580,13 @@ namespace MassiveKnob.Model
|
||||
|
||||
public void Connecting()
|
||||
{
|
||||
// TODO update status ?
|
||||
// TODO (should have) update status ?
|
||||
}
|
||||
|
||||
|
||||
public void Connected(DeviceSpecs specs)
|
||||
{
|
||||
// TODO update status ?
|
||||
// TODO send out initial values for outputs
|
||||
// TODO (should have) update status ?
|
||||
|
||||
owner.UpdateActiveDeviceSpecs(this, specs);
|
||||
}
|
||||
@ -535,7 +594,7 @@ namespace MassiveKnob.Model
|
||||
|
||||
public void Disconnected()
|
||||
{
|
||||
// TODO update status ?
|
||||
// TODO (should have) update status ?
|
||||
}
|
||||
|
||||
|
||||
@ -581,13 +640,13 @@ namespace MassiveKnob.Model
|
||||
|
||||
public void SetAnalogOutput(byte value)
|
||||
{
|
||||
owner.SetAnalogOutput(this, action, index, value);
|
||||
owner.SetAnalogOutput(this, index, value);
|
||||
}
|
||||
|
||||
|
||||
public void SetDigitalOutput(bool on)
|
||||
{
|
||||
owner.SetDigitalOutput(this, action, index, on);
|
||||
owner.SetDigitalOutput(this, index, on);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MassiveKnob.Plugin;
|
||||
using Serilog;
|
||||
using Serilog.Extensions.Logging;
|
||||
|
||||
namespace MassiveKnob.Model
|
||||
{
|
||||
@ -29,9 +31,16 @@ namespace MassiveKnob.Model
|
||||
|
||||
public class PluginManager : IPluginManager
|
||||
{
|
||||
private readonly ILogger logger;
|
||||
private readonly List<IMassiveKnobPlugin> plugins = new List<IMassiveKnobPlugin>();
|
||||
|
||||
|
||||
public PluginManager(ILogger logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<IMassiveKnobDevicePlugin> GetDevicePlugins()
|
||||
{
|
||||
return plugins.Where(p => p is IMassiveKnobDevicePlugin).Cast<IMassiveKnobDevicePlugin>();
|
||||
@ -101,7 +110,7 @@ namespace MassiveKnob.Model
|
||||
}
|
||||
|
||||
|
||||
private static void ValidateRegistration(string filename, IMassiveKnobPlugin plugin, RegisteredIds registeredIds)
|
||||
private void ValidateRegistration(string filename, IMassiveKnobPlugin plugin, RegisteredIds registeredIds)
|
||||
{
|
||||
// Make sure all GUIDs are actually unique and someone has not copy/pasted a plugin without
|
||||
// modifying the values. This way we can safely make that assumption in other code.
|
||||
@ -133,13 +142,42 @@ namespace MassiveKnob.Model
|
||||
throw new MassiveKnobPluginIdConflictException(action.ActionId, conflictingActionFilename, filename);
|
||||
|
||||
registeredIds.ActionById.Add(action.ActionId, filename);
|
||||
|
||||
// TODO check ActionType vs. implemented interfaces
|
||||
ValidateActionType(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ValidateActionType(IMassiveKnobAction action)
|
||||
{
|
||||
var instance = action.Create(new SerilogLoggerProvider(logger).CreateLogger(null));
|
||||
if (instance == null)
|
||||
throw new NullReferenceException("Create method must not return null");
|
||||
|
||||
switch (action.ActionType)
|
||||
{
|
||||
case MassiveKnobActionType.InputAnalog:
|
||||
if (!(instance is IMassiveKnobAnalogAction))
|
||||
throw new InvalidCastException("InputAnalog action must implement IMassiveKnobAnalogAction");
|
||||
|
||||
break;
|
||||
|
||||
case MassiveKnobActionType.InputDigital:
|
||||
if (!(instance is IMassiveKnobDigitalAction))
|
||||
throw new InvalidCastException("InputDigital action must implement IMassiveKnobDigitalAction");
|
||||
|
||||
break;
|
||||
|
||||
case MassiveKnobActionType.OutputAnalog:
|
||||
case MassiveKnobActionType.OutputDigital:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(action.ActionType), action.ActionType, @"Unsupported action type: " + (int)action.ActionType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class RegisteredIds
|
||||
{
|
||||
public readonly Dictionary<Guid, string> PluginById = new Dictionary<Guid, string>();
|
||||
|
@ -21,7 +21,7 @@ namespace MassiveKnob
|
||||
[STAThread]
|
||||
public static int Main()
|
||||
{
|
||||
// TODO make configurable
|
||||
// TODO (should have) make configurable
|
||||
var loggingLevelSwitch = new LoggingLevelSwitch();
|
||||
//var loggingLevelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
|
||||
|
||||
@ -35,7 +35,7 @@ namespace MassiveKnob
|
||||
.CreateLogger();
|
||||
|
||||
|
||||
var pluginManager = new PluginManager();
|
||||
var pluginManager = new PluginManager(logger);
|
||||
|
||||
var messages = new StringBuilder();
|
||||
pluginManager.Load((exception, filename) =>
|
||||
|
@ -10,7 +10,6 @@ namespace MassiveKnob.ViewModel
|
||||
{
|
||||
public class InputOutputViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly SettingsViewModel settingsViewModel;
|
||||
private readonly IMassiveKnobOrchestrator orchestrator;
|
||||
private readonly MassiveKnobActionType actionType;
|
||||
private readonly int index;
|
||||
@ -61,7 +60,6 @@ namespace MassiveKnob.ViewModel
|
||||
|
||||
public InputOutputViewModel(SettingsViewModel settingsViewModel, IMassiveKnobOrchestrator orchestrator, MassiveKnobActionType actionType, int index)
|
||||
{
|
||||
this.settingsViewModel = settingsViewModel;
|
||||
this.orchestrator = orchestrator;
|
||||
this.actionType = actionType;
|
||||
this.index = index;
|
||||
|
@ -10,7 +10,7 @@ using MassiveKnob.Plugin;
|
||||
|
||||
namespace MassiveKnob.ViewModel
|
||||
{
|
||||
// TODO better design-time version
|
||||
// TODO (nice to have) better design-time version
|
||||
public class SettingsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly IMassiveKnobOrchestrator orchestrator;
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 223cfafaf40e0e26e7660860ddfd755cb671f81b
|
||||
Subproject commit 6db7da6234713a50a2c278c00bcd710249738e5e
|
Loading…
Reference in New Issue
Block a user