RemoteControlDevice.cs
author sl
Tue, 04 Nov 2014 22:11:01 +0100
changeset 4 eed66dfd9848
parent 3 db8e6a25d6bc
child 5 b2ed6fc37d95
permissions -rw-r--r--
Cleaning and adding GetRawInputDeviceInfo definition.
We will need to use it to get the Usage Page of HID messages.
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@0
     5
sl@0
     6
sl@0
     7
namespace BruceThomas.Devices.RemoteControl
sl@0
     8
{
sl@0
     9
	public enum InputDevice
sl@0
    10
	{
sl@0
    11
		Key,
sl@0
    12
		Mouse,
sl@0
    13
		OEM
sl@0
    14
	}
sl@0
    15
sl@0
    16
sl@0
    17
	public enum RemoteControlButton
sl@0
    18
	{
sl@0
    19
		Clear,
sl@0
    20
		Down,
sl@0
    21
		Left,
sl@0
    22
		Digit0,
sl@0
    23
		Digit1,
sl@0
    24
		Digit2,
sl@0
    25
		Digit3,
sl@0
    26
		Digit4,
sl@0
    27
		Digit5,
sl@0
    28
		Digit6,
sl@0
    29
		Digit7,
sl@0
    30
		Digit8,
sl@0
    31
		Digit9,
sl@0
    32
		Enter,
sl@0
    33
		Right,
sl@0
    34
		Up,
sl@0
    35
sl@0
    36
		Back,
sl@0
    37
		ChannelDown,
sl@0
    38
		ChannelUp,
sl@0
    39
		FastForward,
sl@0
    40
		VolumeMute,
sl@0
    41
		Pause,
sl@0
    42
		Play,
sl@0
    43
        PlayPause,
sl@0
    44
		Record,
sl@0
    45
		PreviousTrack,
sl@0
    46
		Rewind,
sl@0
    47
		NextTrack,
sl@0
    48
		Stop,
sl@0
    49
		VolumeDown,
sl@0
    50
		VolumeUp,
sl@0
    51
sl@0
    52
		RecordedTV,
sl@0
    53
		Guide,
sl@0
    54
		LiveTV,
sl@0
    55
		Details,
sl@0
    56
		DVDMenu,
sl@0
    57
		DVDAngle,
sl@0
    58
		DVDAudio,
sl@0
    59
		DVDSubtitle,
sl@0
    60
		MyMusic,
sl@0
    61
		MyPictures,
sl@0
    62
		MyVideos,
sl@0
    63
		MyTV,
sl@0
    64
		OEM1,
sl@0
    65
		OEM2,
sl@0
    66
		StandBy,
sl@0
    67
		TVJump,
sl@0
    68
sl@0
    69
		Unknown
sl@0
    70
	}
sl@0
    71
sl@3
    72
    /// <summary>
sl@3
    73
    /// 
sl@3
    74
    /// </summary>
sl@3
    75
    public enum MceButton
sl@3
    76
    {
sl@3
    77
        Null                    =   0x00, //Not defined by the specs
sl@3
    78
        GreenStart              =   0x0D,
sl@3
    79
        ClosedCaptioning        =   0x2B,
sl@3
    80
        Teletext                =   0x5A,
sl@3
    81
        TeletextRed             =   0x5B,
sl@3
    82
        TeletextGreen           =   0x5C,
sl@3
    83
        TeletextYellow          =   0x5D,
sl@3
    84
        TeletextBlue            =   0x5E,
sl@3
    85
        LiveTv                  =   0x25,
sl@3
    86
        Music                   =   0x47,
sl@3
    87
        RecordedTv              =   0x48,
sl@3
    88
        Pictures                =   0x49,
sl@3
    89
        Videos                  =   0x4A,
sl@3
    90
        FmRadio                 =   0x50,
sl@3
    91
        Extras                  =   0x3C,
sl@3
    92
        ExtrasApp               =   0x3D,
sl@3
    93
        DvdMenu                 =   0x24,
sl@3
    94
        DvdAngle                =   0x4B,
sl@3
    95
        DvdAudio                =   0x4C,
sl@3
    96
        DvdSubtitle             =   0x4D,
sl@3
    97
        Eject                   =   0x28,
sl@3
    98
        DvdTopMenu              =   0x43,
sl@3
    99
        Ext0                    =   0x32,
sl@3
   100
        Ext1                    =   0x33,
sl@3
   101
        Ext2                    =   0x34,
sl@3
   102
        Ext3                    =   0x35,
sl@3
   103
        Ext4                    =   0x36,
sl@3
   104
        Ext5                    =   0x37,
sl@3
   105
        Ext6                    =   0x38,
sl@3
   106
        Ext7                    =   0x39,
sl@3
   107
        Ext8                    =   0x3A,
sl@3
   108
        Ext9                    =   0x80,
sl@3
   109
        Ext10                   =   0x81,
sl@3
   110
        Ext11                   =   0x6F,
sl@3
   111
        Zoom                    =   0x27,
sl@3
   112
        ChannelInput            =   0x42,
sl@3
   113
        SubAudio                =   0x2D,
sl@3
   114
        Channel10               =   0x3E,
sl@3
   115
        Channel11               =   0x3F,
sl@3
   116
        Channel12               =   0x40,
sl@3
   117
        Display                 =   0x4F,
sl@3
   118
        Kiosk                   =   0x6A,
sl@3
   119
        NetworkSelection        =   0x2C,
sl@3
   120
        BlueRayTool             =   0x78,
sl@3
   121
        ChannelInfo             =   0x41,
sl@3
   122
        VideoSelection          =   0x61                
sl@3
   123
    }
sl@3
   124
sl@0
   125
sl@0
   126
	#region RemoteControlEventArgs
sl@0
   127
sl@0
   128
	public class RemoteControlEventArgs : EventArgs
sl@0
   129
	{
sl@3
   130
        RemoteControlButton _rcb;
sl@0
   131
		InputDevice _device;
sl@3
   132
        MceButton iMceButton;
sl@0
   133
sl@3
   134
        public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@0
   135
		{
sl@3
   136
            iMceButton = MceButton.Null;
sl@0
   137
			_rcb = rcb;
sl@0
   138
			_device = device;
sl@0
   139
		}
sl@0
   140
sl@3
   141
        public RemoteControlEventArgs(MceButton mce, InputDevice device)
sl@3
   142
        {
sl@3
   143
            iMceButton = mce;
sl@3
   144
            _rcb = RemoteControlButton.Unknown;
sl@3
   145
            _device = device;
sl@3
   146
        }
sl@0
   147
sl@0
   148
		public RemoteControlEventArgs()
sl@0
   149
		{
sl@3
   150
            iMceButton = MceButton.Null;
sl@0
   151
			_rcb = RemoteControlButton.Unknown;
sl@0
   152
			_device = InputDevice.Key;
sl@0
   153
		}
sl@0
   154
sl@0
   155
		public RemoteControlButton Button
sl@0
   156
		{
sl@0
   157
			get { return _rcb;  }
sl@0
   158
			set { _rcb = value; }
sl@0
   159
		}
sl@0
   160
sl@3
   161
        public MceButton MceButton
sl@3
   162
        {
sl@3
   163
            get { return iMceButton; }
sl@3
   164
            set { iMceButton = value; }
sl@3
   165
        }
sl@3
   166
sl@0
   167
		public InputDevice Device
sl@0
   168
		{
sl@0
   169
			get { return _device;  }
sl@0
   170
			set { _device = value; }
sl@0
   171
		}
sl@0
   172
	}
sl@0
   173
sl@0
   174
	#endregion RemoteControlEventArgs
sl@0
   175
sl@0
   176
sl@0
   177
	public sealed class RemoteControlDevice
sl@0
   178
	{
sl@0
   179
sl@0
   180
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   181
		internal struct RAWINPUTDEVICE
sl@0
   182
		{
sl@0
   183
			[MarshalAs(UnmanagedType.U2)]
sl@0
   184
			public ushort usUsagePage;
sl@0
   185
			[MarshalAs(UnmanagedType.U2)]
sl@0
   186
			public ushort usUsage;
sl@0
   187
			[MarshalAs(UnmanagedType.U4)]
sl@0
   188
			public int	 dwFlags;
sl@0
   189
			public IntPtr hwndTarget;
sl@0
   190
		}
sl@0
   191
sl@0
   192
sl@0
   193
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   194
		internal struct RAWINPUTHEADER
sl@0
   195
		{
sl@0
   196
			[MarshalAs(UnmanagedType.U4)]
sl@0
   197
			public int dwType;
sl@0
   198
			[MarshalAs(UnmanagedType.U4)]
sl@0
   199
			public int dwSize;
sl@0
   200
            public IntPtr hDevice;
sl@0
   201
			[MarshalAs(UnmanagedType.U4)]
sl@0
   202
			public int wParam;
sl@0
   203
		}
sl@0
   204
sl@0
   205
sl@0
   206
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   207
		internal struct RAWHID
sl@0
   208
		{
sl@0
   209
			[MarshalAs(UnmanagedType.U4)]
sl@0
   210
			public int dwSizeHid;
sl@0
   211
			[MarshalAs(UnmanagedType.U4)]
sl@0
   212
			public int dwCount;
sl@0
   213
            //
sl@0
   214
            //BYTE  bRawData[1];
sl@0
   215
		}
sl@0
   216
sl@0
   217
sl@0
   218
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   219
		internal struct BUTTONSSTR
sl@0
   220
		{
sl@0
   221
			[MarshalAs(UnmanagedType.U2)]
sl@0
   222
			public ushort usButtonFlags;
sl@0
   223
			[MarshalAs(UnmanagedType.U2)]
sl@0
   224
			public ushort usButtonData;
sl@0
   225
		}
sl@0
   226
sl@0
   227
sl@0
   228
        [StructLayout(LayoutKind.Explicit, Pack = 1)]
sl@0
   229
		internal struct RAWMOUSE
sl@0
   230
		{
sl@0
   231
			[MarshalAs(UnmanagedType.U2)]
sl@0
   232
			[FieldOffset (0)] public ushort usFlags;
sl@0
   233
			[MarshalAs(UnmanagedType.U4)]
sl@0
   234
			[FieldOffset (4)] public uint ulButtons;
sl@0
   235
			[FieldOffset (4)] public BUTTONSSTR buttonsStr;
sl@0
   236
			[MarshalAs(UnmanagedType.U4)]
sl@0
   237
			[FieldOffset (8)] public uint ulRawButtons;
sl@0
   238
            [MarshalAs(UnmanagedType.U4)]
sl@0
   239
            [FieldOffset (12)] public int lLastX;
sl@0
   240
            [MarshalAs(UnmanagedType.U4)]
sl@0
   241
            [FieldOffset (16)] public int lLastY;
sl@0
   242
			[MarshalAs(UnmanagedType.U4)]
sl@0
   243
			[FieldOffset (20)] public uint ulExtraInformation;
sl@0
   244
		}
sl@0
   245
sl@0
   246
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   247
		internal struct RAWKEYBOARD
sl@0
   248
		{
sl@0
   249
			[MarshalAs(UnmanagedType.U2)]
sl@0
   250
			public ushort MakeCode;
sl@0
   251
			[MarshalAs(UnmanagedType.U2)]
sl@0
   252
			public ushort Flags;
sl@0
   253
			[MarshalAs(UnmanagedType.U2)]
sl@0
   254
			public ushort Reserved;
sl@0
   255
			[MarshalAs(UnmanagedType.U2)]
sl@0
   256
			public ushort VKey;
sl@0
   257
			[MarshalAs(UnmanagedType.U4)]
sl@0
   258
			public uint Message;
sl@0
   259
			[MarshalAs(UnmanagedType.U4)]
sl@0
   260
			public uint ExtraInformation;
sl@0
   261
		}
sl@0
   262
sl@0
   263
sl@0
   264
		[StructLayout(LayoutKind.Explicit, Pack=1)]
sl@0
   265
		internal struct RAWINPUT
sl@0
   266
		{
sl@0
   267
			[FieldOffset  (0)] public RAWINPUTHEADER header;
sl@0
   268
			[FieldOffset (16)] public RAWMOUSE mouse;
sl@0
   269
			[FieldOffset (16)] public RAWKEYBOARD keyboard;
sl@0
   270
			[FieldOffset (16)] public RAWHID hid;
sl@0
   271
		}
sl@0
   272
sl@0
   273
sl@0
   274
		[DllImport("User32.dll")]
sl@0
   275
		extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);
sl@0
   276
sl@0
   277
		[DllImport("User32.dll")]
sl@0
   278
		extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);
