diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 46f1173c5..ae98da40c 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -110,6 +110,7 @@ x64 prompt MinimumRecommendedRules.ruleset + true bin\x64\Release\ diff --git a/Artemis/Artemis/Models/ProfileEditorModel.cs b/Artemis/Artemis/Models/ProfileEditorModel.cs index ebc55d2be..050530bae 100644 --- a/Artemis/Artemis/Models/ProfileEditorModel.cs +++ b/Artemis/Artemis/Models/ProfileEditorModel.cs @@ -25,7 +25,7 @@ namespace Artemis.Models private readonly DialogService _dialogService; private readonly WindowService _windowService; private FileSystemWatcher _watcher; - private ProfileModel _luaProfile; + private ModuleModel _luaModule; public ProfileEditorModel(WindowService windowService, MetroDialogService dialogService, DeviceManager deviceManager, LuaManager luaManager) @@ -290,7 +290,7 @@ namespace Artemis.Models #region LUA - public void OpenLuaEditor(ProfileModel profileModel) + public void OpenLuaEditor(ModuleModel moduleModel) { // Clean up old environment DisposeLuaWatcher(); @@ -301,12 +301,12 @@ namespace Artemis.Models file.Dispose(); // Add instructions to LUA script if it's a new file - if (string.IsNullOrEmpty(profileModel.LuaScript)) - profileModel.LuaScript = Encoding.UTF8.GetString(Resources.lua_placeholder); - File.WriteAllText(Path.GetTempPath() + fileName, profileModel.LuaScript); + if (string.IsNullOrEmpty(moduleModel.ProfileModel.LuaScript)) + moduleModel.ProfileModel.LuaScript = Encoding.UTF8.GetString(Resources.lua_placeholder); + File.WriteAllText(Path.GetTempPath() + fileName, moduleModel.ProfileModel.LuaScript); // Watch the file for changes - _luaProfile = profileModel; + _luaModule = moduleModel; _watcher = new FileSystemWatcher(Path.GetTempPath(), fileName); _watcher.Changed += LuaFileChanged; _watcher.EnableRaisingEvents = true; @@ -319,7 +319,7 @@ namespace Artemis.Models private void LuaFileChanged(object sender, FileSystemEventArgs args) { - if (_luaProfile == null) + if (_luaModule == null) { DisposeLuaWatcher(); return; @@ -328,18 +328,18 @@ namespace Artemis.Models if (args.ChangeType != WatcherChangeTypes.Changed) return; - lock (_luaProfile) + lock (_luaModule) { using (var fs = new FileStream(args.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var sr = new StreamReader(fs)) { - _luaProfile.LuaScript = sr.ReadToEnd(); + _luaModule.ProfileModel.LuaScript = sr.ReadToEnd(); } } - ProfileProvider.AddOrUpdate(_luaProfile); - _luaManager.SetupLua(_luaProfile); + ProfileProvider.AddOrUpdate(_luaModule.ProfileModel); + _luaManager.SetupLua(_luaModule.ProfileModel); } } diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileDataModel.cs b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileDataModel.cs index 7400ad81f..95d252fd4 100644 --- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileDataModel.cs +++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileDataModel.cs @@ -15,6 +15,7 @@ namespace Artemis.Modules.General.GeneralProfile CurrentTime = new CurrentTime(); Keyboard = new KbDataModel(); ActiveWindow = new ActiveWindow(); + Audio = new Audio(); } public CpuDataModel Cpu { get; set; } @@ -24,6 +25,30 @@ namespace Artemis.Modules.General.GeneralProfile public CurrentTime CurrentTime { get; set; } public KbDataModel Keyboard { get; set; } public ActiveWindow ActiveWindow { get; set; } + public Audio Audio { get; set; } + } + + [MoonSharpUserData] + public class Audio + { + public double Volume { get; set; } + public double Peak { get; set; } + public AudioDevice Recording { get; set; } = new AudioDevice(); + public AudioDevice Playback { get; set; } = new AudioDevice(); + } + + [MoonSharpUserData] + public class AudioDevice + { + public float OverallPeak { get; set; } + public float Channel1Peak { get; set; } + public float Channel2Peak { get; set; } + public float Channel3Peak { get; set; } + public float Channel4Peak { get; set; } + public float Channel5Peak { get; set; } + public float Channel6Peak { get; set; } + public float Channel7Peak { get; set; } + public float Channel8Peak { get; set; } } [MoonSharpUserData] diff --git a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs index 73162b267..b407cc8d0 100644 --- a/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs +++ b/Artemis/Artemis/Modules/General/GeneralProfile/GeneralProfileModel.cs @@ -7,9 +7,12 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Artemis.DAL; +using Artemis.Events; using Artemis.Managers; using Artemis.Modules.Abstract; +using Artemis.Profiles.Layers.Types.Audio.AudioCapturing; using Artemis.Utilities; +using CSCore.CoreAudioAPI; using Newtonsoft.Json; using SpotifyAPI.Local; @@ -17,19 +20,21 @@ namespace Artemis.Modules.General.GeneralProfile { public class GeneralProfileModel : ModuleModel { - private List _cores; - private int _cpuFrames; + private readonly AudioCaptureManager _audioCaptureManager; private DateTime _lastMusicUpdate; - private PerformanceCounter _overallCpu; private SpotifyLocalAPI _spotify; private bool _spotifySetupBusy; - public GeneralProfileModel(DeviceManager deviceManager, LuaManager luaManager) : base(deviceManager, luaManager) + public GeneralProfileModel(DeviceManager deviceManager, LuaManager luaManager, + AudioCaptureManager audioCaptureManager) : base(deviceManager, luaManager) { + _audioCaptureManager = audioCaptureManager; _lastMusicUpdate = DateTime.Now; Settings = SettingsProvider.Load(); DataModel = new GeneralProfileDataModel(); + + audioCaptureManager.AudioDeviceChanged += AudioDeviceChanged; } public override string Name => "GeneralProfile"; @@ -40,6 +45,7 @@ namespace Artemis.Modules.General.GeneralProfile { SetupCpu(); SetupSpotify(); + SetupAudio(); base.Enable(); } @@ -52,6 +58,7 @@ namespace Artemis.Modules.General.GeneralProfile UpdateDay(dataModel); UpdateKeyStates(dataModel); UpdateActiveWindow(dataModel); + UpdateAudio(dataModel); } #region Current Time @@ -67,8 +74,59 @@ namespace Artemis.Modules.General.GeneralProfile #endregion + #region Audio + + private MMDevice _defaultRecording; + private MMDevice _defaultPlayback; + + private void SetupAudio() + { + _defaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); + _defaultRecording = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); + } + + private void AudioDeviceChanged(object sender, AudioDeviceChangedEventArgs e) + { + _defaultRecording = e.DefaultRecording; + _defaultPlayback = e.DefaultPlayback; + } + + private void UpdateAudio(GeneralProfileDataModel dataModel) + { + var recording = AudioMeterInformation.FromDevice(_defaultRecording); + var playback = AudioMeterInformation.FromDevice(_defaultPlayback); + + dataModel.Audio.Recording.OverallPeak = recording.PeakValue; + for (var i = 0; i < recording.GetChannelsPeakValues(recording.MeteringChannelCount).Length; i++) + { + // Only support up to 8 channels until lists are supported natively + if (i > 7) + break; + + var peakValue = recording.GetChannelsPeakValues(recording.MeteringChannelCount)[i]; + typeof(AudioDevice).GetProperty($"Channel{i + 1}Peak").SetValue(dataModel.Audio.Recording, peakValue); + } + + dataModel.Audio.Playback.OverallPeak = playback.PeakValue; + for (var i = 0; i < playback.GetChannelsPeakValues(playback.MeteringChannelCount).Length; i++) + { + // Only support up to 8 channels until lists are supported natively + if (i > 7) + break; + + var peakValue = playback.GetChannelsPeakValues(playback.MeteringChannelCount)[i]; + typeof(AudioDevice).GetProperty($"Channel{i + 1}Peak").SetValue(dataModel.Audio.Playback, peakValue); + } + } + + #endregion + #region CPU + private List _cores; + private int _cpuFrames; + private PerformanceCounter _overallCpu; + private void SetupCpu() { try diff --git a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCaptureManager.cs b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCaptureManager.cs index cf7d34ee5..de8ccfa2a 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCaptureManager.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Audio/AudioCapturing/AudioCaptureManager.cs @@ -1,65 +1,65 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Timers; -using Artemis.Events; -using CSCore.CoreAudioAPI; -using Ninject.Extensions.Logging; - -namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing -{ - public class AudioCaptureManager - { - private readonly List _audioCaptures; - private MMDevice _lastDefaultPlayback; - private MMDevice _lastDefaultRecording; - - public AudioCaptureManager(ILogger logger) - { - Logger = logger; - _audioCaptures = new List(); - _lastDefaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); - _lastDefaultRecording = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); - - var defaultDeviceTimer = new Timer(1000); - defaultDeviceTimer.Elapsed += DefaultDeviceTimerOnElapsed; - defaultDeviceTimer.Start(); - } - - public event EventHandler AudioDeviceChanged; - - private void DefaultDeviceTimerOnElapsed(object sender, ElapsedEventArgs e) - { - var defaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); - var defaultRecording = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); - - if (defaultPlayback.DeviceID == _lastDefaultPlayback.DeviceID && +using System; +using System.Collections.Generic; +using System.Linq; +using System.Timers; +using Artemis.Events; +using CSCore.CoreAudioAPI; +using Ninject.Extensions.Logging; + +namespace Artemis.Profiles.Layers.Types.Audio.AudioCapturing +{ + public class AudioCaptureManager + { + private readonly List _audioCaptures; + private MMDevice _lastDefaultPlayback; + private MMDevice _lastDefaultRecording; + + public AudioCaptureManager(ILogger logger) + { + Logger = logger; + _audioCaptures = new List(); + _lastDefaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); + _lastDefaultRecording = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); + + var defaultDeviceTimer = new Timer(1000); + defaultDeviceTimer.Elapsed += DefaultDeviceTimerOnElapsed; + defaultDeviceTimer.Start(); + } + + public event EventHandler AudioDeviceChanged; + + private void DefaultDeviceTimerOnElapsed(object sender, ElapsedEventArgs e) + { + var defaultPlayback = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Render, Role.Multimedia); + var defaultRecording = MMDeviceEnumerator.DefaultAudioEndpoint(DataFlow.Capture, Role.Multimedia); + + if (defaultPlayback.DeviceID == _lastDefaultPlayback.DeviceID && defaultRecording.DeviceID == _lastDefaultRecording.DeviceID) - return; - - _lastDefaultPlayback = defaultPlayback; - _lastDefaultRecording = defaultRecording; - OnAudioDeviceChanged(new AudioDeviceChangedEventArgs(_lastDefaultPlayback, _lastDefaultRecording)); - } - - public AudioCapture GetAudioCapture(MMDevice device) - { - // Return existing audio capture if found - var audioCapture = _audioCaptures.FirstOrDefault(a => a.Device.DeviceID == device.DeviceID); - if (audioCapture != null) - return audioCapture; - - // Else create a new one and return that - var newAudioCapture = new AudioCapture(Logger, device); - _audioCaptures.Add(newAudioCapture); - return newAudioCapture; - } - - public ILogger Logger { get; set; } - - protected virtual void OnAudioDeviceChanged(AudioDeviceChangedEventArgs e) - { - AudioDeviceChanged?.Invoke(this, e); - } - } + return; + + _lastDefaultPlayback = defaultPlayback; + _lastDefaultRecording = defaultRecording; + OnAudioDeviceChanged(new AudioDeviceChangedEventArgs(_lastDefaultPlayback, _lastDefaultRecording)); + } + + public AudioCapture GetAudioCapture(MMDevice device) + { + // Return existing audio capture if found + var audioCapture = _audioCaptures.FirstOrDefault(a => a.Device.DeviceID == device.DeviceID); + if (audioCapture != null) + return audioCapture; + + // Else create a new one and return that + var newAudioCapture = new AudioCapture(Logger, device); + _audioCaptures.Add(newAudioCapture); + return newAudioCapture; + } + + public ILogger Logger { get; set; } + + protected virtual void OnAudioDeviceChanged(AudioDeviceChangedEventArgs e) + { + AudioDeviceChanged?.Invoke(this, e); + } + } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs index 5dd3cbfed..75635ea2f 100644 --- a/Artemis/Artemis/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Profiles/ProfileModel.cs @@ -192,8 +192,7 @@ namespace Artemis.Profiles public void Activate(LuaManager luaManager) { - if (!Equals(luaManager.ProfileModel, this) || luaManager.ProfileModel.LuaScript != LuaScript) - luaManager.SetupLua(this); + luaManager.SetupLua(this); } public void Deactivate(LuaManager luaManager) diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs index bfd4f67b2..7145f682a 100644 --- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs @@ -94,7 +94,7 @@ namespace Artemis.ViewModels return; try { - ProfileEditorModel.OpenLuaEditor(SelectedProfile); + ProfileEditorModel.OpenLuaEditor(_moduleModel); } catch (Exception e) {