RemoteControlDevice.cs
author sl
Thu, 06 Nov 2014 21:57:53 +0100
changeset 8 0d0c62b1df48
parent 7 5ecebf1bd397
child 9 94850bfc12b5
permissions -rw-r--r--
Getting our HID consts organized. Adding some consumer controls.
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@8
     5
using Hid.UsageTables;
sl@0
     6
sl@6
     7
namespace Devices.RemoteControl
sl@0
     8
{
sl@6
     9
sl@8
    10
 
sl@6
    11
sl@6
    12
sl@0
    13
	public enum InputDevice
sl@0
    14
	{
sl@0
    15
		Key,
sl@0
    16
		Mouse,
sl@0
    17
		OEM
sl@0
    18
	}
sl@0
    19
sl@0
    20
sl@0
    21
	public enum RemoteControlButton
sl@0
    22
	{
sl@0
    23
		Clear,
sl@0
    24
		Down,
sl@0
    25
		Left,
sl@0
    26
		Digit0,
sl@0
    27
		Digit1,
sl@0
    28
		Digit2,
sl@0
    29
		Digit3,
sl@0
    30
		Digit4,
sl@0
    31
		Digit5,
sl@0
    32
		Digit6,
sl@0
    33
		Digit7,
sl@0
    34
		Digit8,
sl@0
    35
		Digit9,
sl@0
    36
		Enter,
sl@0
    37
		Right,
sl@0
    38
		Up,
sl@0
    39
sl@0
    40
		Back,
sl@0
    41
		ChannelDown,
sl@0
    42
		ChannelUp,
sl@0
    43
		FastForward,
sl@0
    44
		VolumeMute,
sl@0
    45
		Pause,
sl@0
    46
		Play,
sl@0
    47
        PlayPause,
sl@0
    48
		Record,
sl@0
    49
		PreviousTrack,
sl@0
    50
		Rewind,
sl@0
    51
		NextTrack,
sl@0
    52
		Stop,
sl@0
    53
		VolumeDown,
sl@0
    54
		VolumeUp,
sl@0
    55
sl@0
    56
		RecordedTV,
sl@0
    57
		Guide,
sl@0
    58
		LiveTV,
sl@0
    59
		Details,
sl@0
    60
		DVDMenu,
sl@0
    61
		DVDAngle,
sl@0
    62
		DVDAudio,
sl@0
    63
		DVDSubtitle,
sl@0
    64
		MyMusic,
sl@0
    65
		MyPictures,
sl@0
    66
		MyVideos,
sl@0
    67
		MyTV,
sl@0
    68
		OEM1,
sl@0
    69
		OEM2,
sl@0
    70
		StandBy,
sl@0
    71
		TVJump,
sl@0
    72
sl@0
    73
		Unknown
sl@0
    74
	}
sl@0
    75
sl@0
    76
sl@0
    77
	#region RemoteControlEventArgs
sl@0
    78
sl@0
    79
	public class RemoteControlEventArgs : EventArgs
sl@0
    80
	{
sl@3
    81
        RemoteControlButton _rcb;
sl@0
    82
		InputDevice _device;
sl@3
    83
        MceButton iMceButton;
sl@0
    84
sl@3
    85
        public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@0
    86
		{
sl@3
    87
            iMceButton = MceButton.Null;
sl@0
    88
			_rcb = rcb;
sl@0
    89
			_device = device;
sl@0
    90
		}
sl@0
    91
sl@3
    92
        public RemoteControlEventArgs(MceButton mce, InputDevice device)
sl@3
    93
        {
sl@3
    94
            iMceButton = mce;
sl@3
    95
            _rcb = RemoteControlButton.Unknown;
sl@3
    96
            _device = device;
sl@3
    97
        }
sl@0
    98
sl@0
    99
		public RemoteControlEventArgs()
sl@0
   100
		{
sl@3
   101
            iMceButton = MceButton.Null;
sl@0
   102
			_rcb = RemoteControlButton.Unknown;
sl@0
   103
			_device = InputDevice.Key;
sl@0
   104
		}
sl@0
   105
sl@0
   106
		public RemoteControlButton Button
sl@0
   107
		{
sl@0
   108
			get { return _rcb;  }
sl@0
   109
			set { _rcb = value; }
sl@0
   110
		}
sl@0
   111
sl@3
   112
        public MceButton MceButton
sl@3
   113
        {
sl@3
   114
            get { return iMceButton; }
sl@3
   115
            set { iMceButton = value; }
sl@3
   116
        }
sl@3
   117
sl@0
   118
		public InputDevice Device
sl@0
   119
		{
sl@0
   120
			get { return _device;  }
sl@0
   121
			set { _device = value; }
sl@0
   122
		}
sl@0
   123
	}
sl@0
   124
sl@0
   125
	#endregion RemoteControlEventArgs
sl@0
   126
sl@0
   127
sl@0
   128
	public sealed class RemoteControlDevice
sl@0
   129
	{
sl@0
   130
sl@0
   131
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   132
		internal struct RAWINPUTDEVICE
sl@0
   133
		{
sl@0
   134
			[MarshalAs(UnmanagedType.U2)]
sl@0
   135
			public ushort usUsagePage;
sl@0
   136
			[MarshalAs(UnmanagedType.U2)]
sl@0
   137
			public ushort usUsage;
sl@0
   138
			[MarshalAs(UnmanagedType.U4)]
sl@0
   139
			public int	 dwFlags;
sl@0
   140
			public IntPtr hwndTarget;
sl@0
   141
		}
sl@0
   142
sl@0
   143
sl@0
   144
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   145
		internal struct RAWINPUTHEADER
sl@0
   146
		{
sl@0
   147
			[MarshalAs(UnmanagedType.U4)]
sl@0
   148
			public int dwType;
sl@0
   149
			[MarshalAs(UnmanagedType.U4)]
sl@0
   150
			public int dwSize;
sl@0
   151
            public IntPtr hDevice;
sl@0
   152
			[MarshalAs(UnmanagedType.U4)]
sl@0
   153
			public int wParam;
sl@0
   154
		}
sl@0
   155
sl@0
   156
sl@0
   157
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   158
		internal struct RAWHID
sl@0
   159
		{
sl@0
   160
			[MarshalAs(UnmanagedType.U4)]
sl@0
   161
			public int dwSizeHid;
sl@0
   162
			[MarshalAs(UnmanagedType.U4)]
sl@0
   163
			public int dwCount;
sl@0
   164
            //
sl@0
   165
            //BYTE  bRawData[1];
sl@0
   166
		}
sl@0
   167
sl@0
   168
sl@0
   169
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   170
		internal struct BUTTONSSTR
sl@0
   171
		{
sl@0
   172
			[MarshalAs(UnmanagedType.U2)]
sl@0
   173
			public ushort usButtonFlags;
sl@0
   174
			[MarshalAs(UnmanagedType.U2)]
sl@0
   175
			public ushort usButtonData;
sl@0
   176
		}
sl@0
   177
sl@0
   178
sl@0
   179
        [StructLayout(LayoutKind.Explicit, Pack = 1)]
sl@0
   180
		internal struct RAWMOUSE
sl@0
   181
		{
sl@0
   182
			[MarshalAs(UnmanagedType.U2)]
sl@0
   183
			[FieldOffset (0)] public ushort usFlags;
sl@0
   184
			[MarshalAs(UnmanagedType.U4)]
sl@0
   185
			[FieldOffset (4)] public uint ulButtons;
sl@0
   186
			[FieldOffset (4)] public BUTTONSSTR buttonsStr;
sl@0
   187
			[MarshalAs(UnmanagedType.U4)]
sl@0
   188
			[FieldOffset (8)] public uint ulRawButtons;
sl@0
   189
            [MarshalAs(UnmanagedType.U4)]
sl@0
   190
            [FieldOffset (12)] public int lLastX;
sl@0
   191
            [MarshalAs(UnmanagedType.U4)]
sl@0
   192
            [FieldOffset (16)] public int lLastY;
sl@0
   193
			[MarshalAs(UnmanagedType.U4)]
sl@0
   194
			[FieldOffset (20)] public uint ulExtraInformation;
sl@0
   195
		}
sl@0
   196
sl@0
   197
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   198
		internal struct RAWKEYBOARD
sl@0
   199
		{
sl@0
   200
			[MarshalAs(UnmanagedType.U2)]
sl@0
   201
			public ushort MakeCode;
sl@0
   202
			[MarshalAs(UnmanagedType.U2)]
sl@0
   203
			public ushort Flags;
sl@0
   204
			[MarshalAs(UnmanagedType.U2)]
sl@0
   205
			public ushort Reserved;
sl@0
   206
			[MarshalAs(UnmanagedType.U2)]
sl@0
   207
			public ushort VKey;
sl@0
   208
			[MarshalAs(UnmanagedType.U4)]
sl@0
   209
			public uint Message;
sl@0
   210
			[MarshalAs(UnmanagedType.U4)]
sl@0
   211
			public uint ExtraInformation;
sl@0
   212
		}
sl@0
   213
sl@0
   214
sl@0
   215
		[StructLayout(LayoutKind.Explicit, Pack=1)]
sl@0
   216
		internal struct RAWINPUT
sl@0
   217
		{
sl@0
   218
			[FieldOffset  (0)] public RAWINPUTHEADER header;
sl@0
   219
			[FieldOffset (16)] public RAWMOUSE mouse;
sl@0
   220
			[FieldOffset (16)] public RAWKEYBOARD keyboard;
sl@0
   221
			[FieldOffset (16)] public RAWHID hid;
sl@0
   222
		}
sl@0
   223
sl@0
   224
sl@6
   225
        [StructLayout(LayoutKind.Sequential, Pack=1)]
sl@6
   226
        internal struct RID_DEVICE_INFO_MOUSE
sl@6
   227
		{
sl@6
   228
            public uint dwId;
sl@6
   229
            public uint dwNumberOfButtons;
sl@6
   230
            public uint dwSampleRate;
sl@6
   231
            public bool fHasHorizontalWheel;
sl@6
   232
		}
sl@6
   233
sl@6
   234
sl@6
   235
        [StructLayout(LayoutKind.Sequential, Pack=1)]
sl@6
   236
        internal struct RID_DEVICE_INFO_KEYBOARD
sl@6
   237
		{
sl@6
   238
            public uint dwType;
sl@6
   239
            public uint dwSubType;
sl@6
   240
            public uint dwKeyboardMode;
sl@6
   241
            public uint dwNumberOfFunctionKeys;
sl@6
   242
            public uint dwNumberOfIndicators;
sl@6
   243
            public uint dwNumberOfKeysTotal;
sl@6
   244
        }
sl@6
   245
sl@6
   246
        [StructLayout(LayoutKind.Sequential, Pack=1)]
sl@6
   247
        internal struct RID_DEVICE_INFO_HID
sl@6
   248
		{
sl@6
   249
            public uint dwVendorId;
sl@6
   250
            public uint dwProductId;
sl@6
   251
            public uint dwVersionNumber;
sl@6
   252
            public ushort usUsagePage;
sl@6
   253
            public ushort usUsage;
sl@6
   254
        }
sl@6
   255
sl@6
   256
        [StructLayout(LayoutKind.Explicit, Pack=1)]
sl@6
   257
        internal struct RID_DEVICE_INFO
sl@6
   258
		{
sl@6
   259
            [FieldOffset(0)]
sl@6
   260
            public uint cbSize;
sl@6
   261
            [FieldOffset(4)]
sl@6
   262
            public uint dwType;
sl@6
   263
            [FieldOffset(8)]
sl@6
   264
            public RID_DEVICE_INFO_MOUSE mouse;
sl@6
   265
            [FieldOffset(8)]
sl@6
   266
            public RID_DEVICE_INFO_KEYBOARD keyboard;
sl@6
   267
            [FieldOffset(8)]
sl@6
   268
            public RID_DEVICE_INFO_HID hid;
sl@6
   269
		}
sl@6
   270
sl@6
   271
sl@6
   272
sl@0
   273
		[DllImport("User32.dll")]
sl@0
   274
		extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);
sl@0
   275
sl@0
   276
		[DllImport("User32.dll")]
sl@0
   277
		extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);