sl@0
   279
sl@4
   280
   		[DllImport("User32.dll")]
sl@4
   281
		extern static uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
sl@4
   282
sl@0
   283
sl@0
   284
		private const int WM_KEYDOWN	= 0x0100;
sl@0
   285
		private const int WM_APPCOMMAND	= 0x0319;
sl@0
   286
		private const int WM_INPUT		= 0x00FF;
sl@0
   287
sl@0
   288
		private const int APPCOMMAND_BROWSER_BACKWARD   = 1;
sl@0
   289
		private const int APPCOMMAND_VOLUME_MUTE        = 8;
sl@0
   290
		private const int APPCOMMAND_VOLUME_DOWN        = 9;
sl@0
   291
		private const int APPCOMMAND_VOLUME_UP          = 10;
sl@0
   292
		private const int APPCOMMAND_MEDIA_NEXTTRACK    = 11;
sl@0
   293
		private const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12;
sl@0
   294
		private const int APPCOMMAND_MEDIA_STOP         = 13;
sl@0
   295
		private const int APPCOMMAND_MEDIA_PLAY_PAUSE   = 14;
sl@0
   296
		private const int APPCOMMAND_MEDIA_PLAY         = 46;
sl@0
   297
		private const int APPCOMMAND_MEDIA_PAUSE        = 47;
