RemoteControlDevice.cs
author StephaneLenclud
Sun, 15 Feb 2015 22:13:33 +0100
changeset 64 8c2380995bb7
parent 40 b3e177062849
child 66 3461ee6800e3
permissions -rw-r--r--
Adding input capabilities description to device list.
sl@0
     1
using System;
sl@0
     2
using System.Windows.Forms;
sl@0
     3
using System.Runtime.InteropServices;
sl@0
     4
using System.Diagnostics;
sl@23
     5
using System.Text;
sl@24
     6
using Microsoft.Win32.SafeHandles;
sl@23
     7
sl@8
     8
using Hid.UsageTables;
sl@9
     9
using Win32;
sl@0
    10
sl@23
    11
sl@24
    12
sl@6
    13
namespace Devices.RemoteControl
sl@0
    14
{
sl@6
    15
sl@27
    16
    public enum InputDevice
sl@27
    17
    {
sl@27
    18
        Key,
sl@27
    19
        Mouse,
sl@27
    20
        OEM
sl@27
    21
    }
sl@0
    22
sl@0
    23
sl@27
    24
    public enum RemoteControlButton
sl@27
    25
    {
sl@27
    26
        Clear,
sl@27
    27
        Down,
sl@27
    28
        Left,
sl@27
    29
        Digit0,
sl@27
    30
        Digit1,
sl@27
    31
        Digit2,
sl@27
    32
        Digit3,
sl@27
    33
        Digit4,
sl@27
    34
        Digit5,
sl@27
    35
        Digit6,
sl@27
    36
        Digit7,
sl@27
    37
        Digit8,
sl@27
    38
        Digit9,
sl@27
    39
        Enter,
sl@27
    40
        Right,
sl@27
    41
        Up,
sl@0
    42
sl@27
    43
        Back,
sl@27
    44
        ChannelDown,
sl@27
    45
        ChannelUp,
sl@27
    46
        FastForward,
sl@27
    47
        VolumeMute,
sl@27
    48
        Pause,
sl@27
    49
        Play,
sl@0
    50
        PlayPause,
sl@27
    51
        Record,
sl@27
    52
        PreviousTrack,
sl@27
    53
        Rewind,
sl@27
    54
        NextTrack,
sl@27
    55
        Stop,
sl@27
    56
        VolumeDown,
sl@27
    57
        VolumeUp,
sl@0
    58
sl@27
    59
        RecordedTV,
sl@27
    60
        Guide,
sl@27
    61
        LiveTV,
sl@27
    62
        MoreInfo,
sl@12
    63
        Print,
sl@27
    64
        DVDMenu,
sl@27
    65
        DVDAngle,
sl@27
    66
        DVDAudio,
sl@27
    67
        DVDSubtitle,
sl@27
    68
        MyMusic,
sl@27
    69
        MyPictures,
sl@27
    70
        MyVideos,
sl@27
    71
        MyTV,
sl@27
    72
        OEM1,
sl@27
    73
        OEM2,
sl@27
    74
        StandBy,
sl@27
    75
        TVJump,
sl@0
    76
sl@27
    77
        Unknown
sl@27
    78
    }
sl@0
    79
sl@0
    80
sl@27
    81
    #region RemoteControlEventArgs
sl@0
    82
sl@27
    83
    public class RemoteControlEventArgs : EventArgs
sl@27
    84
    {
sl@3
    85
        RemoteControlButton _rcb;
sl@27
    86
        InputDevice _device;
sl@30
    87
        WindowsMediaCenterRemoteControl iMceButton;
sl@19
    88
        ConsumerControl iConsumerControl;
sl@0
    89
sl@3
    90
        public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@27
    91
        {
sl@19
    92
            SetNullButtons();
sl@19
    93
            //
sl@27
    94
            _rcb = rcb;
sl@27
    95
            _device = device;
sl@27
    96
        }
sl@0
    97
sl@19
    98
        public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
sl@19
    99
        {
sl@19
   100
            SetNullButtons();
sl@19
   101
            //
sl@27
   102
            iConsumerControl = aConsumerControl;
sl@19
   103
            _device = device;
sl@19
   104
        }
sl@19
   105
sl@19
   106
sl@30
   107
        public RemoteControlEventArgs(WindowsMediaCenterRemoteControl mce, InputDevice device)
sl@3
   108
        {
sl@19
   109
            SetNullButtons();
sl@19
   110
            //
sl@27
   111
            iMceButton = mce;
sl@19
   112
            _device = device;
sl@19
   113
        }
sl@19
   114
sl@19
   115
        private void SetNullButtons()
sl@19
   116
        {
sl@19
   117
            iConsumerControl = ConsumerControl.Null;
sl@30
   118
            iMceButton = WindowsMediaCenterRemoteControl.Null;
sl@3
   119
            _rcb = RemoteControlButton.Unknown;
sl@3
   120
        }
sl@0
   121
sl@27
   122
        public RemoteControlEventArgs()
sl@27
   123
        {
sl@30
   124
            iMceButton = WindowsMediaCenterRemoteControl.Null;
sl@27
   125
            _rcb = RemoteControlButton.Unknown;
sl@27
   126
            _device = InputDevice.Key;
sl@27
   127
        }
sl@0
   128
sl@27
   129
        public RemoteControlButton Button
sl@27
   130
        {
sl@27
   131
            get { return _rcb; }
sl@27
   132
            set { _rcb = value; }
sl@27
   133
        }
sl@0
   134
sl@30
   135
        public WindowsMediaCenterRemoteControl MceButton
sl@3
   136
        {
sl@3
   137
            get { return iMceButton; }
sl@3
   138
            set { iMceButton = value; }
sl@3
   139
        }
sl@3
   140
sl@19
   141
        public ConsumerControl ConsumerControl
sl@19
   142
        {
sl@19
   143
            get { return iConsumerControl; }
sl@19
   144
            set { iConsumerControl = value; }
sl@19
   145
        }
sl@19
   146
sl@27
   147
        public InputDevice Device
sl@27
   148
        {
sl@27
   149
            get { return _device; }
sl@27
   150
            set { _device = value; }
sl@27
   151
        }
sl@27
   152
    }
sl@0
   153
sl@27
   154
    #endregion RemoteControlEventArgs
sl@0
   155
sl@0
   156
sl@27
   157
    public sealed class RemoteControlDevice
sl@27
   158
    {
sl@27
   159
        public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@27
   160
        public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0
   161
sl@19
   162
        /// <summary>
sl@19
   163
        /// Return true if the usage was processed.
sl@19
   164
        /// </summary>
sl@19
   165
        /// <param name="aUsage"></param>
sl@19
   166
        /// <returns></returns>
sl@19
   167
        public delegate bool HidUsageHandler(ushort aUsage);
sl@12
   168
sl@40
   169
        public Hid.HidHandler iHidHandler;
sl@29
   170
sl@0
   171
sl@27
   172
        //-------------------------------------------------------------
sl@27
   173
        // constructors
sl@27
   174
        //-------------------------------------------------------------
sl@0
   175
sl@27
   176
        public RemoteControlDevice(IntPtr aHWND)
sl@27
   177
        {
sl@27
   178
            // Register the input device to receive the commands from the
sl@27
   179
            // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@27
   180
            // for the vendor defined usage page.
sl@27
   181
sl@27
   182
            RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[4];
sl@0
   183
sl@21
   184
            int i = 0;
sl@30
   185
            rid[i].usUsagePage = (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl;
sl@30
   186
            rid[i].usUsage = (ushort)Hid.UsageCollectionWindowsMediaCenter.WindowsMediaCenterRemoteControl;
sl@21
   187
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   188
            rid[i].hwndTarget = aHWND;
sl@0
   189
sl@21
   190
            i++;
sl@21
   191
            rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
sl@28
   192
            rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.ConsumerControl;
sl@21
   193
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   194
            rid[i].hwndTarget = aHWND;
sl@0
   195
sl@21
   196
            i++;
sl@21
   197
            rid[i].usUsagePage = (ushort)Hid.UsagePage.Consumer;
sl@28
   198
            rid[i].usUsage = (ushort)Hid.UsageCollectionConsumer.Selection;
sl@21
   199
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   200
            rid[i].hwndTarget = aHWND;
sl@21
   201
sl@22
   202
            i++;
sl@28
   203
            rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28
   204
            rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.SystemControl;
sl@22
   205
            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@22
   206
            rid[i].hwndTarget = aHWND;
sl@21
   207
StephaneLenclud@49
   208
			//i++;
StephaneLenclud@49
   209
			rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
StephaneLenclud@49
   210
			rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.GamePad;
StephaneLenclud@49
   211
			rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
StephaneLenclud@49
   212
			rid[i].hwndTarget = aHWND;
StephaneLenclud@49
   213
sl@27
   214
            //i++;
sl@28
   215
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28
   216
            //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Keyboard;
sl@27
   217
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@27
   218
            //rid[i].hwndTarget = aHWND;
sl@21
   219
sl@21
   220
            //i++;
sl@28
   221
            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControls;
sl@28
   222
            //rid[i].usUsage = (ushort)Hid.UsageCollectionGenericDesktop.Mouse;
sl@21
   223
            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
sl@21
   224
            //rid[i].hwndTarget = aHWND;
sl@21
   225
sl@0
   226
sl@29
   227
            iHidHandler = new Hid.HidHandler(rid);
sl@29
   228
            if (!iHidHandler.IsRegistered)
sl@27
   229
            {
sl@29
   230
                Debug.WriteLine("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
sl@27
   231
            }
sl@29
   232
            iHidHandler.OnHidEvent += HandleHidEvent;
sl@27
   233
        }
sl@0
   234
sl@0
   235
sl@27
   236
        //-------------------------------------------------------------
sl@27
   237
        // methods
sl@27
   238
        //-------------------------------------------------------------
sl@0
   239
sl@27
   240
        public void ProcessMessage(Message message)
sl@27
   241
        {
sl@27
   242
            switch (message.Msg)
sl@27
   243
            {
sl@27
   244
                case Const.WM_KEYDOWN:
sl@15
   245
                    ProcessKeyDown(message.WParam);
sl@27
   246
                    break;
sl@15
   247
                case Const.WM_INPUT:
sl@19
   248
                    //Returning zero means we processed that message.
sl@19
   249
                    message.Result = new IntPtr(0);
sl@27
   250
                    ProcessInputCommand(ref message);
sl@27
   251
                    break;
sl@27
   252
            }
sl@0
   253
sl@27
   254
        }
sl@0
   255
sl@0
   256
sl@27
   257
        //-------------------------------------------------------------
sl@27
   258
        // methods (helpers)
sl@27
   259
        //-------------------------------------------------------------
sl@0
   260
sl@27
   261
        private void ProcessKeyDown(IntPtr wParam)
sl@27
   262
        {
sl@27
   263
            RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   264
sl@15
   265
            switch (wParam.ToInt32())
sl@27
   266
            {
sl@27
   267
                case (int)Keys.Escape:
sl@27
   268
                    rcb = RemoteControlButton.Clear;
sl@22
   269
                    break;
sl@22
   270
                case (int)Keys.Up:
sl@22
   271
                    rcb = RemoteControlButton.Up;
sl@22
   272
                    break;
sl@27
   273
                case (int)Keys.Down:
sl@27
   274
                    rcb = RemoteControlButton.Down;
sl@27
   275
                    break;
sl@27
   276
                case (int)Keys.Left:
sl@27
   277
                    rcb = RemoteControlButton.Left;
sl@22
   278
                    break;
sl@22
   279
                case (int)Keys.Right:
sl@22
   280
                    rcb = RemoteControlButton.Right;
sl@22
   281
                    break;
sl@22
   282
                case (int)Keys.Enter:
sl@22
   283
                    rcb = RemoteControlButton.Enter;
sl@22
   284
                    break;
sl@27
   285
                case (int)Keys.D0:
sl@27
   286
                    rcb = RemoteControlButton.Digit0;
sl@22
   287
                    break;
sl@27
   288
                case (int)Keys.D1:
sl@27
   289
                    rcb = RemoteControlButton.Digit1;
sl@27
   290
                    break;
sl@27
   291
                case (int)Keys.D2:
sl@27
   292
                    rcb = RemoteControlButton.Digit2;
sl@27
   293
                    break;
sl@27
   294
                case (int)Keys.D3:
sl@27
   295
                    rcb = RemoteControlButton.Digit3;
sl@27
   296
                    break;
sl@27
   297
                case (int)Keys.D4:
sl@27
   298
                    rcb = RemoteControlButton.Digit4;
sl@27
   299
                    break;
sl@27
   300
                case (int)Keys.D5:
sl@27
   301
                    rcb = RemoteControlButton.Digit5;
sl@27
   302
                    break;
sl@27
   303
                case (int)Keys.D6:
sl@27
   304
                    rcb = RemoteControlButton.Digit6;
sl@27
   305
                    break;
sl@27
   306
                case (int)Keys.D7:
sl@27
   307
                    rcb = RemoteControlButton.Digit7;
sl@27
   308
                    break;
sl@27
   309
                case (int)Keys.D8:
sl@27
   310
                    rcb = RemoteControlButton.Digit8;
sl@27
   311
                    break;
sl@27
   312
                case (int)Keys.D9:
sl@27
   313
                    rcb = RemoteControlButton.Digit9;
sl@27
   314
                    break;
sl@27
   315
            }
sl@0
   316
sl@22
   317
            if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@22
   318
            {
sl@22
   319
                Debug.WriteLine("KeyDown: " + rcb.ToString());
sl@20
   320
                this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
sl@22
   321
            }
sl@27
   322
        }
sl@0
   323
sl@0
   324
sl@12
   325
        /// <summary>
sl@12
   326
        /// 
sl@12
   327
        /// </summary>
sl@12
   328
        /// <param name="aUsage"></param>
sl@19
   329
        private bool HidConsumerDeviceHandler(ushort aUsage)
sl@12
   330
        {
sl@12
   331
            if (aUsage == 0)
sl@12
   332
            {
sl@12
   333
                //Just skip those
sl@19
   334
                return false;
sl@12
   335
            }
sl@12
   336
sl@12
   337
            if (Enum.IsDefined(typeof(ConsumerControl), aUsage) && aUsage != 0) //Our button is a known consumer control
sl@12
   338
            {
sl@12
   339
                if (this.ButtonPressed != null)
sl@12
   340
                {
sl@19
   341
                    return this.ButtonPressed(this, new RemoteControlEventArgs((ConsumerControl)aUsage, InputDevice.OEM));
sl@12
   342
                }
sl@19
   343
                return false;
sl@12
   344
            }
sl@12
   345
            else
sl@12
   346
            {
sl@12
   347
                Debug.WriteLine("Unknown Consumer Control!");
sl@19
   348
                return false;
sl@12
   349
            }
sl@12
   350
        }
sl@12
   351
sl@12
   352
        /// <summary>
sl@12
   353
        /// 
sl@12
   354
        /// </summary>
sl@12
   355
        /// <param name="aUsage"></param>
sl@19
   356
        private bool HidMceRemoteHandler(ushort aUsage)
sl@12
   357
        {
sl@12
   358
            if (aUsage == 0)
sl@12
   359
            {
sl@12
   360
                //Just skip those
sl@19
   361
                return false;
sl@12
   362
            }
sl@12
   363
sl@12
   364
sl@30
   365
            if (Enum.IsDefined(typeof(WindowsMediaCenterRemoteControl), aUsage) && aUsage != 0) //Our button is a known MCE button
sl@12
   366
            {
sl@12
   367
                if (this.ButtonPressed != null)
sl@12
   368
                {
sl@30
   369
                    return this.ButtonPressed(this, new RemoteControlEventArgs((WindowsMediaCenterRemoteControl)aUsage, InputDevice.OEM));
sl@12
   370
                }
sl@19
   371
                return false;
sl@12
   372
            }
sl@12
   373
            else
sl@12
   374
            {
sl@12
   375
                Debug.WriteLine("Unknown MCE button!");
sl@19
   376
                return false;
sl@12
   377
            }
sl@12
   378
        }
sl@12
   379
sl@29
   380
        /// <summary>
sl@29
   381
        /// 
sl@29
   382
        /// </summary>
sl@29
   383
        /// <param name="message"></param>
sl@27
   384
        private void ProcessInputCommand(ref Message message)
sl@27
   385
        {
sl@15
   386
            //We received a WM_INPUT message
sl@7
   387
            Debug.WriteLine("================WM_INPUT================");
sl@6
   388
sl@29
   389
            iHidHandler.ProcessInput(message);
sl@27
   390
sl@29
   391
        }
sl@0
   392
sl@29
   393
        /// <summary>
sl@29
   394
        /// 
sl@29
   395
        /// </summary>
sl@29
   396
        /// <param name="aSender"></param>
sl@29
   397
        /// <param name="aHidEvent"></param>
sl@29
   398
        void HandleHidEvent(object aSender, Hid.HidEvent aHidEvent)
sl@29
   399
        {
sl@27
   400
            HidUsageHandler usagePageHandler = null;
sl@27
   401
sl@27
   402
            //Check if this an MCE remote HID message
sl@30
   403
            if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.WindowsMediaCenterRemoteControl && aHidEvent.UsageCollection == (ushort)Hid.UsageCollectionWindowsMediaCenter.WindowsMediaCenterRemoteControl)
sl@10
   404
            {
sl@27
   405
                usagePageHandler = HidMceRemoteHandler;
sl@27
   406
            }
sl@27
   407
            //Check if this is a consumer control HID message
sl@29
   408
            else if (aHidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && aHidEvent.UsageCollection == (ushort)Hid.UsageCollectionConsumer.ConsumerControl)
sl@27
   409
            {
sl@27
   410
                usagePageHandler = HidConsumerDeviceHandler;
sl@27
   411
            }
sl@27
   412
            //Unknown HID message
sl@27
   413
            else
sl@27
   414
            {
sl@27
   415
                Debug.WriteLine("Unknown HID message.");
sl@27
   416
                return;
sl@27
   417
            }
sl@6
   418
sl@29
   419
            foreach (ushort usage in aHidEvent.Usages)
sl@27
   420
            {
sl@27
   421
                usagePageHandler(usage);
sl@27
   422
            }
sl@27
   423
        }
sl@27
   424
    }
sl@27
   425
}
sl@23
   426