Support for launch action and WMC HID events.
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">