sl@0
   278
sl@6
   279
   		[DllImport("User32.dll", SetLastError=true)]
sl@6
   280
		extern static int GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
sl@4
   281
sl@0
   282
sl@0
   283
		private const int WM_KEYDOWN	= 0x0100;
sl@0
   284
		private const int WM_APPCOMMAND	= 0x0319;
sl@0
   285
		private const int WM_INPUT		= 0x00FF;
sl@0
   286
sl@0
   287
		private const int APPCOMMAND_BROWSER_BACKWARD   = 1;
sl@0
   288
		private const int APPCOMMAND_VOLUME_MUTE        = 8;
sl@0
   289
		private const int APPCOMMAND_VOLUME_DOWN        = 9;
sl@0
   290
		private const int APPCOMMAND_VOLUME_UP          = 10;
sl@0
   291
		private const int APPCOMMAND_MEDIA_NEXTTRACK    = 11;
sl@0
   292
		private const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12;
sl@0
   293
		private const int APPCOMMAND_MEDIA_STOP         = 13;
sl@0
   294
		private const int APPCOMMAND_MEDIA_PLAY_PAUSE   = 14;
sl@0
   295
		private const int APPCOMMAND_MEDIA_PLAY         = 46;
sl@0
   296
		private const int APPCOMMAND_MEDIA_PAUSE        = 47;