sl@0
   298
		private const int APPCOMMAND_MEDIA_RECORD       = 48;
sl@0
   299
		private const int APPCOMMAND_MEDIA_FAST_FORWARD = 49;
sl@0
   300
		private const int APPCOMMAND_MEDIA_REWIND       = 50;
sl@0
   301
		private const int APPCOMMAND_MEDIA_CHANNEL_UP   = 51;
sl@0
   302
		private const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52;
sl@0
   303
sl@0
   304
		private const int RIM_TYPEMOUSE					= 0;
sl@0
   305
		private const int RIM_TYPEKEYBOARD				= 1;
sl@0
   306
		private const int RIM_TYPEHID					= 2;
sl@0
   307
sl@0
   308
		private const int RID_INPUT						= 0x10000003;
sl@0
   309
		private const int RID_HEADER					= 0x10000005;
sl@0
   310
sl@0
   311
		private const int FAPPCOMMAND_MASK				= 0xF000;
sl@0
   312
		private const int FAPPCOMMAND_MOUSE				= 0x8000;
sl@0
   313
		private const int FAPPCOMMAND_KEY				= 0;
sl@0
   314
		private const int FAPPCOMMAND_OEM				= 0x1000;
sl@0
   315
sl@0
   316
		public delegate void RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@0
   317
		public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0
   318
