Support for launch action and WMC HID events.
authorStephaneLenclud
Thu, 18 Aug 2016 14:35:50 +0200
changeset 238c92587ddabcd
parent 237 1a1c2ae3a29c
child 239 dd7770b97916
Support for launch action and WMC HID events.
.hgignore
Server/Actions/ActionHarmonyCommand.cs
Server/Events/EventHidConsumerControl.cs
Server/Events/EventHidWindowsMediaCenter.cs
Server/FormEditObject.cs
Server/FormMain.Hid.cs
SharpLibEar/Action.cs
SharpLibEar/ActionLaunchApp.cs
SharpLibEar/AttributeObjectProperty.cs
SharpLibEar/Event.cs
SharpLibEar/Object.cs
SharpLibEar/PropertyFile.cs
SharpLibEar/SharpLibEar.csproj
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Thu Aug 18 14:35:50 2016 +0200
     1.3 @@ -0,0 +1,5 @@
     1.4 +obj/*.*
     1.5 +bin/*.*
     1.6 +packages/*.*
     1.7 +.vs/*.*
     1.8 +ipch/*.*
     1.9 \ No newline at end of file
     2.1 --- a/Server/Actions/ActionHarmonyCommand.cs	Wed Aug 17 16:39:36 2016 +0200
     2.2 +++ b/Server/Actions/ActionHarmonyCommand.cs	Thu Aug 18 14:35:50 2016 +0200
     2.3 @@ -36,7 +36,7 @@
     2.4          /// <returns></returns>
     2.5          public override string Brief()
     2.6          {
     2.7 -            string brief="";
     2.8 +            string brief="Harmony: ";
     2.9  
    2.10              if (Program.HarmonyConfig != null)
    2.11              {
     3.1 --- a/Server/Events/EventHidConsumerControl.cs	Wed Aug 17 16:39:36 2016 +0200
     3.2 +++ b/Server/Events/EventHidConsumerControl.cs	Thu Aug 18 14:35:50 2016 +0200
     3.3 @@ -42,10 +42,14 @@
     3.4          /// <returns></returns>
     3.5          public override bool Equals(object obj)
     3.6          {
     3.7 -            EventHidConsumerControl e = (EventHidConsumerControl) obj;
     3.8 -            bool res = (e != null && e.Usage == Usage);
     3.9 -            return res;
    3.10 +            if (obj is EventHidConsumerControl)
    3.11 +            {
    3.12 +                EventHidConsumerControl e = (EventHidConsumerControl)obj;
    3.13 +                bool res = (e.Usage == Usage);
    3.14 +                return res;
    3.15 +            }
    3.16 +
    3.17 +            return false;
    3.18          }
    3.19 -
    3.20      }
    3.21  }
     4.1 --- a/Server/Events/EventHidWindowsMediaCenter.cs	Wed Aug 17 16:39:36 2016 +0200
     4.2 +++ b/Server/Events/EventHidWindowsMediaCenter.cs	Thu Aug 18 14:35:50 2016 +0200
     4.3 @@ -3,10 +3,54 @@
     4.4  using System.Linq;
     4.5  using System.Text;
     4.6  using System.Threading.Tasks;
     4.7 +using System.Runtime.Serialization;
     4.8 +using Ear = SharpLib.Ear;
     4.9 +using Hid = SharpLib.Hid;
    4.10  
    4.11 -namespace SharpDisplayManager.Events
    4.12 +namespace SharpDisplayManager
    4.13  {
    4.14 -    class EventHidWindowsMediaCenter
    4.15 +    [DataContract]
    4.16 +    [Ear.AttributeObject(Id = "Event.Hid.WindowsMediaCenter", Name = "HID Windows Media Center", Description = "Corresponding HID message received.")]
    4.17 +    public class EventHidWindowsMediaCenter : Ear.Event
    4.18      {
    4.19 +        public EventHidWindowsMediaCenter()
    4.20 +        {
    4.21 +        }
    4.22 +
    4.23 +        [DataMember]
    4.24 +        [Ear.AttributeObjectProperty
    4.25 +            (
    4.26 +            Id = "HID.WMC.Usage",
    4.27 +            Name = "Usage",
    4.28 +            Description = "The usage corresponding to your remote button."
    4.29 +            )]
    4.30 +        public Hid.Usage.WindowsMediaCenterRemoteControl Usage { get; set; }
    4.31 +
    4.32 +        /// <summary>
    4.33 +        /// Make sure we distinguish between various configuration of this event 
    4.34 +        /// </summary>
    4.35 +        /// <returns></returns>
    4.36 +        public override string Brief()
    4.37 +        {
    4.38 +            return Name + ": " + Usage.ToString();
    4.39 +        }
    4.40 +
    4.41 +        /// <summary>
    4.42 +        ///
    4.43 +        /// </summary>
    4.44 +        /// <param name="obj"></param>
    4.45 +        /// <returns></returns>
    4.46 +        public override bool Equals(object obj)
    4.47 +        {
    4.48 +            if (obj is EventHidWindowsMediaCenter)
    4.49 +            {
    4.50 +                EventHidWindowsMediaCenter e = (EventHidWindowsMediaCenter)obj;
    4.51 +                bool res = (e.Usage == Usage);
    4.52 +                return res;
    4.53 +            }
    4.54 +
    4.55 +            return false;
    4.56 +        }
    4.57 +
    4.58      }
    4.59  }
     5.1 --- a/Server/FormEditObject.cs	Wed Aug 17 16:39:36 2016 +0200
     5.2 +++ b/Server/FormEditObject.cs	Thu Aug 18 14:35:50 2016 +0200
     5.3 @@ -13,6 +13,7 @@
     5.4  using System.Reflection;
     5.5  using Microsoft.VisualBasic.CompilerServices;
     5.6  using SharpLib.Utils;
     5.7 +using CodeProject.Dialog;
     5.8  
     5.9  namespace SharpDisplayManager
    5.10  {
    5.11 @@ -146,6 +147,12 @@
    5.12                  TextBox ctrl = (TextBox)aControl;
    5.13                  aInfo.SetValue(aObject, ctrl.Text);
    5.14              }
    5.15 +            else if (aInfo.PropertyType == typeof(PropertyFile))
    5.16 +            {
    5.17 +                Button ctrl = (Button)aControl;
    5.18 +                PropertyFile value = new PropertyFile {FullPath=ctrl.Text};
    5.19 +                aInfo.SetValue(aObject, value);
    5.20 +            }
    5.21              //TODO: add support for other types here
    5.22          }
    5.23  
    5.24 @@ -218,6 +225,31 @@
    5.25                  ctrl.Text = (string)aInfo.GetValue(aObject);
    5.26                  return ctrl;
    5.27              }
    5.28 +            else if (aInfo.PropertyType == typeof(PropertyFile))
    5.29 +            {
    5.30 +                // We have a file property
    5.31 +                // Create a button that will trigger the open file dialog to select our file.
    5.32 +                Button ctrl = new Button();
    5.33 +                ctrl.AutoSize = true;
    5.34 +                ctrl.Text = ((PropertyFile)aInfo.GetValue(aObject)).FullPath;
    5.35 +                // Add lambda expression to Click event
    5.36 +                ctrl.Click += (sender, e) =>
    5.37 +                {
    5.38 +                    // Create open file dialog
    5.39 +                    OpenFileDialog ofd = new OpenFileDialog();
    5.40 +                    ofd.RestoreDirectory = true;
    5.41 +                    // Use file filter specified by our property
    5.42 +                    ofd.Filter = aAttribute.Filter;
    5.43 +                    // Show our dialog
    5.44 +                    if (DlgBox.ShowDialog(ofd) == DialogResult.OK)
    5.45 +                    {
    5.46 +                        // Fetch selected file name
    5.47 +                        ctrl.Text = ofd.FileName;
    5.48 +                    }
    5.49 +                };
    5.50 +
    5.51 +                return ctrl;
    5.52 +            }
    5.53              //TODO: add support for other control type here
    5.54  
    5.55              return null;
    5.56 @@ -245,6 +277,10 @@
    5.57              {
    5.58                  return true;
    5.59              }
    5.60 +            else if (aInfo.PropertyType == typeof(PropertyFile))
    5.61 +            {
    5.62 +                return true;
    5.63 +            }
    5.64              //TODO: add support for other type here
    5.65  
    5.66              return false;
     6.1 --- a/Server/FormMain.Hid.cs	Wed Aug 17 16:39:36 2016 +0200
     6.2 +++ b/Server/FormMain.Hid.cs	Thu Aug 18 14:35:50 2016 +0200
     6.3 @@ -127,6 +127,12 @@
     6.4                  //We are in the proper thread
     6.5                  if (aHidEvent.UsagePage == (ushort) Hid.UsagePage.WindowsMediaCenterRemoteControl)
     6.6                  {
     6.7 +                    //Trigger events as needed
     6.8 +                    EventHidWindowsMediaCenter e = new EventHidWindowsMediaCenter { Usage = (Hid.Usage.WindowsMediaCenterRemoteControl)aHidEvent.Usages[0] };
     6.9 +                    Properties.Settings.Default.EarManager.TriggerEvent(e);
    6.10 +
    6.11 +                    //Old legacy hard coded stuff
    6.12 +                    //TODO: remove it
    6.13                      switch (aHidEvent.Usages[0])
    6.14                      {
    6.15                          case (ushort)Hid.Usage.WindowsMediaCenterRemoteControl.GreenStart:
    6.16 @@ -140,16 +146,14 @@
    6.17                  }
    6.18                  else if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer)
    6.19                  {
    6.20 +                    EventHidConsumerControl e = new EventHidConsumerControl { Usage = (Hid.Usage.ConsumerControl)aHidEvent.Usages[0] };
    6.21 +                    Properties.Settings.Default.EarManager.TriggerEvent(e);
    6.22 +
    6.23                      //Keep this for debug when only ThinkPad keyboard is available
    6.24                      //if (aHidEvent.Usages[0] == (ushort)Hid.Usage.ConsumerControl.ThinkPadFullscreenMagnifier)
    6.25                      //{
    6.26                      //    HandleEject();
    6.27                      //}
    6.28 -
    6.29 -                    EventHidConsumerControl e = new EventHidConsumerControl {Usage = (Hid.Usage.ConsumerControl)aHidEvent.Usages[0]};
    6.30 -                    Properties.Settings.Default.EarManager.TriggerEvent(e);
    6.31 -
    6.32 -
    6.33                  }
    6.34  
    6.35              }
     7.1 --- a/SharpLibEar/Action.cs	Wed Aug 17 16:39:36 2016 +0200
     7.2 +++ b/SharpLibEar/Action.cs	Thu Aug 18 14:35:50 2016 +0200
     7.3 @@ -9,8 +9,7 @@
     7.4  namespace SharpLib.Ear
     7.5  {
     7.6      [DataContract]
     7.7 -    [KnownType("DerivedTypes")]
     7.8 -    public abstract class Action: IComparable
     7.9 +    public abstract class Action: Object
    7.10      {
    7.11          protected abstract void DoExecute();
    7.12  
    7.13 @@ -29,28 +28,6 @@
    7.14              DoExecute();
    7.15          }
    7.16  
    7.17 -        public string Name {
    7.18 -            //Get the name of this object action attribute
    7.19 -            get { return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Name; }
    7.20 -            private set { }
    7.21 -        }
    7.22 -
    7.23 -        public virtual string Brief()
    7.24 -        {
    7.25 -            return Name;
    7.26 -        }
    7.27 -
    7.28 -        public int CompareTo(object obj)
    7.29 -        {
    7.30 -            //Sort by action name
    7.31 -            return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Name.CompareTo(obj.GetType());            
    7.32 -        }
    7.33 -
    7.34 -        private static IEnumerable<Type> DerivedTypes()
    7.35 -        {
    7.36 -            return SharpLib.Utils.Reflection.GetDerivedTypes<Action>();
    7.37 -        }
    7.38 -
    7.39      }
    7.40  
    7.41  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/SharpLibEar/ActionLaunchApp.cs	Thu Aug 18 14:35:50 2016 +0200
     8.3 @@ -0,0 +1,88 @@
     8.4 +using System;
     8.5 +using System.Collections.Generic;
     8.6 +using System.Diagnostics;
     8.7 +using System.IO;
     8.8 +using System.Linq;
     8.9 +using System.Runtime.Serialization;
    8.10 +using System.Text;
    8.11 +using System.Threading.Tasks;
    8.12 +
    8.13 +namespace SharpLib.Ear
    8.14 +{
    8.15 +    [DataContract]
    8.16 +    [AttributeObject(Id = "Action.Launch.App", Name = "Launch application", Description = "Launch an application.")]
    8.17 +    public class ActionLaunchApp : Action
    8.18 +    {
    8.19 +        [DataMember]
    8.20 +        [AttributeObjectProperty
    8.21 +            (
    8.22 +            Id = "Action.Launch.App.File",
    8.23 +            Name = "File to launch",
    8.24 +            Description = "Specifies the application file to launch.",
    8.25 +            Filter = "EXE files (*.exe)|*.exe"
    8.26 +            )
    8.27 +        ]
    8.28 +        public PropertyFile File { get; set; } = new PropertyFile();
    8.29 +
    8.30 +        [DataMember]
    8.31 +        [AttributeObjectProperty
    8.32 +            (
    8.33 +            Id = "Action.Launch.App.SwitchTo",
    8.34 +            Name = "Switch to",
    8.35 +            Description = "Specifies if we should switch the application if it's already launched."
    8.36 +            )
    8.37 +        ]
    8.38 +        public bool SwitchTo { get; set; } = true;
    8.39 +
    8.40 +        [DataMember]
    8.41 +        [AttributeObjectProperty
    8.42 +            (
    8.43 +            Id = "Action.Launch.App.MultipleInstance",
    8.44 +            Name = "Multiple Instance",
    8.45 +            Description = "Specifies if We should launch multiple instance."
    8.46 +            )
    8.47 +        ]
    8.48 +        public bool MultipleInstance { get; set; } = false;
    8.49 +
    8.50 +        public override string Brief()
    8.51 +        {
    8.52 +            return Name + ": " + Path.GetFileName(File.FullPath);
    8.53 +        }
    8.54 +
    8.55 +        [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SwitchToThisWindow")]
    8.56 +        public static extern void SwitchToThisWindow([System.Runtime.InteropServices.InAttribute()] System.IntPtr hwnd, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fUnknown);
    8.57 +
    8.58 +
    8.59 +        protected override void DoExecute()
    8.60 +        {
    8.61 +            //First check if the process we want to launch already exists
    8.62 +            string procName = Path.GetFileNameWithoutExtension(File.FullPath);
    8.63 +            Process[] existingProcesses = Process.GetProcessesByName(procName);
    8.64 +            if (existingProcesses == null || existingProcesses.Length == 0 || MultipleInstance)
    8.65 +            {
    8.66 +                // Process do not exists just try to launch it
    8.67 +                ProcessStartInfo start = new ProcessStartInfo();
    8.68 +                // Enter in the command line arguments, everything you would enter after the executable name itself
    8.69 +                //start.Arguments = arguments; 
    8.70 +                // Enter the executable to run, including the complete path
    8.71 +                start.FileName = File.FullPath;
    8.72 +                start.WindowStyle = ProcessWindowStyle.Normal;
    8.73 +                start.CreateNoWindow = true;
    8.74 +                start.UseShellExecute = true;
    8.75 +                // Run the external process & wait for it to finish
    8.76 +                Process proc = Process.Start(start);
    8.77 +
    8.78 +                //SL: We could have used that too
    8.79 +                //Shell32.Shell shell = new Shell32.Shell();
    8.80 +                //shell.ShellExecute(Properties.Settings.Default.StartFileName);
    8.81 +            }
    8.82 +            else if (SwitchTo)
    8.83 +            {
    8.84 +                //This won't work properly until we have a manifest that enables uiAccess.
    8.85 +                //However uiAccess just won't work with ClickOnce so we will have to use a different deployment system.
    8.86 +                SwitchToThisWindow(existingProcesses[0].MainWindowHandle, true);
    8.87 +            }
    8.88 +
    8.89 +        }
    8.90 +    }
    8.91 +}
     9.1 --- a/SharpLibEar/AttributeObjectProperty.cs	Wed Aug 17 16:39:36 2016 +0200
     9.2 +++ b/SharpLibEar/AttributeObjectProperty.cs	Thu Aug 18 14:35:50 2016 +0200
     9.3 @@ -19,6 +19,8 @@
     9.4          public string Minimum;
     9.5          public string Maximum;
     9.6          public string Increment;
     9.7 +        // For file dialog
     9.8 +        public string Filter;
     9.9      }
    9.10  
    9.11  
    10.1 --- a/SharpLibEar/Event.cs	Wed Aug 17 16:39:36 2016 +0200
    10.2 +++ b/SharpLibEar/Event.cs	Thu Aug 18 14:35:50 2016 +0200
    10.3 @@ -8,8 +8,7 @@
    10.4  namespace SharpLib.Ear
    10.5  {
    10.6      [DataContract]
    10.7 -    [KnownType("DerivedTypes")]
    10.8 -    public abstract class Event
    10.9 +    public abstract class Event : Object
   10.10      {
   10.11          [DataMember]
   10.12          [AttributeObjectProperty
   10.13 @@ -24,24 +23,7 @@
   10.14          [DataMember]
   10.15          public List<Action> Actions = new List<Action>();
   10.16  
   10.17 -        public string Name
   10.18 -        {
   10.19 -            //Get the name of this object attribute
   10.20 -            get { return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Name; }
   10.21 -            private set { }
   10.22 -        }
   10.23  
   10.24 -        public string Description
   10.25 -        {
   10.26 -            //Get the description of this object attribute
   10.27 -            get { return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Description; }
   10.28 -            private set { }
   10.29 -        }
   10.30 -
   10.31 -        public virtual string Brief()
   10.32 -        {
   10.33 -            return Name;
   10.34 -        }
   10.35  
   10.36          protected Event()
   10.37          {
   10.38 @@ -68,15 +50,6 @@
   10.39              }
   10.40          }
   10.41  
   10.42 -        /// <summary>
   10.43 -        /// So that data contract knows all our types.
   10.44 -        /// </summary>
   10.45 -        /// <returns></returns>
   10.46 -        private static IEnumerable<Type> DerivedTypes()
   10.47 -        {
   10.48 -            return SharpLib.Utils.Reflection.GetDerivedTypes<Event>();
   10.49 -        }
   10.50 -
   10.51          //
   10.52          public override bool Equals(object obj)
   10.53          {
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/SharpLibEar/Object.cs	Thu Aug 18 14:35:50 2016 +0200
    11.3 @@ -0,0 +1,60 @@
    11.4 +using System;
    11.5 +using System.Collections.Generic;
    11.6 +using System.Linq;
    11.7 +using System.Text;
    11.8 +using System.Threading.Tasks;
    11.9 +
   11.10 +
   11.11 +using System;
   11.12 +using System.Collections.Generic;
   11.13 +using System.Runtime.Serialization;
   11.14 +
   11.15 +
   11.16 +namespace SharpLib.Ear
   11.17 +{
   11.18 +
   11.19 +    /// <summary>
   11.20 +    /// EAR object provides serialization support.
   11.21 +    /// It assumes most derived class is decorated with AttributeObject.
   11.22 +    /// </summary>
   11.23 +    [DataContract]
   11.24 +    [KnownType("DerivedTypes")]
   11.25 +    public abstract class Object: IComparable
   11.26 +    {
   11.27 +
   11.28 +        public string Name
   11.29 +        {
   11.30 +            //Get the name of this object attribute
   11.31 +            get { return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Name; }
   11.32 +            private set { }
   11.33 +        }
   11.34 +
   11.35 +        public string Description
   11.36 +        {
   11.37 +            //Get the description of this object attribute
   11.38 +            get { return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Description; }
   11.39 +            private set { }
   11.40 +        }
   11.41 +
   11.42 +        public virtual string Brief()
   11.43 +        {
   11.44 +            return Name;
   11.45 +        }
   11.46 +
   11.47 +        public int CompareTo(object obj)
   11.48 +        {
   11.49 +            //Sort by object name
   11.50 +            return Utils.Reflection.GetAttribute<AttributeObject>(GetType()).Name.CompareTo(obj.GetType());
   11.51 +        }
   11.52 +
   11.53 +        /// <summary>
   11.54 +        /// So that data contract knows all our types.
   11.55 +        /// </summary>
   11.56 +        /// <returns></returns>
   11.57 +        private static IEnumerable<Type> DerivedTypes()
   11.58 +        {
   11.59 +            return SharpLib.Utils.Reflection.GetDerivedTypes<Object>();
   11.60 +        }
   11.61 +
   11.62 +    }
   11.63 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/SharpLibEar/PropertyFile.cs	Thu Aug 18 14:35:50 2016 +0200
    12.3 @@ -0,0 +1,20 @@
    12.4 +using System;
    12.5 +using System.Collections.Generic;
    12.6 +using System.Linq;
    12.7 +using System.Runtime.Serialization;
    12.8 +using System.Text;
    12.9 +using System.Threading.Tasks;
   12.10 +
   12.11 +namespace SharpLib.Ear
   12.12 +{
   12.13 +    /// <summary>
   12.14 +    /// File property
   12.15 +    /// </summary>
   12.16 +    [DataContract]
   12.17 +    [AttributeObject(Id = "Property.File", Name = "File", Description = "Holds a full file path.")]
   12.18 +    public class PropertyFile : Object
   12.19 +    {
   12.20 +        [DataMember]
   12.21 +        public string FullPath { get; set; } = "";
   12.22 +    }
   12.23 +}
    13.1 --- a/SharpLibEar/SharpLibEar.csproj	Wed Aug 17 16:39:36 2016 +0200
    13.2 +++ b/SharpLibEar/SharpLibEar.csproj	Thu Aug 18 14:35:50 2016 +0200
    13.3 @@ -61,6 +61,7 @@
    13.4    <ItemGroup>
    13.5      <Compile Include="Action.cs" />
    13.6      <Compile Include="ActionCallback.cs" />
    13.7 +    <Compile Include="ActionLaunchApp.cs" />
    13.8      <Compile Include="ActionSleep.cs" />
    13.9      <Compile Include="ActionType.cs" />
   13.10      <Compile Include="AttributeObject.cs" />
   13.11 @@ -69,7 +70,9 @@
   13.12      <Compile Include="EventMonitorPowerOff.cs" />
   13.13      <Compile Include="EventMonitorPowerOn.cs" />
   13.14      <Compile Include="Manager.cs" />
   13.15 +    <Compile Include="Object.cs" />
   13.16      <Compile Include="Properties\AssemblyInfo.cs" />
   13.17 +    <Compile Include="PropertyFile.cs" />
   13.18    </ItemGroup>
   13.19    <ItemGroup>
   13.20      <ProjectReference Include="..\SharpLibUtils\SharpLibUtils.csproj">