sl@0
   297
		private const int APPCOMMAND_MEDIA_RECORD       = 48;
sl@0
   298
		private const int APPCOMMAND_MEDIA_FAST_FORWARD = 49;
sl@0
   299
		private const int APPCOMMAND_MEDIA_REWIND       = 50;
sl@0
   300
		private const int APPCOMMAND_MEDIA_CHANNEL_UP   = 51;
sl@0
   301
		private const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52;
sl@0
   302
sl@0
   303
		private const int RID_INPUT						= 0x10000003;
sl@0
   304
		private const int RID_HEADER					= 0x10000005;
sl@0
   305
sl@0
   306
		private const int FAPPCOMMAND_MASK				= 0xF000;
sl@0
   307
		private const int FAPPCOMMAND_MOUSE				= 0x8000;
sl@0
   308
		private const int FAPPCOMMAND_KEY				= 0;
sl@0
   309
		private const int FAPPCOMMAND_OEM				= 0x1000;
sl@0
   310
sl@6
   311
        /// <summary>
sl@6
   312
        /// GetRawInputDeviceInfo pData points to a string that contains the device name.
sl@6
   313
        /// </summary>
sl@6
   314
        public const uint RIDI_DEVICENAME = 0x20000007;
sl@6
   315
        /// <summary>