sl@0
   319
sl@0
   320
		//-------------------------------------------------------------
sl@0
   321
		// constructors
sl@0
   322
		//-------------------------------------------------------------
sl@0
   323
sl@0
   324
		public RemoteControlDevice()
sl@0
   325
		{
sl@0
   326
			// Register the input device to receive the commands from the
sl@0
   327
			// remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@0
   328
			// for the vendor defined usage page.
sl@0
   329
sl@0
   330
			RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[3];
sl@0
   331
sl@0
   332
			rid[0].usUsagePage = 0xFFBC;
sl@0
   333
			rid[0].usUsage = 0x88;
sl@0
   334
			rid[0].dwFlags = 0;
sl@0
   335
sl@0
   336
			rid[1].usUsagePage = 0x0C;
sl@0
   337
			rid[1].usUsage = 0x01;
sl@0
   338
			rid[1].dwFlags = 0;
sl@0
   339
sl@0
   340
			rid[2].usUsagePage = 0x0C;
sl@0
   341
			rid[2].usUsage = 0x80;
sl@0
   342
			rid[2].dwFlags = 0;
sl@0
   343
sl@0
   344
			if (!RegisterRawInputDevices(rid,
sl@0
   345
				(uint) rid.Length,
sl@0
   346
				(uint) Marshal.SizeOf(rid[0]))
sl@0
   347
				)
sl@0
   348
			{
sl@0
   349
				throw new ApplicationException("Failed to register raw input devices.");
sl@0
   350
			}
sl@0
   351
		}
