diff --git a/InstallForge/2021_1_InstallProject.ifp b/InstallForge/2021_1_InstallProject.ifp
new file mode 100644
index 0000000..2d5a883
Binary files /dev/null and b/InstallForge/2021_1_InstallProject.ifp differ
diff --git a/McIntyreAFC/McIntyreAFC.csproj b/McIntyreAFC/McIntyreAFC.csproj
index c579dd6..fe614c3 100644
--- a/McIntyreAFC/McIntyreAFC.csproj
+++ b/McIntyreAFC/McIntyreAFC.csproj
@@ -1,23 +1,28 @@
-
- netcoreapp3.1
-
+
+ netcoreapp3.1
+
-
- ..\ProtocolMasterWPF\bin\Debug\netcoreapp3.1\Extensions\
- false
- 5
-
+
+ ..\ProtocolMasterWPF\bin\Debug\netcoreapp3.1\Extensions\
+ false
+ 5
+
-
-
-
+
+ ..\ProtocolMasterWPF\bin\Release\netcoreapp3.1\Extensions\
+ false
+
-
-
- false
-
-
+
+
+
+
+
+
+ false
+
+
diff --git a/ProtocolMasterCore/Protocol/Driver/DriverMeta.cs b/ProtocolMasterCore/Protocol/Driver/DriverMeta.cs
index 9789f38..7f5c356 100644
--- a/ProtocolMasterCore/Protocol/Driver/DriverMeta.cs
+++ b/ProtocolMasterCore/Protocol/Driver/DriverMeta.cs
@@ -19,6 +19,9 @@ public DriverMeta(string name, string version, params string[] eventNames) : bas
this.Version = version;
this.HandlerLabels = eventNames;
}
+ public DriverMeta()
+ {
+ }
public DriverMeta(IDictionary inputs)
{
@@ -34,7 +37,7 @@ public override string ToString()
public bool Equals([AllowNull] IExtensionMeta other)
{
- return this.Name == other.Name && this.Version == other.Version;
+ return this.Name == other.Name && this.Version == other.Version;
}
}
}
diff --git a/ProtocolMasterCore/Protocol/ExtensionManager.cs b/ProtocolMasterCore/Protocol/ExtensionManager.cs
index 5110ac1..b7f498d 100644
--- a/ProtocolMasterCore/Protocol/ExtensionManager.cs
+++ b/ProtocolMasterCore/Protocol/ExtensionManager.cs
@@ -50,13 +50,13 @@ public IExtensionMeta Selected
{
foreach (ExportFactory i in Extensions)
{
- if ((IExtensionMeta)i.Metadata == value)
+ if (i.Metadata.Equals(value))
{
extensionFactory = i;
return;
}
}
- throw new Exception($"No extension of type {typeof(E)} of with metadata {value} is loaded");
+ throw new ArgumentException($"No extension of type {typeof(E)} of with metadata {value} is loaded");
}
}
public IEnumerable Options
diff --git a/ProtocolMasterCore/Protocol/IExtensionMeta.cs b/ProtocolMasterCore/Protocol/IExtensionMeta.cs
index 1b7c824..7bd48c6 100644
--- a/ProtocolMasterCore/Protocol/IExtensionMeta.cs
+++ b/ProtocolMasterCore/Protocol/IExtensionMeta.cs
@@ -1,4 +1,7 @@
using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Xml.Serialization;
namespace ProtocolMasterCore.Protocol
{
@@ -7,4 +10,5 @@ public interface IExtensionMeta : IEquatable
string Name { get; }
string Version { get; }
}
+
}
diff --git a/ProtocolMasterWPF/Helpers/NotNullToBoolConverter.cs b/ProtocolMasterWPF/Helpers/NotNullToBoolConverter.cs
index 2708dcd..0766dc8 100644
--- a/ProtocolMasterWPF/Helpers/NotNullToBoolConverter.cs
+++ b/ProtocolMasterWPF/Helpers/NotNullToBoolConverter.cs
@@ -13,7 +13,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
- return value != null;
+ throw new NotSupportedException();
}
}
}
diff --git a/ProtocolMasterWPF/Model/Camera.cs b/ProtocolMasterWPF/Model/Camera.cs
index f8341bf..184bd5a 100644
--- a/ProtocolMasterWPF/Model/Camera.cs
+++ b/ProtocolMasterWPF/Model/Camera.cs
@@ -30,18 +30,38 @@ private async void InitVideoStore()
{
videoStore = await StorageFolder.GetFolderFromPathAsync(storagePath);
}
- public async void InitializeCap(DeviceInformation videoDevice, DeviceInformation audioDevice)
+ public void InitializeCap(DeviceInformation videoDevice, DeviceInformation audioDevice)
{
- try
+ if(videoDevice == null)
+ Log.Error($"Video Device null");
+ if (audioDevice == null)
{
- await MediaCap.InitializeAsync(new MediaCaptureInitializationSettings() {
- VideoDeviceId = videoDevice.Id,
- AudioDeviceId = audioDevice.Id
- });
+ try
+ {
+ MediaCap.InitializeAsync(new MediaCaptureInitializationSettings()
+ {
+ VideoDeviceId = videoDevice.Id
+ }).AsTask().Wait();
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ Log.Error($"The app was denied access to the camera: {ex}");
+ }
}
- catch (UnauthorizedAccessException ex)
+ else
{
- Log.Error($"The app was denied access to the camera:\t{ex}");
+ try
+ {
+ MediaCap.InitializeAsync(new MediaCaptureInitializationSettings()
+ {
+ VideoDeviceId = videoDevice.Id,
+ AudioDeviceId = audioDevice.Id
+ }).AsTask().Wait();
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ Log.Error($"The app was denied access to the camera: {ex}");
+ }
}
}
public async void StartPreview()
diff --git a/ProtocolMasterWPF/Model/CameraContainer.cs b/ProtocolMasterWPF/Model/CameraContainer.cs
index e69229b..a51e9c5 100644
--- a/ProtocolMasterWPF/Model/CameraContainer.cs
+++ b/ProtocolMasterWPF/Model/CameraContainer.cs
@@ -1,4 +1,6 @@
-using System;
+using ProtocolMasterCore.Utility;
+using ProtocolMasterWPF.Properties;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -11,53 +13,79 @@ internal class CameraContainer : Observable
{
public CameraContainer()
{
- RefreshDevices();
- _videoDevice = VideoDevices.First();
- _audioDevice = AudioDevices.First();
+ InitDefaultDevices();
ResetCam();
}
- public Camera Cam { get => _cam; private set { _cam = value; NotifyProperty(); } }
- private Camera _cam;
- public DeviceInformation VideoDevice { get => _videoDevice; set { _videoDevice = value; NotifyProperty(); ResetCam(); } }
- private DeviceInformation _videoDevice;
- public DeviceInformation AudioDevice { get => _audioDevice; set { _audioDevice = value; NotifyProperty(); ResetCam(); } }
- private DeviceInformation _audioDevice;
- public void StartRecord() => Cam.StartRecord();
- public void StopRecord() => Cam.StopRecord();
- private DeviceInformationCollection _videoDevices;
- public DeviceInformationCollection VideoDevices
+ public Camera Cam
{
- get => _videoDevices;
- set
+ get => _cam;
+ private set
{
- _videoDevices = value;
+ _cam = value;
NotifyProperty();
}
}
- public void RefreshDevices()
+ private Camera _cam;
+ public DeviceInformation VideoDevice
{
- Task task = DeviceInformation.FindAllAsync(DeviceClass.VideoCapture).AsTask();
- task.Wait();
- VideoDevices = task.Result;
- task.Dispose();
-
- task = DeviceInformation.FindAllAsync(DeviceClass.AudioCapture).AsTask();
- task.Wait();
- AudioDevices = task.Result;
+ get => _videoDevice;
+ set
+ {
+ _videoDevice = value;
+ NotifyProperty();
+ ResetCam();
+ if (value.Id != Settings.Default.CameraID)
+ {
+ Settings.Default.CameraID = value.Id;
+ Settings.Default.Save();
+ }
+ }
}
- private DeviceInformationCollection _audioDevices;
- public DeviceInformationCollection AudioDevices
+ private DeviceInformation _videoDevice;
+ public DeviceInformation AudioDevice
{
- get => _audioDevices;
+ get => _audioDevice;
set
{
- _audioDevices = value;
+ _audioDevice = value;
NotifyProperty();
+ ResetCam();
+ if(value.Id != Settings.Default.MicrophoneID)
+ {
+ Settings.Default.MicrophoneID = value.Id;
+ Settings.Default.Save();
+ }
}
}
+ private DeviceInformation _audioDevice;
+ public void StartRecord() => Cam.StartRecord();
+ public void StopRecord() => Cam.StopRecord();
+
private void ResetCam()
{
Cam = new Camera(VideoDevice, AudioDevice);
}
+
+ public void InitDefaultDevices()
+ {
+ try
+ {
+ _videoDevice = MediaDevices.Instance.VideoDeviceByID(Settings.Default.CameraID);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"Default Camera could not be seleted, exception: {e}");
+ VideoDevice = MediaDevices.Instance.VideoDevices.First();
+ }
+ try
+ {
+ _audioDevice = MediaDevices.Instance.AudioDeviceByID(Settings.Default.MicrophoneID);
+ }
+ catch (Exception e)
+ {
+ Log.Error($"Default Microphone could not be seleted, exception: {e}");
+ AudioDevice = MediaDevices.Instance.AudioDevices.First();
+ }
+ }
}
}
diff --git a/ProtocolMasterWPF/Model/ExtensionMetaSetting.cs b/ProtocolMasterWPF/Model/ExtensionMetaSetting.cs
new file mode 100644
index 0000000..1d6318d
--- /dev/null
+++ b/ProtocolMasterWPF/Model/ExtensionMetaSetting.cs
@@ -0,0 +1,27 @@
+using ProtocolMasterCore.Protocol;
+using ProtocolMasterCore.Protocol.Driver;
+using ProtocolMasterCore.Protocol.Interpreter;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+
+namespace ProtocolMasterWPF.Model
+{
+ [Serializable]
+ public sealed class ExtensionMetaSetting : IExtensionMeta
+ {
+ public string Name { get; set; }
+ public string Version { get; set; }
+ public ExtensionMetaSetting() { }
+ public ExtensionMetaSetting(IExtensionMeta from)
+ {
+ Name = from.Name; Version = from.Version;
+ }
+ public bool Equals([AllowNull] IExtensionMeta other)
+ {
+ return this.Name == other.Name && this.Version == other.Version;
+ }
+ }
+}
diff --git a/ProtocolMasterWPF/Model/MediaDevices.cs b/ProtocolMasterWPF/Model/MediaDevices.cs
new file mode 100644
index 0000000..de01729
--- /dev/null
+++ b/ProtocolMasterWPF/Model/MediaDevices.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.Devices.Enumeration;
+
+namespace ProtocolMasterWPF.Model
+{
+ internal class MediaDevices : Observable
+ {
+ private static MediaDevices instance = new MediaDevices();
+ public static MediaDevices Instance { get => instance; }
+ static MediaDevices() { }
+ private MediaDevices()
+ {
+ RefreshDevices();
+ }
+ private DeviceInformationCollection _videoDevices;
+
+ public DeviceInformationCollection VideoDevices
+ {
+ get => _videoDevices;
+ set
+ {
+ _videoDevices = value;
+ NotifyProperty();
+ }
+ }
+ public void RefreshDevices()
+ {
+ Task task = DeviceInformation.FindAllAsync(DeviceClass.VideoCapture).AsTask();
+ task.Wait();
+ VideoDevices = task.Result;
+ task.Dispose();
+
+ task = DeviceInformation.FindAllAsync(DeviceClass.AudioCapture).AsTask();
+ task.Wait();
+ AudioDevices = task.Result;
+ }
+ private DeviceInformationCollection _audioDevices;
+ public DeviceInformationCollection AudioDevices
+ {
+ get => _audioDevices;
+ set
+ {
+ _audioDevices = value;
+ NotifyProperty();
+ }
+ }
+ public DeviceInformation AudioDeviceByID(string id)
+ {
+ return AudioDevices.First(a => a.Id == id);
+ }
+ public DeviceInformation VideoDeviceByID(string id)
+ {
+ return VideoDevices.First(a => a.Id == id);
+ }
+ }
+}
diff --git a/ProtocolMasterWPF/Model/Session.cs b/ProtocolMasterWPF/Model/Session.cs
index 610562e..3e26241 100644
--- a/ProtocolMasterWPF/Model/Session.cs
+++ b/ProtocolMasterWPF/Model/Session.cs
@@ -1,6 +1,7 @@
using ProtocolMasterCore.Protocol;
using ProtocolMasterCore.Utility;
using ProtocolMasterWPF.Helpers;
+using ProtocolMasterWPF.Properties;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -29,10 +30,38 @@ internal class Session : Observable
CancellationToken CancelToken { get; set; }
public List InterpreterOptions { get => _interpreterOptions; private set { _interpreterOptions = value; NotifyProperty(); } }
private List _interpreterOptions;
- public IExtensionMeta SelectedInterpreter { get => Protocol.InterpreterManager.Selected; set { Protocol.InterpreterManager.Selected = value; NotifyProperty(); } }
+ public IExtensionMeta SelectedInterpreter
+ {
+ get => Protocol.InterpreterManager.Selected;
+ set
+ {
+ if (value == null) return;
+ Protocol.InterpreterManager.Selected = value;
+ NotifyProperty();
+ if (Settings.Default.InterpreterMeta != value)
+ {
+ Settings.Default.InterpreterMeta = new ExtensionMetaSetting(value);
+ Settings.Default.Save();
+ }
+ }
+ }
public List DriverOptions { get => _driverOptions; private set { _driverOptions = value; NotifyProperty(); } }
private List _driverOptions;
- public IExtensionMeta SelectedDriver { get => Protocol.DriverManager.Selected; set { Protocol.DriverManager.Selected = value; NotifyProperty(); } }
+ public IExtensionMeta SelectedDriver
+ {
+ get => Protocol.DriverManager.Selected;
+ set
+ {
+ if (value == null) return;
+ Protocol.DriverManager.Selected = value;
+ NotifyProperty();
+ if (Settings.Default.DriverMeta != value)
+ {
+ Settings.Default.DriverMeta = new ExtensionMetaSetting(value);
+ Settings.Default.Save();
+ }
+ }
+ }
public ClockAnimator Animator { get; private set; }
public CameraContainer Cam { get; private set; }
SessionState State { get => _state; set { _state = value; NotifyStateProperties(); } }
@@ -69,11 +98,44 @@ public Session()
Protocol.InterpreterManager.OnEventsLoaded += Animator.FindMaxTime;
Protocol.DriverManager.OnProtocolStart += Animator.StartAnimatorNow;
Protocol.DriverManager.OnProtocolEnd += Animator.StopAnimator;
- Protocol.LoadExtensions();
+
+ InitDefaultExtensions();
+
+
Cam = new CameraContainer();
OnStart += Cam.StartRecord;
OnStop += Cam.StopRecord;
}
+ public void InitDefaultExtensions()
+ {
+ Protocol.LoadExtensions();
+ try
+ {
+ SelectedDriver = Settings.Default.DriverMeta;
+ }
+ catch (ArgumentException e)
+ {
+ Log.Error($"Default Driver could not be seleted, exception: {e}");
+ SelectedDriver = Protocol.DriverManager.Selected;
+ }
+ catch (NullReferenceException)
+ {
+ SelectedDriver = Protocol.DriverManager.Selected;
+ }
+ try
+ {
+ SelectedInterpreter = Settings.Default.InterpreterMeta;
+ }
+ catch (ArgumentException e)
+ {
+ Log.Error($"Default Interpreter could not be seleted, exception: {e}");
+ SelectedInterpreter = Protocol.InterpreterManager.Selected;
+ }
+ catch (NullReferenceException)
+ {
+ SelectedDriver = Protocol.DriverManager.Selected;
+ }
+ }
private void LoadInterpreterOptions(List options) => InterpreterOptions = options;
private void LoadDriverOptions(List options) => DriverOptions = options;
private void NotifyStateProperties()
@@ -105,7 +167,7 @@ public void Start(bool overrideCheck = false)
OnRun?.Invoke();
Protocol.Run();
}
- if(!CancelToken.IsCancellationRequested)
+ if (!CancelToken.IsCancellationRequested)
Stop();
}, CancelSource.Token);
SessionTask.Start();
diff --git a/ProtocolMasterWPF/Properties/Settings.Designer.cs b/ProtocolMasterWPF/Properties/Settings.Designer.cs
index 723439d..9abb4c8 100644
--- a/ProtocolMasterWPF/Properties/Settings.Designer.cs
+++ b/ProtocolMasterWPF/Properties/Settings.Designer.cs
@@ -26,12 +26,58 @@ public static Settings Default {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
- public string SessionConfig {
+ public string CameraID {
get {
- return ((string)(this["SessionConfig"]));
+ return ((string)(this["CameraID"]));
}
set {
- this["SessionConfig"] = value;
+ this["CameraID"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string MicrophoneID {
+ get {
+ return ((string)(this["MicrophoneID"]));
+ }
+ set {
+ this["MicrophoneID"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public global::ProtocolMasterWPF.Model.ExtensionMetaSetting DriverMeta {
+ get {
+ return ((global::ProtocolMasterWPF.Model.ExtensionMetaSetting)(this["DriverMeta"]));
+ }
+ set {
+ this["DriverMeta"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public global::ProtocolMasterWPF.Model.ExtensionMetaSetting InterpreterMeta {
+ get {
+ return ((global::ProtocolMasterWPF.Model.ExtensionMetaSetting)(this["InterpreterMeta"]));
+ }
+ set {
+ this["InterpreterMeta"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string ExperimentDefaultTab {
+ get {
+ return ((string)(this["ExperimentDefaultTab"]));
+ }
+ set {
+ this["ExperimentDefaultTab"] = value;
}
}
}
diff --git a/ProtocolMasterWPF/Properties/Settings.settings b/ProtocolMasterWPF/Properties/Settings.settings
index 5e7af51..6a6e335 100644
--- a/ProtocolMasterWPF/Properties/Settings.settings
+++ b/ProtocolMasterWPF/Properties/Settings.settings
@@ -2,7 +2,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ProtocolMasterWPF/ProtocolMasterWPF.csproj b/ProtocolMasterWPF/ProtocolMasterWPF.csproj
index 54ee78b..7cea15d 100644
--- a/ProtocolMasterWPF/ProtocolMasterWPF.csproj
+++ b/ProtocolMasterWPF/ProtocolMasterWPF.csproj
@@ -6,6 +6,9 @@
true
Assets\Logo\LogoSquareIcon.ico
app.manifest
+ 2021.1
+ false
+ false
@@ -15,6 +18,7 @@
x64
+ false
diff --git a/ProtocolMasterWPF/Settings.cs b/ProtocolMasterWPF/Settings.cs
new file mode 100644
index 0000000..aac3792
--- /dev/null
+++ b/ProtocolMasterWPF/Settings.cs
@@ -0,0 +1,28 @@
+namespace ProtocolMasterWPF.Properties {
+
+
+ // This class allows you to handle specific events on the settings class:
+ // The SettingChanging event is raised before a setting's value is changed.
+ // The PropertyChanged event is raised after a setting's value is changed.
+ // The SettingsLoaded event is raised after the setting values are loaded.
+ // The SettingsSaving event is raised before the setting values are saved.
+ internal sealed partial class Settings {
+
+ public Settings() {
+ // // To add event handlers for saving and changing settings, uncomment the lines below:
+ //
+ // this.SettingChanging += this.SettingChangingEventHandler;
+ //
+ // this.SettingsSaving += this.SettingsSavingEventHandler;
+ //
+ }
+
+ private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
+ // Add code to handle the SettingChangingEvent event here.
+ }
+
+ private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
+ // Add code to handle the SettingsSaving event here.
+ }
+ }
+}
diff --git a/ProtocolMasterWPF/View/ProtocolSelectView.xaml b/ProtocolMasterWPF/View/ProtocolSelectView.xaml
index f58f0d8..ad899c2 100644
--- a/ProtocolMasterWPF/View/ProtocolSelectView.xaml
+++ b/ProtocolMasterWPF/View/ProtocolSelectView.xaml
@@ -8,7 +8,7 @@
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
-
@@ -70,7 +70,7 @@
-
+
@@ -81,10 +81,10 @@
ItemsSource="{Binding DriverOptions}" SelectedValue="{Binding SelectedDriver, Mode=TwoWay}" BorderThickness="1" BorderBrush="{DynamicResource MaterialDesignLightSeparatorBackground}"/>
+ ItemsSource="{Binding Source={x:Static model:MediaDevices.Instance}, Path=VideoDevices}" SelectedValue="{Binding Cam.VideoDevice, Mode=TwoWay}" DisplayMemberPath="Name" BorderThickness="1" BorderBrush="{DynamicResource MaterialDesignLightSeparatorBackground}"/>
+ ItemsSource="{Binding Source={x:Static model:MediaDevices.Instance}, Path=AudioDevices}" SelectedValue="{Binding Cam.AudioDevice, Mode=TwoWay}" DisplayMemberPath="Name" BorderThickness="1" BorderBrush="{DynamicResource MaterialDesignLightSeparatorBackground}"/>