sl@6
   316
        /// GetRawInputDeviceInfo For this uiCommand only, the value in pcbSize is the character count (not the byte count).
sl@6
   317
        /// </summary>
sl@6
   318
        public const uint RIDI_DEVICEINFO = 0x2000000b;
sl@6
   319
        /// <summary>
sl@6
   320
        /// GetRawInputDeviceInfo pData points to an RID_DEVICE_INFO structure.
sl@6
   321
        /// </summary>
sl@6
   322
        public const uint RIDI_PREPARSEDDATA = 0x20000005;
sl@6
   323
sl@6
   324
sl@6
   325
        /// <summary>
sl@6
   326
        /// Data comes from a mouse.
sl@6
   327
        /// </summary>
sl@6
   328
        public const uint RIM_TYPEMOUSE = 0;
sl@6
   329
        /// <summary>
sl@6
   330
        /// Data comes from a keyboard.
sl@6
   331
        /// </summary>
sl@6
   332
        public const uint RIM_TYPEKEYBOARD = 1;
sl@6
   333
        /// <summary>
sl@6
   334
        /// Data comes from an HID that is not a keyboard or a mouse.
sl@6
   335
        /// </summary>
sl@6
   336
        public const uint RIM_TYPEHID = 2;
sl@6
   337
sl@6
   338