sl@0
   352
sl@0
   353
sl@0
   354
		//-------------------------------------------------------------
sl@0
   355
		// methods
sl@0
   356
		//-------------------------------------------------------------
sl@0
   357
sl@0
   358
		public void ProcessMessage(Message message)
sl@0
   359
		{
sl@0
   360
			int param;
sl@0
   361
sl@0
   362
			switch (message.Msg)
sl@0
   363
			{
sl@0
   364
				case WM_KEYDOWN:
sl@0
   365
					param = message.WParam.ToInt32();
sl@0
   366
					ProcessKeyDown(param);
sl@0
   367
					break;
sl@0
   368
				case WM_APPCOMMAND:
sl@0
   369
					param = message.LParam.ToInt32();
sl@0
   370
					ProcessAppCommand(param);
sl@0
   371
					break;
sl@0
   372
				case WM_INPUT:
sl@0
   373
					ProcessInputCommand(ref message);
sl@0
   374
                    message.Result = new IntPtr(0);
sl@0
   375
					break;
sl@0
   376
			}
sl@0
   377
sl@0
   378
		}
sl@0
   379
sl@0
   380
sl@0
   381
		//-------------------------------------------------------------
sl@0
   382
		// methods (helpers)
sl@0
   383
		//-------------------------------------------------------------
sl@0
   384
sl@0
   385
		private void ProcessKeyDown(int param)
sl@0
   386
		{
sl@0
   387
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   388
sl@0
   389
			switch (param)
sl@0
   390
			{
sl@0
   391
				case (int) Keys.Escape:
sl@0
   392
					rcb = RemoteControlButton.Clear;
sl@0
   393
					break;
sl@0
   394
				case (int) Keys.Down:
sl@0
   395
					rcb = RemoteControlButton.Down;
sl@0
   396
					break;
sl@0
   397
				case (int) Keys.Left:
sl@0
   398
					rcb = RemoteControlButton.Left;
sl@0
   399
					break;
sl@0
   400
				case (int) Keys.D0:
sl@0
   401
					rcb = RemoteControlButton.Digit0;
sl@0
   402
					break;
sl@0
   403
				case (int) Keys.D1:
sl@0
   404
					rcb = RemoteControlButton.Digit1;
sl@0
   405
					break;
sl@0
   406
				case (int) Keys.D2:
sl@0
   407
					rcb = RemoteControlButton.Digit2;
sl@0
   408
					break;
sl@0
   409
				case (int) Keys.D3:
sl@0
   410
					rcb = RemoteControlButton.Digit3;
sl@0
   411
					break;
sl@0
   412
				case (int) Keys.D4:
sl@0
   413
					rcb = RemoteControlButton.Digit4;
sl@0
   414
					break;
sl@0
   415
				case (int) Keys.D5:
sl@0
   416
					rcb = RemoteControlButton.Digit5;
sl@0
   417
					break;
sl@0
   418
				case (int) Keys.D6:
sl@0
   419
					rcb = RemoteControlButton.Digit6;
sl@0
   420
					break;
sl@0
   421
				case (int) Keys.D7:
sl@0
   422
					rcb = RemoteControlButton.Digit7;
sl@0
   423
					break;
sl@0
   424
				case (int) Keys.D8:
sl@0
   425
					rcb = RemoteControlButton.Digit8;
sl@0
   426
					break;
sl@0
   427
				case (int) Keys.D9:
sl@0
   428
					rcb = RemoteControlButton.Digit9;
sl@0
   429
					break;
sl@0
   430
				case (int) Keys.Enter:
sl@0
   431
					rcb = RemoteControlButton.Enter;
sl@0
   432
					break;
sl@0
   433
				case (int) Keys.Right:
sl@0
   434
					rcb = RemoteControlButton.Right;
sl@0
   435
					break;
sl@0
   436
				case (int) Keys.Up:
sl@0
   437
					rcb = RemoteControlButton.Up;
sl@0
   438
					break;
sl@0
   439
			}
sl@0
   440
sl@0
   441
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@0
   442
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(param)));
sl@0
   443
		}
