# HG changeset patch # User StephaneLenclud # Date 1471523750 -7200 # Node ID c92587ddabcdd4da1984d03612b5263ea6fb1121 # Parent 1a1c2ae3a29c7ea86f55eda3527cddfad2ca6069 Support for launch action and WMC HID events. diff -r 1a1c2ae3a29c -r c92587ddabcd .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Aug 18 14:35:50 2016 +0200 @@ -0,0 +1,5 @@ +obj/*.* +bin/*.* +packages/*.* +.vs/*.* +ipch/*.* \ No newline at end of file diff -r 1a1c2ae3a29c -r c92587ddabcd Server/Actions/ActionHarmonyCommand.cs --- a/Server/Actions/ActionHarmonyCommand.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/Server/Actions/ActionHarmonyCommand.cs Thu Aug 18 14:35:50 2016 +0200 @@ -36,7 +36,7 @@ /// public override string Brief() { - string brief=""; + string brief="Harmony: "; if (Program.HarmonyConfig != null) { diff -r 1a1c2ae3a29c -r c92587ddabcd Server/Events/EventHidConsumerControl.cs --- a/Server/Events/EventHidConsumerControl.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/Server/Events/EventHidConsumerControl.cs Thu Aug 18 14:35:50 2016 +0200 @@ -42,10 +42,14 @@ /// public override bool Equals(object obj) { - EventHidConsumerControl e = (EventHidConsumerControl) obj; - bool res = (e != null && e.Usage == Usage); - return res; + if (obj is EventHidConsumerControl) + { + EventHidConsumerControl e = (EventHidConsumerControl)obj; + bool res = (e.Usage == Usage); + return res; + } + + return false; } - } } diff -r 1a1c2ae3a29c -r c92587ddabcd Server/Events/EventHidWindowsMediaCenter.cs --- a/Server/Events/EventHidWindowsMediaCenter.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/Server/Events/EventHidWindowsMediaCenter.cs Thu Aug 18 14:35:50 2016 +0200 @@ -3,10 +3,54 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Runtime.Serialization; +using Ear = SharpLib.Ear; +using Hid = SharpLib.Hid; -namespace SharpDisplayManager.Events +namespace SharpDisplayManager { - class EventHidWindowsMediaCenter + [DataContract] + [Ear.AttributeObject(Id = "Event.Hid.WindowsMediaCenter", Name = "HID Windows Media Center", Description = "Corresponding HID message received.")] + public class EventHidWindowsMediaCenter : Ear.Event { + public EventHidWindowsMediaCenter() + { + } + + [DataMember] + [Ear.AttributeObjectProperty + ( + Id = "HID.WMC.Usage", + Name = "Usage", + Description = "The usage corresponding to your remote button." + )] + public Hid.Usage.WindowsMediaCenterRemoteControl Usage { get; set; } + + /// + /// Make sure we distinguish between various configuration of this event + /// + /// + public override string Brief() + { + return Name + ": " + Usage.ToString(); + } + + /// + /// + /// + /// + /// + public override bool Equals(object obj) + { + if (obj is EventHidWindowsMediaCenter) + { + EventHidWindowsMediaCenter e = (EventHidWindowsMediaCenter)obj; + bool res = (e.Usage == Usage); + return res; + } + + return false; + } + } } diff -r 1a1c2ae3a29c -r c92587ddabcd Server/FormEditObject.cs --- a/Server/FormEditObject.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/Server/FormEditObject.cs Thu Aug 18 14:35:50 2016 +0200 @@ -13,6 +13,7 @@ using System.Reflection; using Microsoft.VisualBasic.CompilerServices; using SharpLib.Utils; +using CodeProject.Dialog; namespace SharpDisplayManager { @@ -146,6 +147,12 @@ TextBox ctrl = (TextBox)aControl; aInfo.SetValue(aObject, ctrl.Text); } + else if (aInfo.PropertyType == typeof(PropertyFile)) + { + Button ctrl = (Button)aControl; + PropertyFile value = new PropertyFile {FullPath=ctrl.Text}; + aInfo.SetValue(aObject, value); + } //TODO: add support for other types here } @@ -218,6 +225,31 @@ ctrl.Text = (string)aInfo.GetValue(aObject); return ctrl; } + else if (aInfo.PropertyType == typeof(PropertyFile)) + { + // We have a file property + // Create a button that will trigger the open file dialog to select our file. + Button ctrl = new Button(); + ctrl.AutoSize = true; + ctrl.Text = ((PropertyFile)aInfo.GetValue(aObject)).FullPath; + // Add lambda expression to Click event + ctrl.Click += (sender, e) => + { + // Create open file dialog + OpenFileDialog ofd = new OpenFileDialog(); + ofd.RestoreDirectory = true; + // Use file filter specified by our property + ofd.Filter = aAttribute.Filter; + // Show our dialog + if (DlgBox.ShowDialog(ofd) == DialogResult.OK) + { + // Fetch selected file name + ctrl.Text = ofd.FileName; + } + }; + + return ctrl; + } //TODO: add support for other control type here return null; @@ -245,6 +277,10 @@ { return true; } + else if (aInfo.PropertyType == typeof(PropertyFile)) + { + return true; + } //TODO: add support for other type here return false; diff -r 1a1c2ae3a29c -r c92587ddabcd Server/FormMain.Hid.cs --- a/Server/FormMain.Hid.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/Server/FormMain.Hid.cs Thu Aug 18 14:35:50 2016 +0200 @@ -127,6 +127,12 @@ //We are in the proper thread if (aHidEvent.UsagePage == (ushort) Hid.UsagePage.WindowsMediaCenterRemoteControl) { + //Trigger events as needed + EventHidWindowsMediaCenter e = new EventHidWindowsMediaCenter { Usage = (Hid.Usage.WindowsMediaCenterRemoteControl)aHidEvent.Usages[0] }; + Properties.Settings.Default.EarManager.TriggerEvent(e); + + //Old legacy hard coded stuff + //TODO: remove it switch (aHidEvent.Usages[0]) { case (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart: @@ -140,16 +146,14 @@ } else if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer) { + EventHidConsumerControl e = new EventHidConsumerControl { Usage = (Hid.Usage.ConsumerControl)aHidEvent.Usages[0] }; + Properties.Settings.Default.EarManager.TriggerEvent(e); + //Keep this for debug when only ThinkPad keyboard is available //if (aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier) //{ // HandleEject(); //} - - EventHidConsumerControl e = new EventHidConsumerControl {Usage = (Hid.Usage.ConsumerControl)aHidEvent.Usages[0]}; - Properties.Settings.Default.EarManager.TriggerEvent(e); - - } } diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/Action.cs --- a/SharpLibEar/Action.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/SharpLibEar/Action.cs Thu Aug 18 14:35:50 2016 +0200 @@ -9,8 +9,7 @@ namespace SharpLib.Ear { [DataContract] - [KnownType("DerivedTypes")] - public abstract class Action: IComparable + public abstract class Action: Object { protected abstract void DoExecute(); @@ -29,28 +28,6 @@ DoExecute(); } - public string Name { - //Get the name of this object action attribute - get { return Utils.Reflection.GetAttribute(GetType()).Name; } - private set { } - } - - public virtual string Brief() - { - return Name; - } - - public int CompareTo(object obj) - { - //Sort by action name - return Utils.Reflection.GetAttribute(GetType()).Name.CompareTo(obj.GetType()); - } - - private static IEnumerable DerivedTypes() - { - return SharpLib.Utils.Reflection.GetDerivedTypes(); - } - } diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/ActionLaunchApp.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SharpLibEar/ActionLaunchApp.cs Thu Aug 18 14:35:50 2016 +0200 @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace SharpLib.Ear +{ + [DataContract] + [AttributeObject(Id = "Action.Launch.App", Name = "Launch application", Description = "Launch an application.")] + public class ActionLaunchApp : Action + { + [DataMember] + [AttributeObjectProperty + ( + Id = "Action.Launch.App.File", + Name = "File to launch", + Description = "Specifies the application file to launch.", + Filter = "EXE files (*.exe)|*.exe" + ) + ] + public PropertyFile File { get; set; } = new PropertyFile(); + + [DataMember] + [AttributeObjectProperty + ( + Id = "Action.Launch.App.SwitchTo", + Name = "Switch to", + Description = "Specifies if we should switch the application if it's already launched." + ) + ] + public bool SwitchTo { get; set; } = true; + + [DataMember] + [AttributeObjectProperty + ( + Id = "Action.Launch.App.MultipleInstance", + Name = "Multiple Instance", + Description = "Specifies if We should launch multiple instance." + ) + ] + public bool MultipleInstance { get; set; } = false; + + public override string Brief() + { + return Name + ": " + Path.GetFileName(File.FullPath); + } + + [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SwitchToThisWindow")] + public static extern void SwitchToThisWindow([System.Runtime.InteropServices.InAttribute()] System.IntPtr hwnd, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fUnknown); + + + protected override void DoExecute() + { + //First check if the process we want to launch already exists + string procName = Path.GetFileNameWithoutExtension(File.FullPath); + Process[] existingProcesses = Process.GetProcessesByName(procName); + if (existingProcesses == null || existingProcesses.Length == 0 || MultipleInstance) + { + // Process do not exists just try to launch it + ProcessStartInfo start = new ProcessStartInfo(); + // Enter in the command line arguments, everything you would enter after the executable name itself + //start.Arguments = arguments; + // Enter the executable to run, including the complete path + start.FileName = File.FullPath; + start.WindowStyle = ProcessWindowStyle.Normal; + start.CreateNoWindow = true; + start.UseShellExecute = true; + // Run the external process & wait for it to finish + Process proc = Process.Start(start); + + //SL: We could have used that too + //Shell32.Shell shell = new Shell32.Shell(); + //shell.ShellExecute(Properties.Settings.Default.StartFileName); + } + else if (SwitchTo) + { + //This won't work properly until we have a manifest that enables uiAccess. + //However uiAccess just won't work with ClickOnce so we will have to use a different deployment system. + SwitchToThisWindow(existingProcesses[0].MainWindowHandle, true); + } + + } + } +} diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/AttributeObjectProperty.cs --- a/SharpLibEar/AttributeObjectProperty.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/SharpLibEar/AttributeObjectProperty.cs Thu Aug 18 14:35:50 2016 +0200 @@ -19,6 +19,8 @@ public string Minimum; public string Maximum; public string Increment; + // For file dialog + public string Filter; } diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/Event.cs --- a/SharpLibEar/Event.cs Wed Aug 17 16:39:36 2016 +0200 +++ b/SharpLibEar/Event.cs Thu Aug 18 14:35:50 2016 +0200 @@ -8,8 +8,7 @@ namespace SharpLib.Ear { [DataContract] - [KnownType("DerivedTypes")] - public abstract class Event + public abstract class Event : Object { [DataMember] [AttributeObjectProperty @@ -24,24 +23,7 @@ [DataMember] public List Actions = new List(); - public string Name - { - //Get the name of this object attribute - get { return Utils.Reflection.GetAttribute(GetType()).Name; } - private set { } - } - public string Description - { - //Get the description of this object attribute - get { return Utils.Reflection.GetAttribute(GetType()).Description; } - private set { } - } - - public virtual string Brief() - { - return Name; - } protected Event() { @@ -68,15 +50,6 @@ } } - /// - /// So that data contract knows all our types. - /// - /// - private static IEnumerable DerivedTypes() - { - return SharpLib.Utils.Reflection.GetDerivedTypes(); - } - // public override bool Equals(object obj) { diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/Object.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SharpLibEar/Object.cs Thu Aug 18 14:35:50 2016 +0200 @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + + +namespace SharpLib.Ear +{ + + /// + /// EAR object provides serialization support. + /// It assumes most derived class is decorated with AttributeObject. + /// + [DataContract] + [KnownType("DerivedTypes")] + public abstract class Object: IComparable + { + + public string Name + { + //Get the name of this object attribute + get { return Utils.Reflection.GetAttribute(GetType()).Name; } + private set { } + } + + public string Description + { + //Get the description of this object attribute + get { return Utils.Reflection.GetAttribute(GetType()).Description; } + private set { } + } + + public virtual string Brief() + { + return Name; + } + + public int CompareTo(object obj) + { + //Sort by object name + return Utils.Reflection.GetAttribute(GetType()).Name.CompareTo(obj.GetType()); + } + + /// + /// So that data contract knows all our types. + /// + /// + private static IEnumerable DerivedTypes() + { + return SharpLib.Utils.Reflection.GetDerivedTypes(); + } + + } +} diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/PropertyFile.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SharpLibEar/PropertyFile.cs Thu Aug 18 14:35:50 2016 +0200 @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace SharpLib.Ear +{ + /// + /// File property + /// + [DataContract] + [AttributeObject(Id = "Property.File", Name = "File", Description = "Holds a full file path.")] + public class PropertyFile : Object + { + [DataMember] + public string FullPath { get; set; } = ""; + } +} diff -r 1a1c2ae3a29c -r c92587ddabcd SharpLibEar/SharpLibEar.csproj --- a/SharpLibEar/SharpLibEar.csproj Wed Aug 17 16:39:36 2016 +0200 +++ b/SharpLibEar/SharpLibEar.csproj Thu Aug 18 14:35:50 2016 +0200 @@ -61,6 +61,7 @@ + @@ -69,7 +70,9 @@ + +