sl@6
   339
sl@6
   340
sl@6
   341
sl@0
   342
		public delegate void RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@0
   343
		public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0
   344
sl@0
   345
sl@0
   346
		//-------------------------------------------------------------
sl@0
   347
		// constructors
sl@0
   348
		//-------------------------------------------------------------
sl@0
   349
sl@0
   350
		public RemoteControlDevice()
sl@0
   351
		{
sl@0
   352
			// Register the input device to receive the commands from the
sl@0
   353
			// remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@0
   354
			// for the vendor defined usage page.
sl@0
   355
sl@0
   356
			RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[3];
sl@0
   357
sl@0
   358
			rid[0].usUsagePage = 0xFFBC;
sl@0
   359
			rid[0].usUsage = 0x88;
sl@0
   360
			rid[0].dwFlags = 0;
sl@0
   361
sl@0
   362
			rid[1].usUsagePage = 0x0C;
sl@0
   363
			rid[1].usUsage = 0x01;
sl@0
   364
			rid[1].dwFlags = 0;
sl@0
   365
sl@0
   366
			rid[2].usUsagePage = 0x0C;
sl@0
   367
			rid[2].usUsage = 0x80;
sl@0
   368
			rid[2].dwFlags = 0;
sl@0
   369
sl@0
   370
			if (!RegisterRawInputDevices(rid,
sl@0
   371
				(uint) rid.Length,
sl@0
   372
				(uint) Marshal.SizeOf(rid[0]))
sl@0
   373
				)
sl@0
   374
			{
sl@0
   375
				throw new ApplicationException("Failed to register raw input devices.");
sl@0
   376
			}
sl@0
   377
		}
sl@0
   378
sl@0
   379
sl@0
   380
		//-------------------------------------------------------------
sl@0
   381
		// methods
sl@0
   382
		//-------------------------------------------------------------
sl@0
   383
sl@0
   384
		public void ProcessMessage(Message message)
sl@0
   385
		{
sl@0
   386
			int param;
sl@0
   387
sl@0
   388
			switch (message.Msg)
sl@0
   389
			{
sl@0
   390
				case WM_KEYDOWN:
sl@0
   391
					param = message.WParam.ToInt32();
sl@0
   392
					ProcessKeyDown(param);
sl@0
   393
					break;
sl@0
   394
				case WM_APPCOMMAND:
sl@0
   395
					param = message.LParam.ToInt32();
sl@0
   396
					ProcessAppCommand(param);
sl@0
   397
					break;
sl@0
   398
				case WM_INPUT:
sl@0
   399
					ProcessInputCommand(ref message);
sl@0
   400
                    message.Result = new IntPtr(0);
sl@0
   401
					break;
sl@0
   402
			}
sl@0
   403
sl@0
   404
		}
sl@0
   405
sl@0
   406
sl@0
   407
		//-------------------------------------------------------------
sl@0
   408
		// methods (helpers)
sl@0
   409
		//-------------------------------------------------------------
sl@0
   410
sl@0
   411
		private void ProcessKeyDown(int param)