sl@0
   444
sl@0
   445
sl@0
   446
		private void ProcessAppCommand(int param)
sl@0
   447
		{
sl@0
   448
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   449
sl@0
   450
			int cmd	= (int) (((ushort) (param >> 16)) & ~FAPPCOMMAND_MASK);
sl@0
   451
sl@0
   452
			switch (cmd)
sl@0
   453
			{
sl@0
   454
				case APPCOMMAND_BROWSER_BACKWARD:
sl@0
   455
					rcb = RemoteControlButton.Back;
sl@0
   456
					break;
sl@0
   457
				case APPCOMMAND_MEDIA_CHANNEL_DOWN:
sl@0
   458
					rcb = RemoteControlButton.ChannelDown;
sl@0
   459
					break;
sl@0
   460
				case APPCOMMAND_MEDIA_CHANNEL_UP:
sl@0
   461
					rcb = RemoteControlButton.ChannelUp;
sl@0
   462
					break;
sl@0
   463
				case APPCOMMAND_MEDIA_FAST_FORWARD:
sl@0
   464
					rcb = RemoteControlButton.FastForward;
sl@0
   465
					break;
sl@0
   466
				case APPCOMMAND_VOLUME_MUTE:
sl@0
   467
					rcb = RemoteControlButton.VolumeMute;
sl@0
   468
					break;
sl@0
   469
				case APPCOMMAND_MEDIA_PAUSE:
sl@0
   470
					rcb = RemoteControlButton.Pause;
sl@0
   471
					break;
sl@0
   472
				case APPCOMMAND_MEDIA_PLAY:
sl@0
   473
					rcb = RemoteControlButton.Play;
sl@0
   474
					break;
sl@0
   475
                case APPCOMMAND_MEDIA_PLAY_PAUSE:
sl@0
   476
                    rcb = RemoteControlButton.PlayPause;
sl@0
   477
                    break;
sl@0
   478
				case APPCOMMAND_MEDIA_RECORD:
sl@0
   479
					rcb = RemoteControlButton.Record;
sl@0
   480
					break;
sl@0
   481
				case APPCOMMAND_MEDIA_PREVIOUSTRACK:
sl@0
   482
					rcb = RemoteControlButton.PreviousTrack;
sl@0
   483
					break;
sl@0
   484
				case APPCOMMAND_MEDIA_REWIND:
sl@0
   485
					rcb = RemoteControlButton.Rewind;
sl@0
   486
					break;
sl@0
   487
				case APPCOMMAND_MEDIA_NEXTTRACK:
sl@0
   488
					rcb = RemoteControlButton.NextTrack;
sl@0
   489
					break;
sl@0
   490
				case APPCOMMAND_MEDIA_STOP:
sl@0
   491
					rcb = RemoteControlButton.Stop;
sl@0
   492
					break;
sl@0
   493
				case APPCOMMAND_VOLUME_DOWN:
sl@0
   494
					rcb = RemoteControlButton.VolumeDown;
sl@0
   495
					break;
sl@0
   496
				case APPCOMMAND_VOLUME_UP:
sl@0
   497
					rcb = RemoteControlButton.VolumeUp;
sl@0
   498
					break;
sl@0
   499
			}
sl@0
   500
sl@0
   501
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@0
   502
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(param)));
sl@0
   503
		}
sl@0
   504
sl@0
   505
sl@0
   506
		private void ProcessInputCommand(ref Message message)
