From 03c8da54c3e9560fa8113e5f8ab03666e9773bf3 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 1 Nov 2016 16:28:57 +0100 Subject: [PATCH] LUA memory improvements --- Artemis/Artemis/Models/EffectModel.cs | 9 +- .../ProfilePreview/ProfilePreviewModel.cs | 4 +- .../Profiles/Lua/Events/LuaEventsWrapper.cs | 86 +++++++---------- .../Profiles/Lua/LuaKeyboardWrapper.cs | 8 +- Artemis/Artemis/Profiles/Lua/LuaWrapper.cs | 96 +++++++++++-------- Artemis/Artemis/Profiles/ProfileModel.cs | 23 ++++- .../Profiles/ProfileEditorViewModel.cs | 22 +---- 7 files changed, 119 insertions(+), 129 deletions(-) diff --git a/Artemis/Artemis/Models/EffectModel.cs b/Artemis/Artemis/Models/EffectModel.cs index 7dad6f719..5a455f702 100644 --- a/Artemis/Artemis/Models/EffectModel.cs +++ b/Artemis/Artemis/Models/EffectModel.cs @@ -41,10 +41,7 @@ namespace Artemis.Models public virtual void Dispose() { - if (Profile?.LuaWrapper == null) - return; - Profile.LuaWrapper.Dispose(); - Profile.LuaWrapper = null; + Profile?.Deactivate(); } // Called on creation @@ -70,8 +67,8 @@ namespace Artemis.Models var renderLayers = GetRenderLayers(keyboardOnly); // If the profile has no active LUA wrapper, create one - if (Profile.LuaWrapper == null && !string.IsNullOrEmpty(Profile.LuaScript)) - Profile.LuaWrapper = new LuaWrapper(Profile, MainManager.DeviceManager.ActiveKeyboard); + if (!string.IsNullOrEmpty(Profile.LuaScript)) + Profile.Activate(MainManager.DeviceManager.ActiveKeyboard); // Render the keyboard layer-by-layer var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); diff --git a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs index f547cd0ec..7fb9fa7b0 100644 --- a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs +++ b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs @@ -54,8 +54,8 @@ namespace Artemis.Modules.Effects.ProfilePreview var renderLayers = GetRenderLayers(keyboardOnly); // If the profile has no active LUA wrapper, create one - if (Profile.LuaWrapper == null && !string.IsNullOrEmpty(Profile.LuaScript)) - Profile.LuaWrapper = new LuaWrapper(Profile, MainManager.DeviceManager.ActiveKeyboard); + if (!string.IsNullOrEmpty(Profile.LuaScript)) + Profile.Activate(MainManager.DeviceManager.ActiveKeyboard); // Render the keyboard layer-by-layer var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); diff --git a/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs b/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs index bf9327c7c..d763bead8 100644 --- a/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs +++ b/Artemis/Artemis/Profiles/Lua/Events/LuaEventsWrapper.cs @@ -11,6 +11,7 @@ namespace Artemis.Profiles.Lua.Events public class LuaEventsWrapper { private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + private readonly string _invokeLock = string.Empty; public event EventHandler ProfileUpdating; public event EventHandler ProfileDrawing; public event EventHandler KeyboardKeyPressed; @@ -19,8 +20,8 @@ namespace Artemis.Profiles.Lua.Events { try { - OnProfileUpdating(new LuaProfileWrapper(profileModel), - new LuaProfileUpdatingEventArgs(dataModel, preview)); + LuaInvoke(profileModel, () => OnProfileUpdating(new LuaProfileWrapper(profileModel), + new LuaProfileUpdatingEventArgs(dataModel, preview))); } catch (Exception) { @@ -32,8 +33,8 @@ namespace Artemis.Profiles.Lua.Events { try { - OnProfileDrawing(new LuaProfileWrapper(profileModel), - new LuaProfileDrawingEventArgs(dataModel, preview, new LuaDrawWrapper(c))); + LuaInvoke(profileModel, () => OnProfileDrawing(new LuaProfileWrapper(profileModel), + new LuaProfileDrawingEventArgs(dataModel, preview, new LuaDrawWrapper(c)))); } catch (Exception) { @@ -45,7 +46,8 @@ namespace Artemis.Profiles.Lua.Events { try { - OnKeyboardKeyPressed(new LuaProfileWrapper(profileModel), keyboard, new LuaKeyPressEventArgs(key, x, y)); + LuaInvoke(profileModel, () => OnKeyboardKeyPressed(new LuaProfileWrapper(profileModel), + keyboard, new LuaKeyPressEventArgs(key, x, y))); } catch (Exception) { @@ -53,65 +55,43 @@ namespace Artemis.Profiles.Lua.Events } } + private void LuaInvoke(ProfileModel profileModel, Action action) + { + lock (_invokeLock) + { + try + { + action.Invoke(); + } + catch (InternalErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (SyntaxErrorException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + catch (ScriptRuntimeException ex) + { + _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); + } + } + } + protected virtual void OnProfileUpdating(LuaProfileWrapper profileModel, LuaProfileUpdatingEventArgs e) { - try - { - ProfileUpdating?.Invoke(profileModel, e); - } - catch (InternalErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (SyntaxErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (ScriptRuntimeException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } + ProfileUpdating?.Invoke(profileModel, e); } protected virtual void OnProfileDrawing(LuaProfileWrapper profileModel, LuaProfileDrawingEventArgs e) { - try - { - ProfileDrawing?.Invoke(profileModel, e); - } - catch (InternalErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (SyntaxErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (ScriptRuntimeException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } + ProfileDrawing?.Invoke(profileModel, e); } protected virtual void OnKeyboardKeyPressed(LuaProfileWrapper profileModel, LuaKeyboardWrapper keyboard, LuaKeyPressEventArgs e) { - try - { - KeyboardKeyPressed?.Invoke(profileModel, e); - } - catch (InternalErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (SyntaxErrorException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } - catch (ScriptRuntimeException ex) - { - _logger.Error(ex, "[{0}-LUA]: Error: {1}", profileModel.Name, ex.DecoratedMessage); - } + KeyboardKeyPressed?.Invoke(profileModel, e); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs b/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs index ec5fcdf92..5f38bf4ec 100644 --- a/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs +++ b/Artemis/Artemis/Profiles/Lua/LuaKeyboardWrapper.cs @@ -11,11 +11,9 @@ namespace Artemis.Profiles.Lua public class LuaKeyboardWrapper : IDisposable { private readonly KeyboardProvider _keyboardProvider; - private readonly LuaWrapper _luaWrapper; - public LuaKeyboardWrapper(LuaWrapper luaWrapper, KeyboardProvider keyboardProvider) + public LuaKeyboardWrapper(KeyboardProvider keyboardProvider) { - _luaWrapper = luaWrapper; _keyboardProvider = keyboardProvider; KeyboardHook.KeyDownCallback += KeyboardHookOnKeyDownCallback; @@ -36,8 +34,8 @@ namespace Artemis.Profiles.Lua { var keyMatch = _keyboardProvider.GetKeyPosition(e.KeyCode); if (keyMatch != null) - _luaWrapper.LuaEventsWrapper.InvokeKeyPressed(_luaWrapper.ProfileModel, this, - keyMatch.Value.KeyCode, keyMatch.Value.X, keyMatch.Value.Y); + LuaWrapper.LuaEventsWrapper.InvokeKeyPressed(LuaWrapper.ProfileModel, this, keyMatch.Value.KeyCode, + keyMatch.Value.X, keyMatch.Value.Y); } public void SendKeys(string keys) diff --git a/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs b/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs index ce0fda411..230fc3c15 100644 --- a/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs +++ b/Artemis/Artemis/Profiles/Lua/LuaWrapper.cs @@ -12,37 +12,40 @@ using NLog; namespace Artemis.Profiles.Lua { - public class LuaWrapper : IDisposable + public static class LuaWrapper { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Script LuaScript = new Script(CoreModules.Preset_SoftSandbox); + private static KeyboardProvider _keyboardProvider; + private static FileSystemWatcher _watcher; - public LuaWrapper(ProfileModel profileModel, KeyboardProvider keyboardProvider) + public static ProfileModel ProfileModel { get; private set; } + public static LuaProfileWrapper LuaProfileWrapper { get; private set; } + public static LuaBrushWrapper LuaBrushWrapper { get; private set; } + public static LuaKeyboardWrapper LuaKeyboardWrapper { get; private set; } + public static LuaEventsWrapper LuaEventsWrapper { get; private set; } + + public static void SetupLua(ProfileModel profileModel, KeyboardProvider keyboardProvider) { + Clear(); + + if (profileModel == null || keyboardProvider == null) + return; + + // Setup a new environment + _keyboardProvider = keyboardProvider; ProfileModel = profileModel; LuaProfileWrapper = new LuaProfileWrapper(ProfileModel); LuaBrushWrapper = new LuaBrushWrapper(); - LuaKeyboardWrapper = new LuaKeyboardWrapper(this, keyboardProvider); - SetupLuaScript(); - } - - public ProfileModel ProfileModel { get; set; } - public LuaProfileWrapper LuaProfileWrapper { get; set; } - public LuaBrushWrapper LuaBrushWrapper { get; set; } - public LuaKeyboardWrapper LuaKeyboardWrapper { get; set; } - public LuaEventsWrapper LuaEventsWrapper { get; set; } - public Script LuaScript { get; set; } - - private void SetupLuaScript() - { + LuaKeyboardWrapper = new LuaKeyboardWrapper(keyboardProvider); LuaEventsWrapper = new LuaEventsWrapper(); - LuaScript = new Script(CoreModules.Preset_SoftSandbox); LuaScript.Options.DebugPrint = LuaPrint; LuaScript.Globals["Profile"] = LuaProfileWrapper; LuaScript.Globals["Events"] = LuaEventsWrapper; LuaScript.Globals["Brushes"] = LuaBrushWrapper; LuaScript.Globals["Keyboard"] = LuaKeyboardWrapper; - + if (ProfileModel.LuaScript.IsNullOrEmpty()) return; @@ -66,7 +69,7 @@ namespace Artemis.Profiles.Lua #region Private lua functions - private void LuaPrint(string s) + private static void LuaPrint(string s) { Logger.Debug("[{0}-LUA]: {1}", ProfileModel.Name, s); } @@ -75,8 +78,11 @@ namespace Artemis.Profiles.Lua #region Editor - public void OpenEditor() + public static void OpenEditor() { + if (ProfileModel == null) + return; + // Create a temp file var fileName = Guid.NewGuid() + ".lua"; var file = File.Create(Path.GetTempPath() + fileName); @@ -88,21 +94,31 @@ namespace Artemis.Profiles.Lua File.WriteAllText(Path.GetTempPath() + fileName, ProfileModel.LuaScript); // Watch the file for changes - var watcher = new FileSystemWatcher(Path.GetTempPath(), fileName); - watcher.Changed += LuaFileChanged; - watcher.EnableRaisingEvents = true; + SetupWatcher(Path.GetTempPath(), fileName); // Open the temp file with the default editor System.Diagnostics.Process.Start(Path.GetTempPath() + fileName); } - private void LuaFileChanged(object sender, FileSystemEventArgs fileSystemEventArgs) + private static void SetupWatcher(string path, string fileName) { - if (fileSystemEventArgs.ChangeType != WatcherChangeTypes.Changed) + if (_watcher == null) + { + _watcher = new FileSystemWatcher(Path.GetTempPath(), fileName); + _watcher.Changed += LuaFileChanged; + _watcher.EnableRaisingEvents = true; + } + + _watcher.Path = path; + _watcher.Filter = fileName; + } + + private static void LuaFileChanged(object sender, FileSystemEventArgs args) + { + if (args.ChangeType != WatcherChangeTypes.Changed) return; - using (var fs = new FileStream(fileSystemEventArgs.FullPath, - FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var fs = new FileStream(args.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var sr = new StreamReader(fs)) { @@ -111,29 +127,27 @@ namespace Artemis.Profiles.Lua } ProfileProvider.AddOrUpdate(ProfileModel); - SetupLuaScript(); + + if (_keyboardProvider != null) + SetupLua(ProfileModel, _keyboardProvider); } #endregion - #region Event triggers - - public void TriggerUpdate() + public static void Clear() { - } + // Clear old fields/properties + _keyboardProvider = null; + ProfileModel = null; + LuaKeyboardWrapper?.Dispose(); + LuaKeyboardWrapper = null; - public void TriggerDraw() - { - } - - #endregion - - public void Dispose() - { - LuaKeyboardWrapper.Dispose(); LuaScript.Globals.Clear(); LuaScript.Registry.Clear(); - LuaScript = null; + LuaScript.Registry.RegisterConstants(); + LuaScript.Registry.RegisterCoreModules(CoreModules.Preset_SoftSandbox); + LuaScript.Globals.RegisterConstants(); + LuaScript.Globals.RegisterCoreModules(CoreModules.Preset_SoftSandbox); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs index d6d5173ee..5098300b4 100644 --- a/Artemis/Artemis/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Profiles/ProfileModel.cs @@ -40,9 +40,6 @@ namespace Artemis.Profiles public int Height { get; set; } public string LuaScript { get; set; } - [JsonIgnore] - public LuaWrapper LuaWrapper { get; set; } - public void FixOrder() { Layers.Sort(l => l.Order); @@ -118,14 +115,14 @@ namespace Artemis.Profiles layerModel.Update(dataModel, preview, updateAnimations); if (triggerLua) - LuaWrapper?.LuaEventsWrapper?.InvokeProfileUpdate(this, dataModel, preview); + LuaWrapper.LuaEventsWrapper?.InvokeProfileUpdate(this, dataModel, preview); // Draw the layers foreach (var layerModel in layerModels) layerModel.Draw(dataModel, c, preview, updateAnimations); if (triggerLua) - LuaWrapper?.LuaEventsWrapper?.InvokeProfileDraw(this, dataModel, preview, c); + LuaWrapper.LuaEventsWrapper?.InvokeProfileDraw(this, dataModel, preview, c); // Remove the clip c.Pop(); @@ -206,5 +203,21 @@ namespace Artemis.Profiles } #endregion + + public void Activate(KeyboardProvider keyboard) + { + if (!Equals(LuaWrapper.ProfileModel, this)) + { + LuaWrapper.SetupLua(this, keyboard); + } + } + + public void Deactivate() + { + if (Equals(LuaWrapper.ProfileModel, this)) + { + LuaWrapper.Clear(); + } + } } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs index 0d973218f..29cc10dbe 100644 --- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs @@ -125,11 +125,7 @@ namespace Artemis.ViewModels.Profiles set { if (Equals(value, _selectedProfile)) return; - if (_selectedProfile?.LuaWrapper != null) - { - _selectedProfile.LuaWrapper.Dispose(); - _selectedProfile.LuaWrapper = null; - } + _selectedProfile?.Deactivate(); _selectedProfile = value; NotifyOfPropertyChange(() => SelectedProfile); } @@ -237,12 +233,7 @@ namespace Artemis.ViewModels.Profiles public void Deactivate() { ProfileViewModel.Deactivate(); - if (SelectedProfile?.LuaWrapper != null) - { - SelectedProfile.LuaWrapper.Dispose(); - SelectedProfile.LuaWrapper = null; - } - _saveTimer.Stop(); + SelectedProfile?.Deactivate(); } /// @@ -713,11 +704,8 @@ namespace Artemis.ViewModels.Profiles return; try { - if (SelectedProfile.LuaWrapper == null) - SelectedProfile.LuaWrapper = new LuaWrapper(SelectedProfile, - _mainManager.DeviceManager.ActiveKeyboard); - - SelectedProfile.LuaWrapper.OpenEditor(); + SelectedProfile?.Activate(_mainManager.DeviceManager.ActiveKeyboard); + LuaWrapper.OpenEditor(); } catch (Exception e) { @@ -755,7 +743,7 @@ namespace Artemis.ViewModels.Profiles private void ProfileSaveHandler(object sender, ElapsedEventArgs e) { - if (_saving || (SelectedProfile == null)) + if (_saving || (SelectedProfile == null) || !IsActive) return; _saving = true;