sl@0
   412
		{
sl@0
   413
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   414
sl@0
   415
			switch (param)
sl@0
   416
			{
sl@0
   417
				case (int) Keys.Escape:
sl@0
   418
					rcb = RemoteControlButton.Clear;
sl@0
   419
					break;
sl@0
   420
				case (int) Keys.Down:
sl@0
   421
					rcb = RemoteControlButton.Down;
sl@0
   422
					break;
sl@0
   423
				case (int) Keys.Left:
sl@0
   424
					rcb = RemoteControlButton.Left;
sl@0
   425
					break;
sl@0
   426
				case (int) Keys.D0:
sl@0
   427
					rcb = RemoteControlButton.Digit0;
sl@0
   428
					break;
sl@0
   429
				case (int) Keys.D1:
sl@0
   430
					rcb = RemoteControlButton.Digit1;
sl@0
   431
					break;
sl@0
   432
				case (int) Keys.D2:
sl@0
   433
					rcb = RemoteControlButton.Digit2;
sl@0
   434
					break;
sl@0
   435
				case (int) Keys.D3:
sl@0
   436
					rcb = RemoteControlButton.Digit3;
sl@0
   437
					break;
sl@0
   438
				case (int) Keys.D4:
sl@0
   439
					rcb = RemoteControlButton.Digit4;
sl@0
   440
					break;
sl@0
   441
				case (int) Keys.D5:
sl@0
   442
					rcb = RemoteControlButton.Digit5;
sl@0
   443
					break;
sl@0
   444
				case (int) Keys.D6:
sl@0
   445
					rcb = RemoteControlButton.Digit6;
sl@0
   446
					break;
sl@0
   447
				case (int) Keys.D7:
sl@0
   448
					rcb = RemoteControlButton.Digit7;
sl@0
   449
					break;
sl@0
   450
				case (int) Keys.D8:
sl@0
   451
					rcb = RemoteControlButton.Digit8;
sl@0
   452
					break;
sl@0
   453
				case (int) Keys.D9:
sl@0
   454
					rcb = RemoteControlButton.Digit9;
sl@0
   455
					break;
sl@0
   456
				case (int) Keys.Enter:
sl@0
   457
					rcb = RemoteControlButton.Enter;
sl@0
   458
					break;
sl@0
   459
				case (int) Keys.Right:
sl@0
   460
					rcb = RemoteControlButton.Right;
sl@0
   461
					break;
sl@0
   462
				case (int) Keys.Up:
sl@0
   463
					rcb = RemoteControlButton.Up;
sl@0
   464
					break;
sl@0
   465
			}
sl@0
   466
sl@0
   467
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@0
   468
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(param)));
sl@0
   469
		}
sl@0
   470
sl@0
   471
sl@0
   472
		private void ProcessAppCommand(int param)
sl@0
   473
		{
sl@0
   474
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   475
sl@0
   476
			int cmd	= (int) (((ushort) (param >> 16)) & ~FAPPCOMMAND_MASK);
sl@0
   477
sl@0
   478
			switch (cmd)
sl@0
   479
			{
sl@0
   480
				case APPCOMMAND_BROWSER_BACKWARD:
sl@0
   481
					rcb = RemoteControlButton.Back;
sl@0
   482
					break;
sl@0
   483
				case APPCOMMAND_MEDIA_CHANNEL_DOWN:
sl@0
   484
					rcb = RemoteControlButton.ChannelDown;
sl@0
   485
					break;
sl@0
   486
				case APPCOMMAND_MEDIA_CHANNEL_UP:
sl@0
   487
					rcb = RemoteControlButton.ChannelUp;
sl@0
   488
					break;
sl@0
   489
				case APPCOMMAND_MEDIA_FAST_FORWARD:
sl@0
   490
					rcb = RemoteControlButton.FastForward;
sl@0
   491
					break;
sl@0
   492
				case APPCOMMAND_VOLUME_MUTE:
sl@0
   493
					rcb = RemoteControlButton.VolumeMute;
sl@0
   494
					break;
sl@0
   495
				case APPCOMMAND_MEDIA_PAUSE:
sl@0
   496
					rcb = RemoteControlButton.Pause;
sl@0
   497
					break;
sl@0
   498
				case APPCOMMAND_MEDIA_PLAY:
sl@0
   499
					rcb = RemoteControlButton.Play;
sl@0
   500
					break;
sl@0
   501
                case APPCOMMAND_MEDIA_PLAY_PAUSE:
sl@0
   502
                    rcb = RemoteControlButton.PlayPause;
sl@0
   503
                    break;
sl@0
   504
				case APPCOMMAND_MEDIA_RECORD:
sl@0
   505
					rcb = RemoteControlButton.Record;
sl@0
   506
					break;
sl@0
   507
				case APPCOMMAND_MEDIA_PREVIOUSTRACK:
sl@0
   508
					rcb = RemoteControlButton.PreviousTrack;
sl@0
   509
					break;
sl@0
   510
				case APPCOMMAND_MEDIA_REWIND:
sl@0
   511
					rcb = RemoteControlButton.Rewind;
sl@0
   512
					break;
sl@0
   513
				case APPCOMMAND_MEDIA_NEXTTRACK:
sl@0
   514
					rcb = RemoteControlButton.NextTrack;
sl@0
   515
					break;
sl@0
   516
				case APPCOMMAND_MEDIA_STOP:
sl@0
   517
					rcb = RemoteControlButton.Stop;
sl@0
   518
					break;
sl@0
   519
				case APPCOMMAND_VOLUME_DOWN:
sl@0
   520
					rcb = RemoteControlButton.VolumeDown;
sl@0
   521
					break;
sl@0
   522
				case APPCOMMAND_VOLUME_UP:
sl@0
   523
					rcb = RemoteControlButton.VolumeUp;
sl@0
   524
					break;
sl@0
   525
			}
sl@0
   526
sl@0
   527
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@0
   528
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(param)));
sl@0
   529
		}