sl@0
   507
		{
sl@0
   508
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   509
			uint dwSize = 0;
sl@0
   510
sl@0
   511
            uint sizeOfHeader=(uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
sl@0
   512
sl@0
   513
            //Get the size of our raw input data.
sl@0
   514
			GetRawInputData(message.LParam,	RID_INPUT, IntPtr.Zero,	ref dwSize,	sizeOfHeader);
sl@0
   515
sl@0
   516
            //Allocate a large enough buffer
sl@0
   517
			IntPtr buffer = Marshal.AllocHGlobal((int) dwSize);
sl@0
   518
			try
sl@0
   519
			{
sl@0
   520
				if(buffer == IntPtr.Zero)
sl@0
   521
					return;
sl@0
   522
sl@0
   523
                //Now read our RAWINPUT data
sl@0
   524
				if (GetRawInputData(message.LParam,	RID_INPUT, buffer, ref dwSize, (uint) Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
sl@0
   525
				{
sl@0
   526
					return;
sl@0
   527
				}
sl@0
   528
sl@0
   529
                //Cast our buffer
sl@0
   530
                RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(buffer, typeof(RAWINPUT));
sl@0
   531
sl@0
   532
                //Check that our raw input is HID
sl@0
   533
                if (raw.header.dwType == RIM_TYPEHID && raw.hid.dwSizeHid>0)
sl@0
   534
				{
sl@0
   535
                    //Allocate a buffer for one HID message
sl@0
   536
					byte[] bRawData = new byte[raw.hid.dwSizeHid];
sl@0
   537
sl@0
   538
                    //Compute the address from which to copy our HID message
sl@0
   539
                    int pRawData = 0;
sl@0
   540
                    unsafe
sl@0
   541
                    {
sl@0
   542
                        byte* source = (byte*)buffer;
sl@0
   543
                        source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID);
sl@0
   544
                        pRawData = (int)source;
sl@0
   545
                    }
sl@0
   546
sl@4
   547
                    //Copy HID message into our buffer
sl@0
   548
                    Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizeHid);
sl@4
   549
                    //bRawData[0] //Not sure what's the meaning of the code at offset 0
sl@4
   550
                    //TODO: check size before access
sl@0
   551
                    int rawData = bRawData[1]; //Get button code
sl@4
   552
                    //Print HID codes in our debug output
sl@2
   553
                    Debug.WriteLine("HID " + raw.hid.dwCount + "/" + raw.hid.dwSizeHid + ":" + bRawData[0].ToString("X2") + bRawData[1].ToString("X2"));
sl@0
   554
sl@3
   555
                    if (Enum.IsDefined(typeof(MceButton), rawData) && rawData!=0) //Our button is a known MCE button
sl@3
   556
                    {
sl@3
   557
                        if (this.ButtonPressed != null) //What's that?
sl@3
   558
                        {
sl@3
   559
                            this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32())));
sl@3
   560
                        }
sl@3
   561
                    }
sl@0
   562
				}
sl@0
   563
				else if(raw.header.dwType == RIM_TYPEMOUSE)
sl@0
   564
				{
sl@0
   565
					// do mouse handling...
sl@0
   566
				}
sl@0
   567
				else if(raw.header.dwType == RIM_TYPEKEYBOARD)
sl@0
   568
				{
sl@0
   569
					// do keyboard handling...
sl@0
   570
				}
sl@0
   571
			}
sl@0
   572
			finally
sl@0
   573
			{
sl@0
   574
				Marshal.FreeHGlobal(buffer);
sl@0
   575
			}
sl@0
   576
		}
sl@0
   577
sl@0
   578
sl@0
   579
		private InputDevice GetDevice(int param)
sl@0
   580
		{
sl@0
   581
			InputDevice inputDevice;
sl@0
   582
sl@0
   583
			switch ((int) (((ushort) (param >> 16)) & FAPPCOMMAND_MASK))
sl@0
   584
			{
sl@0
   585
				case FAPPCOMMAND_OEM:
sl@0
   586
					inputDevice = InputDevice.OEM;
sl@0
   587
					break;
sl@0
   588
				case FAPPCOMMAND_MOUSE:
sl@0
   589
					inputDevice = InputDevice.Mouse;
sl@0
   590
					break;
sl@0
   591
				default:
sl@0
   592
					inputDevice = InputDevice.Key;
sl@0
   593
					break;
sl@0
   594
			}
sl@0
   595
sl@0
   596
			return inputDevice;
sl@0
   597
		}
sl@0
   598
	}
sl@0
   599
}