sl@0
   530
sl@0
   531
sl@0
   532
		private void ProcessInputCommand(ref Message message)
sl@0
   533
		{
sl@7
   534
            Debug.WriteLine("================WM_INPUT================");
sl@6
   535
sl@0
   536
			uint dwSize = 0;
sl@0
   537
sl@0
   538
            uint sizeOfHeader=(uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
sl@0
   539
sl@0
   540
            //Get the size of our raw input data.
sl@0
   541
			GetRawInputData(message.LParam,	RID_INPUT, IntPtr.Zero,	ref dwSize,	sizeOfHeader);
sl@0
   542
sl@0
   543
            //Allocate a large enough buffer
sl@6
   544
			IntPtr rawInputBuffer = Marshal.AllocHGlobal((int) dwSize);
sl@0
   545
			try
sl@0
   546
			{
sl@6
   547
				if(rawInputBuffer == IntPtr.Zero)
sl@0
   548
					return;
sl@0
   549
sl@0
   550
                //Now read our RAWINPUT data
sl@6
   551
				if (GetRawInputData(message.LParam,	RID_INPUT, rawInputBuffer, ref dwSize, (uint) Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
sl@0
   552
				{
sl@0
   553
					return;
sl@0
   554
				}
sl@0
   555
sl@0
   556
                //Cast our buffer
sl@6
   557
                RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
sl@6
   558
sl@6
   559
                //Get Device Info
sl@6
   560
                uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
sl@6
   561
                IntPtr deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
sl@6
   562
sl@6
   563
                int res = GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
sl@6
   564
                if (res <= 0)
sl@6
   565
                {
sl@6
   566
                    Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
sl@6
   567
                    return;
sl@6
   568
                }
sl@6
   569
sl@6
   570
                //Cast our buffer
sl@6
   571
                RID_DEVICE_INFO deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
sl@6
   572
sl@6
   573
                //Check type of input device and quite if we don't like it
sl@6
   574
                switch (deviceInfo.dwType)
sl@6
   575
                {
sl@6
   576
                    case RIM_TYPEHID:
sl@6
   577
                        Debug.WriteLine("WM_INPUT source device is HID.");
sl@6
   578
                        break;
sl@6
   579
                    case RIM_TYPEMOUSE:
sl@6
   580
                        Debug.WriteLine("WM_INPUT source device is Mouse.");
sl@6
   581
                        return;
sl@6
   582
                    case RIM_TYPEKEYBOARD:
sl@6
   583
                        Debug.WriteLine("WM_INPUT source device is Keyboard.");
sl@6
   584
                        return;
sl@6
   585
                    default:
sl@6
   586
                        Debug.WriteLine("WM_INPUT source device is Unknown.");
sl@6
   587
                        return;
sl@6
   588
                }
sl@6
   589
sl@6
   590
                //Get Usage Page and Usage
sl@6
   591
                Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
sl@0
   592
sl@0
   593
                //Check that our raw input is HID
sl@0
   594
                if (raw.header.dwType == RIM_TYPEHID && raw.hid.dwSizeHid>0)
sl@0
   595
				{
sl@0
   596
                    //Allocate a buffer for one HID message
sl@0
   597
					byte[] bRawData = new byte[raw.hid.dwSizeHid];
sl@0
   598
sl@0
   599
                    //Compute the address from which to copy our HID message
sl@0
   600
                    int pRawData = 0;
sl@0
   601
                    unsafe
sl@0
   602
                    {
sl@6
   603
                        byte* source = (byte*)rawInputBuffer;
sl@0
   604
                        source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID);
sl@0
   605
                        pRawData = (int)source;
sl@0
   606
                    }
sl@0
   607
sl@4
   608
                    //Copy HID message into our buffer
sl@0
   609
                    Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizeHid);
sl@4
   610
                    //bRawData[0] //Not sure what's the meaning of the code at offset 0
sl@4
   611
                    //TODO: check size before access
sl@0
   612
                    int rawData = bRawData[1]; //Get button code
sl@4
   613
                    //Print HID codes in our debug output
sl@6
   614
                    string hidDump = "HID " + raw.hid.dwCount + "/" + raw.hid.dwSizeHid + ":";
sl@6
   615
                    foreach (byte b in bRawData)
sl@6
   616
                    {
sl@6
   617
                        hidDump += b.ToString("X2");
sl@6
   618
                    }
sl@6
   619
                    Debug.WriteLine(hidDump);
sl@6
   620
sl@6
   621
                    //Make sure both usage page and usage are matching MCE remote
sl@8
   622
                    if (deviceInfo.hid.usUsagePage != (ushort)Hid.UsagePage.MceRemote || deviceInfo.hid.usUsage != (ushort)Hid.UsageId.MceRemoteUsage)
sl@6
   623
                    {
sl@6
   624
                        Debug.WriteLine("Not MCE remote page and usage.");
sl@6
   625
                        return;
sl@6
   626
                    }
sl@0
   627
sl@3
   628
                    if (Enum.IsDefined(typeof(MceButton), rawData) && rawData!=0) //Our button is a known MCE button
sl@3
   629
                    {
sl@3
   630
                        if (this.ButtonPressed != null) //What's that?
sl@3
   631
                        {
sl@3
   632
                            this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32())));
sl@3
   633
                        }
sl@3
   634
                    }
sl@0
   635
				}
sl@0
   636
				else if(raw.header.dwType == RIM_TYPEMOUSE)
sl@0
   637
				{
sl@0
   638
					// do mouse handling...
sl@0
   639
				}
sl@0
   640
				else if(raw.header.dwType == RIM_TYPEKEYBOARD)
sl@0
   641
				{
sl@0
   642
					// do keyboard handling...
sl@0
   643
				}
sl@0
   644
			}
sl@0
   645
			finally
sl@0
   646
			{
sl@6
   647
				Marshal.FreeHGlobal(rawInputBuffer);
sl@0
   648
			}
sl@0
   649
		}
sl@0
   650
sl@0
   651
sl@0
   652
		private InputDevice GetDevice(int param)
sl@0
   653
		{
sl@0
   654
			InputDevice inputDevice;
sl@0
   655
sl@0
   656
			switch ((int) (((ushort) (param >> 16)) & FAPPCOMMAND_MASK))
sl@0
   657
			{
sl@0
   658
				case FAPPCOMMAND_OEM:
sl@0
   659
					inputDevice = InputDevice.OEM;
sl@0
   660
					break;
sl@0
   661
				case FAPPCOMMAND_MOUSE:
sl@0
   662
					inputDevice = InputDevice.Mouse;
sl@0
   663
					break;
sl@0
   664
				default:
sl@0
   665
					inputDevice = InputDevice.Key;
sl@0
   666
					break;
sl@0
   667
			}
sl@0
   668
sl@0
   669
			return inputDevice;
sl@0
   670
		}
sl@0
   671
	}
sl@0
   672
}