RemoteControlDevice.cs
author sl
Wed, 05 Nov 2014 10:19:02 +0100
changeset 5 b2ed6fc37d95
parent 4 eed66dfd9848
child 6 fa97ff5ceb7b
permissions -rw-r--r--
Adding docs for some MCE buttons.
Adding HP MCE button extension mapping and docs.
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@5
    77
        /// <summary>
sl@5
    78
        /// Not defined by the Microsoft specs.
sl@5
    79
        /// </summary>
sl@5
    80
        Null                    =   0x00, 
sl@3
    81
        GreenStart              =   0x0D,
sl@3
    82
        ClosedCaptioning        =   0x2B,
sl@3
    83
        Teletext                =   0x5A,
sl@3
    84
        TeletextRed             =   0x5B,
sl@3
    85
        TeletextGreen           =   0x5C,
sl@3
    86
        TeletextYellow          =   0x5D,
sl@3
    87
        TeletextBlue            =   0x5E,
sl@3
    88
        LiveTv                  =   0x25,
sl@3
    89
        Music                   =   0x47,
sl@3
    90
        RecordedTv              =   0x48,
sl@3
    91
        Pictures                =   0x49,
sl@3
    92
        Videos                  =   0x4A,
sl@3
    93
        FmRadio                 =   0x50,
sl@3
    94
        Extras                  =   0x3C,
sl@3
    95
        ExtrasApp               =   0x3D,
sl@3
    96
        DvdMenu                 =   0x24,
sl@3
    97
        DvdAngle                =   0x4B,
sl@3
    98
        DvdAudio                =   0x4C,
sl@3
    99
        DvdSubtitle             =   0x4D,
sl@5
   100
        /// <summary>
sl@5
   101
        /// First press action: Ejects a DVD drive.
sl@5
   102
        /// <para />
sl@5
   103
        /// Second press action: Repeats first press action.
sl@5
   104
        /// <para />
sl@5
   105
        /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
sl@5
   106
        /// </summary>
sl@3
   107
        Eject                   =   0x28,
sl@3
   108
        DvdTopMenu              =   0x43,
sl@5
   109
        /// <summary>
sl@5
   110
        /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
sl@5
   111
        /// Collection (page 0xFFBC, usage 0x88).
sl@5
   112
        /// <para />
sl@5
   113
        /// Second press action: Repeats message.
sl@5
   114
        /// <para />
sl@5
   115
        /// Auto-repeat: No
sl@5
   116
        /// <para />
sl@5
   117
        /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   118
        /// <para />
sl@5
   119
        /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
sl@5
   120
        /// </summary>
sl@3
   121
        Ext0                    =   0x32,
sl@5
   122
        /// <summary>
sl@5
   123
        /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
sl@5
   124
        /// Collection (page 0xFFBC, usage 0x88).
sl@5
   125
        /// <para />
sl@5
   126
        /// Second press action: Repeats message.
sl@5
   127
        /// <para />
sl@5
   128
        /// Auto-repeat: No
sl@5
   129
        /// <para />
sl@5
   130
        /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   131
        /// <para />
sl@5
   132
        /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
sl@5
   133
        /// </summary>
sl@3
   134
        Ext1                    =   0x33,
sl@5
   135
        /// <summary>
sl@5
   136
        /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
sl@5
   137
        /// Collection (page 0xFFBC, usage 0x88).
sl@5
   138
        /// <para />
sl@5
   139
        /// Second press action: Repeats message.
sl@5
   140
        /// <para />
sl@5
   141
        /// Auto-repeat: No
sl@5
   142
        /// <para />
sl@5
   143
        /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   144
        /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
sl@5
   145
        /// </summary>
sl@3
   146
        Ext2                    =   0x34,
sl@5
   147
        /// <summary>
sl@5
   148
        /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
sl@5
   149
        /// Collection (page 0xFFBC, usage 0x88).
sl@5
   150
        /// <para />
sl@5
   151
        /// Second press action: Repeats message.
sl@5
   152
        /// <para />
sl@5
   153
        /// Auto-repeat: No
sl@5
   154
        /// <para />
sl@5
   155
        /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   156
        /// </summary>
sl@3
   157
        Ext3                    =   0x35,
sl@3
   158
        Ext4                    =   0x36,
sl@3
   159
        Ext5                    =   0x37,
sl@3
   160
        Ext6                    =   0x38,
sl@3
   161
        Ext7                    =   0x39,
sl@3
   162
        Ext8                    =   0x3A,
sl@3
   163
        Ext9                    =   0x80,
sl@3
   164
        Ext10                   =   0x81,
sl@3
   165
        Ext11                   =   0x6F,
sl@3
   166
        Zoom                    =   0x27,
sl@3
   167
        ChannelInput            =   0x42,
sl@3
   168
        SubAudio                =   0x2D,
sl@3
   169
        Channel10               =   0x3E,
sl@3
   170
        Channel11               =   0x3F,
sl@3
   171
        Channel12               =   0x40,
sl@5
   172
        /// <summary>
sl@5
   173
        /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific
sl@5
   174
        /// Collection. This button is intended to control the front panel display of home entertainment
sl@5
   175
        /// computers. When this button is pressed, the display could be turned on or off, or the display
sl@5
   176
        /// mode could change.
sl@5
   177
        /// <para />
sl@5
   178
        /// Second press action: Repeats message.
sl@5
   179
        /// <para />
sl@5
   180
        /// Auto-repeat: No
sl@5
   181
        /// <para />
sl@5
   182
        /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
sl@5
   183
        /// </summary>
sl@3
   184
        Display                 =   0x4F,
sl@5
   185
        /// <summary>
sl@5
   186
        /// First press action: To be determined.
sl@5
   187
        /// <para />
sl@5
   188
        /// Second press action: Repeats message.
sl@5
   189
        /// <para />
sl@5
   190
        /// Auto-repeat: No
sl@5
   191
        /// </summary>
sl@3
   192
        Kiosk                   =   0x6A,
sl@3
   193
        NetworkSelection        =   0x2C,
sl@3
   194
        BlueRayTool             =   0x78,
sl@3
   195
        ChannelInfo             =   0x41,
sl@3
   196
        VideoSelection          =   0x61                
sl@3
   197
    }
sl@3
   198
sl@5
   199
    public enum HpMceButton
sl@5
   200
    {
sl@5
   201
        /// <summary>
sl@5
   202
        /// Displays visual imagery that is synchronized to the sound of your music tracks.
sl@5
   203
        /// <para />
sl@5
   204
        /// Second press action: Repeats message.
sl@5
   205
        /// <para />
sl@5
   206
        /// Auto-repeat: No
sl@5
   207
        /// <para />
sl@5
   208
        /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   209
        /// <para />
sl@5
   210
        /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
sl@5
   211
        /// </summary>
sl@5
   212
        Visualization = MceButton.Ext0,
sl@5
   213
        /// <summary>
sl@5
   214
        /// Plays a slide show of all the pictures on your hard disk drive.
sl@5
   215
        /// <para />
sl@5
   216
        /// Second press action: Repeats message.
sl@5
   217
        /// <para />
sl@5
   218
        /// Auto-repeat: No
sl@5
   219
        /// <para />
sl@5
   220
        /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   221
        /// <para />
sl@5
   222
        /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
sl@5
   223
        /// </summary>
sl@5
   224
        SlideShow = MceButton.Ext1,
sl@5
   225
        /// <summary>
sl@5
   226
        /// Eject optical drive.
sl@5
   227
        /// <para />
sl@5
   228
        /// Second press action: Repeats message.
sl@5
   229
        /// <para />
sl@5
   230
        /// Auto-repeat: No
sl@5
   231
        /// <para />
sl@5
   232
        /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   233
        /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
sl@5
   234
        /// </summary>
sl@5
   235
        Eject = MceButton.Ext2,
sl@5
   236
        /// <summary>
sl@5
   237
        /// Not sure what this should do.
sl@5
   238
        /// <para />
sl@5
   239
        /// Second press action: Repeats message.
sl@5
   240
        /// <para />
sl@5
   241
        /// Auto-repeat: No
sl@5
   242
        /// <para />
sl@5
   243
        /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
sl@5
   244
        /// </summary>
sl@5
   245
        InputSelection = MceButton.Ext3,
sl@5
   246
    }
sl@5
   247
sl@5
   248
sl@0
   249
sl@0
   250
	#region RemoteControlEventArgs
sl@0
   251
sl@0
   252
	public class RemoteControlEventArgs : EventArgs
sl@0
   253
	{
sl@3
   254
        RemoteControlButton _rcb;
sl@0
   255
		InputDevice _device;
sl@3
   256
        MceButton iMceButton;
sl@0
   257
sl@3
   258
        public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
sl@0
   259
		{
sl@3
   260
            iMceButton = MceButton.Null;
sl@0
   261
			_rcb = rcb;
sl@0
   262
			_device = device;
sl@0
   263
		}
sl@0
   264
sl@3
   265
        public RemoteControlEventArgs(MceButton mce, InputDevice device)
sl@3
   266
        {
sl@3
   267
            iMceButton = mce;
sl@3
   268
            _rcb = RemoteControlButton.Unknown;
sl@3
   269
            _device = device;
sl@3
   270
        }
sl@0
   271
sl@0
   272
		public RemoteControlEventArgs()
sl@0
   273
		{
sl@3
   274
            iMceButton = MceButton.Null;
sl@0
   275
			_rcb = RemoteControlButton.Unknown;
sl@0
   276
			_device = InputDevice.Key;
sl@0
   277
		}
sl@0
   278
sl@0
   279
		public RemoteControlButton Button
sl@0
   280
		{
sl@0
   281
			get { return _rcb;  }
sl@0
   282
			set { _rcb = value; }
sl@0
   283
		}
sl@0
   284
sl@3
   285
        public MceButton MceButton
sl@3
   286
        {
sl@3
   287
            get { return iMceButton; }
sl@3
   288
            set { iMceButton = value; }
sl@3
   289
        }
sl@3
   290
sl@0
   291
		public InputDevice Device
sl@0
   292
		{
sl@0
   293
			get { return _device;  }
sl@0
   294
			set { _device = value; }
sl@0
   295
		}
sl@0
   296
	}
sl@0
   297
sl@0
   298
	#endregion RemoteControlEventArgs
sl@0
   299
sl@0
   300
sl@0
   301
	public sealed class RemoteControlDevice
sl@0
   302
	{
sl@0
   303
sl@0
   304
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   305
		internal struct RAWINPUTDEVICE
sl@0
   306
		{
sl@0
   307
			[MarshalAs(UnmanagedType.U2)]
sl@0
   308
			public ushort usUsagePage;
sl@0
   309
			[MarshalAs(UnmanagedType.U2)]
sl@0
   310
			public ushort usUsage;
sl@0
   311
			[MarshalAs(UnmanagedType.U4)]
sl@0
   312
			public int	 dwFlags;
sl@0
   313
			public IntPtr hwndTarget;
sl@0
   314
		}
sl@0
   315
sl@0
   316
sl@0
   317
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   318
		internal struct RAWINPUTHEADER
sl@0
   319
		{
sl@0
   320
			[MarshalAs(UnmanagedType.U4)]
sl@0
   321
			public int dwType;
sl@0
   322
			[MarshalAs(UnmanagedType.U4)]
sl@0
   323
			public int dwSize;
sl@0
   324
            public IntPtr hDevice;
sl@0
   325
			[MarshalAs(UnmanagedType.U4)]
sl@0
   326
			public int wParam;
sl@0
   327
		}
sl@0
   328
sl@0
   329
sl@0
   330
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   331
		internal struct RAWHID
sl@0
   332
		{
sl@0
   333
			[MarshalAs(UnmanagedType.U4)]
sl@0
   334
			public int dwSizeHid;
sl@0
   335
			[MarshalAs(UnmanagedType.U4)]
sl@0
   336
			public int dwCount;
sl@0
   337
            //
sl@0
   338
            //BYTE  bRawData[1];
sl@0
   339
		}
sl@0
   340
sl@0
   341
sl@0
   342
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   343
		internal struct BUTTONSSTR
sl@0
   344
		{
sl@0
   345
			[MarshalAs(UnmanagedType.U2)]
sl@0
   346
			public ushort usButtonFlags;
sl@0
   347
			[MarshalAs(UnmanagedType.U2)]
sl@0
   348
			public ushort usButtonData;
sl@0
   349
		}
sl@0
   350
sl@0
   351
sl@0
   352
        [StructLayout(LayoutKind.Explicit, Pack = 1)]
sl@0
   353
		internal struct RAWMOUSE
sl@0
   354
		{
sl@0
   355
			[MarshalAs(UnmanagedType.U2)]
sl@0
   356
			[FieldOffset (0)] public ushort usFlags;
sl@0
   357
			[MarshalAs(UnmanagedType.U4)]
sl@0
   358
			[FieldOffset (4)] public uint ulButtons;
sl@0
   359
			[FieldOffset (4)] public BUTTONSSTR buttonsStr;
sl@0
   360
			[MarshalAs(UnmanagedType.U4)]
sl@0
   361
			[FieldOffset (8)] public uint ulRawButtons;
sl@0
   362
            [MarshalAs(UnmanagedType.U4)]
sl@0
   363
            [FieldOffset (12)] public int lLastX;
sl@0
   364
            [MarshalAs(UnmanagedType.U4)]
sl@0
   365
            [FieldOffset (16)] public int lLastY;
sl@0
   366
			[MarshalAs(UnmanagedType.U4)]
sl@0
   367
			[FieldOffset (20)] public uint ulExtraInformation;
sl@0
   368
		}
sl@0
   369
sl@0
   370
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
sl@0
   371
		internal struct RAWKEYBOARD
sl@0
   372
		{
sl@0
   373
			[MarshalAs(UnmanagedType.U2)]
sl@0
   374
			public ushort MakeCode;
sl@0
   375
			[MarshalAs(UnmanagedType.U2)]
sl@0
   376
			public ushort Flags;
sl@0
   377
			[MarshalAs(UnmanagedType.U2)]
sl@0
   378
			public ushort Reserved;
sl@0
   379
			[MarshalAs(UnmanagedType.U2)]
sl@0
   380
			public ushort VKey;
sl@0
   381
			[MarshalAs(UnmanagedType.U4)]
sl@0
   382
			public uint Message;
sl@0
   383
			[MarshalAs(UnmanagedType.U4)]
sl@0
   384
			public uint ExtraInformation;
sl@0
   385
		}
sl@0
   386
sl@0
   387
sl@0
   388
		[StructLayout(LayoutKind.Explicit, Pack=1)]
sl@0
   389
		internal struct RAWINPUT
sl@0
   390
		{
sl@0
   391
			[FieldOffset  (0)] public RAWINPUTHEADER header;
sl@0
   392
			[FieldOffset (16)] public RAWMOUSE mouse;
sl@0
   393
			[FieldOffset (16)] public RAWKEYBOARD keyboard;
sl@0
   394
			[FieldOffset (16)] public RAWHID hid;
sl@0
   395
		}
sl@0
   396
sl@0
   397
sl@0
   398
		[DllImport("User32.dll")]
sl@0
   399
		extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize);
sl@0
   400
sl@0
   401
		[DllImport("User32.dll")]
sl@0
   402
		extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader);
sl@0
   403
sl@4
   404
   		[DllImport("User32.dll")]
sl@4
   405
		extern static uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize);
sl@4
   406
sl@0
   407
sl@0
   408
		private const int WM_KEYDOWN	= 0x0100;
sl@0
   409
		private const int WM_APPCOMMAND	= 0x0319;
sl@0
   410
		private const int WM_INPUT		= 0x00FF;
sl@0
   411
sl@0
   412
		private const int APPCOMMAND_BROWSER_BACKWARD   = 1;
sl@0
   413
		private const int APPCOMMAND_VOLUME_MUTE        = 8;
sl@0
   414
		private const int APPCOMMAND_VOLUME_DOWN        = 9;
sl@0
   415
		private const int APPCOMMAND_VOLUME_UP          = 10;
sl@0
   416
		private const int APPCOMMAND_MEDIA_NEXTTRACK    = 11;
sl@0
   417
		private const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12;
sl@0
   418
		private const int APPCOMMAND_MEDIA_STOP         = 13;
sl@0
   419
		private const int APPCOMMAND_MEDIA_PLAY_PAUSE   = 14;
sl@0
   420
		private const int APPCOMMAND_MEDIA_PLAY         = 46;
sl@0
   421
		private const int APPCOMMAND_MEDIA_PAUSE        = 47;
sl@0
   422
		private const int APPCOMMAND_MEDIA_RECORD       = 48;
sl@0
   423
		private const int APPCOMMAND_MEDIA_FAST_FORWARD = 49;
sl@0
   424
		private const int APPCOMMAND_MEDIA_REWIND       = 50;
sl@0
   425
		private const int APPCOMMAND_MEDIA_CHANNEL_UP   = 51;
sl@0
   426
		private const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52;
sl@0
   427
sl@0
   428
		private const int RIM_TYPEMOUSE					= 0;
sl@0
   429
		private const int RIM_TYPEKEYBOARD				= 1;
sl@0
   430
		private const int RIM_TYPEHID					= 2;
sl@0
   431
sl@0
   432
		private const int RID_INPUT						= 0x10000003;
sl@0
   433
		private const int RID_HEADER					= 0x10000005;
sl@0
   434
sl@0
   435
		private const int FAPPCOMMAND_MASK				= 0xF000;
sl@0
   436
		private const int FAPPCOMMAND_MOUSE				= 0x8000;
sl@0
   437
		private const int FAPPCOMMAND_KEY				= 0;
sl@0
   438
		private const int FAPPCOMMAND_OEM				= 0x1000;
sl@0
   439
sl@0
   440
		public delegate void RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
sl@0
   441
		public event RemoteControlDeviceEventHandler ButtonPressed;
sl@0
   442
sl@0
   443
sl@0
   444
		//-------------------------------------------------------------
sl@0
   445
		// constructors
sl@0
   446
		//-------------------------------------------------------------
sl@0
   447
sl@0
   448
		public RemoteControlDevice()
sl@0
   449
		{
sl@0
   450
			// Register the input device to receive the commands from the
sl@0
   451
			// remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
sl@0
   452
			// for the vendor defined usage page.
sl@0
   453
sl@0
   454
			RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[3];
sl@0
   455
sl@0
   456
			rid[0].usUsagePage = 0xFFBC;
sl@0
   457
			rid[0].usUsage = 0x88;
sl@0
   458
			rid[0].dwFlags = 0;
sl@0
   459
sl@0
   460
			rid[1].usUsagePage = 0x0C;
sl@0
   461
			rid[1].usUsage = 0x01;
sl@0
   462
			rid[1].dwFlags = 0;
sl@0
   463
sl@0
   464
			rid[2].usUsagePage = 0x0C;
sl@0
   465
			rid[2].usUsage = 0x80;
sl@0
   466
			rid[2].dwFlags = 0;
sl@0
   467
sl@0
   468
			if (!RegisterRawInputDevices(rid,
sl@0
   469
				(uint) rid.Length,
sl@0
   470
				(uint) Marshal.SizeOf(rid[0]))
sl@0
   471
				)
sl@0
   472
			{
sl@0
   473
				throw new ApplicationException("Failed to register raw input devices.");
sl@0
   474
			}
sl@0
   475
		}
sl@0
   476
sl@0
   477
sl@0
   478
		//-------------------------------------------------------------
sl@0
   479
		// methods
sl@0
   480
		//-------------------------------------------------------------
sl@0
   481
sl@0
   482
		public void ProcessMessage(Message message)
sl@0
   483
		{
sl@0
   484
			int param;
sl@0
   485
sl@0
   486
			switch (message.Msg)
sl@0
   487
			{
sl@0
   488
				case WM_KEYDOWN:
sl@0
   489
					param = message.WParam.ToInt32();
sl@0
   490
					ProcessKeyDown(param);
sl@0
   491
					break;
sl@0
   492
				case WM_APPCOMMAND:
sl@0
   493
					param = message.LParam.ToInt32();
sl@0
   494
					ProcessAppCommand(param);
sl@0
   495
					break;
sl@0
   496
				case WM_INPUT:
sl@0
   497
					ProcessInputCommand(ref message);
sl@0
   498
                    message.Result = new IntPtr(0);
sl@0
   499
					break;
sl@0
   500
			}
sl@0
   501
sl@0
   502
		}
sl@0
   503
sl@0
   504
sl@0
   505
		//-------------------------------------------------------------
sl@0
   506
		// methods (helpers)
sl@0
   507
		//-------------------------------------------------------------
sl@0
   508
sl@0
   509
		private void ProcessKeyDown(int param)
sl@0
   510
		{
sl@0
   511
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   512
sl@0
   513
			switch (param)
sl@0
   514
			{
sl@0
   515
				case (int) Keys.Escape:
sl@0
   516
					rcb = RemoteControlButton.Clear;
sl@0
   517
					break;
sl@0
   518
				case (int) Keys.Down:
sl@0
   519
					rcb = RemoteControlButton.Down;
sl@0
   520
					break;
sl@0
   521
				case (int) Keys.Left:
sl@0
   522
					rcb = RemoteControlButton.Left;
sl@0
   523
					break;
sl@0
   524
				case (int) Keys.D0:
sl@0
   525
					rcb = RemoteControlButton.Digit0;
sl@0
   526
					break;
sl@0
   527
				case (int) Keys.D1:
sl@0
   528
					rcb = RemoteControlButton.Digit1;
sl@0
   529
					break;
sl@0
   530
				case (int) Keys.D2:
sl@0
   531
					rcb = RemoteControlButton.Digit2;
sl@0
   532
					break;
sl@0
   533
				case (int) Keys.D3:
sl@0
   534
					rcb = RemoteControlButton.Digit3;
sl@0
   535
					break;
sl@0
   536
				case (int) Keys.D4:
sl@0
   537
					rcb = RemoteControlButton.Digit4;
sl@0
   538
					break;
sl@0
   539
				case (int) Keys.D5:
sl@0
   540
					rcb = RemoteControlButton.Digit5;
sl@0
   541
					break;
sl@0
   542
				case (int) Keys.D6:
sl@0
   543
					rcb = RemoteControlButton.Digit6;
sl@0
   544
					break;
sl@0
   545
				case (int) Keys.D7:
sl@0
   546
					rcb = RemoteControlButton.Digit7;
sl@0
   547
					break;
sl@0
   548
				case (int) Keys.D8:
sl@0
   549
					rcb = RemoteControlButton.Digit8;
sl@0
   550
					break;
sl@0
   551
				case (int) Keys.D9:
sl@0
   552
					rcb = RemoteControlButton.Digit9;
sl@0
   553
					break;
sl@0
   554
				case (int) Keys.Enter:
sl@0
   555
					rcb = RemoteControlButton.Enter;
sl@0
   556
					break;
sl@0
   557
				case (int) Keys.Right:
sl@0
   558
					rcb = RemoteControlButton.Right;
sl@0
   559
					break;
sl@0
   560
				case (int) Keys.Up:
sl@0
   561
					rcb = RemoteControlButton.Up;
sl@0
   562
					break;
sl@0
   563
			}
sl@0
   564
sl@0
   565
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@0
   566
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(param)));
sl@0
   567
		}
sl@0
   568
sl@0
   569
sl@0
   570
		private void ProcessAppCommand(int param)
sl@0
   571
		{
sl@0
   572
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   573
sl@0
   574
			int cmd	= (int) (((ushort) (param >> 16)) & ~FAPPCOMMAND_MASK);
sl@0
   575
sl@0
   576
			switch (cmd)
sl@0
   577
			{
sl@0
   578
				case APPCOMMAND_BROWSER_BACKWARD:
sl@0
   579
					rcb = RemoteControlButton.Back;
sl@0
   580
					break;
sl@0
   581
				case APPCOMMAND_MEDIA_CHANNEL_DOWN:
sl@0
   582
					rcb = RemoteControlButton.ChannelDown;
sl@0
   583
					break;
sl@0
   584
				case APPCOMMAND_MEDIA_CHANNEL_UP:
sl@0
   585
					rcb = RemoteControlButton.ChannelUp;
sl@0
   586
					break;
sl@0
   587
				case APPCOMMAND_MEDIA_FAST_FORWARD:
sl@0
   588
					rcb = RemoteControlButton.FastForward;
sl@0
   589
					break;
sl@0
   590
				case APPCOMMAND_VOLUME_MUTE:
sl@0
   591
					rcb = RemoteControlButton.VolumeMute;
sl@0
   592
					break;
sl@0
   593
				case APPCOMMAND_MEDIA_PAUSE:
sl@0
   594
					rcb = RemoteControlButton.Pause;
sl@0
   595
					break;
sl@0
   596
				case APPCOMMAND_MEDIA_PLAY:
sl@0
   597
					rcb = RemoteControlButton.Play;
sl@0
   598
					break;
sl@0
   599
                case APPCOMMAND_MEDIA_PLAY_PAUSE:
sl@0
   600
                    rcb = RemoteControlButton.PlayPause;
sl@0
   601
                    break;
sl@0
   602
				case APPCOMMAND_MEDIA_RECORD:
sl@0
   603
					rcb = RemoteControlButton.Record;
sl@0
   604
					break;
sl@0
   605
				case APPCOMMAND_MEDIA_PREVIOUSTRACK:
sl@0
   606
					rcb = RemoteControlButton.PreviousTrack;
sl@0
   607
					break;
sl@0
   608
				case APPCOMMAND_MEDIA_REWIND:
sl@0
   609
					rcb = RemoteControlButton.Rewind;
sl@0
   610
					break;
sl@0
   611
				case APPCOMMAND_MEDIA_NEXTTRACK:
sl@0
   612
					rcb = RemoteControlButton.NextTrack;
sl@0
   613
					break;
sl@0
   614
				case APPCOMMAND_MEDIA_STOP:
sl@0
   615
					rcb = RemoteControlButton.Stop;
sl@0
   616
					break;
sl@0
   617
				case APPCOMMAND_VOLUME_DOWN:
sl@0
   618
					rcb = RemoteControlButton.VolumeDown;
sl@0
   619
					break;
sl@0
   620
				case APPCOMMAND_VOLUME_UP:
sl@0
   621
					rcb = RemoteControlButton.VolumeUp;
sl@0
   622
					break;
sl@0
   623
			}
sl@0
   624
sl@0
   625
			if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
sl@0
   626
				this.ButtonPressed(this, new RemoteControlEventArgs(rcb, GetDevice(param)));
sl@0
   627
		}
sl@0
   628
sl@0
   629
sl@0
   630
		private void ProcessInputCommand(ref Message message)
sl@0
   631
		{
sl@0
   632
			RemoteControlButton rcb = RemoteControlButton.Unknown;
sl@0
   633
			uint dwSize = 0;
sl@0
   634
sl@0
   635
            uint sizeOfHeader=(uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
sl@0
   636
sl@0
   637
            //Get the size of our raw input data.
sl@0
   638
			GetRawInputData(message.LParam,	RID_INPUT, IntPtr.Zero,	ref dwSize,	sizeOfHeader);
sl@0
   639
sl@0
   640
            //Allocate a large enough buffer
sl@0
   641
			IntPtr buffer = Marshal.AllocHGlobal((int) dwSize);
sl@0
   642
			try
sl@0
   643
			{
sl@0
   644
				if(buffer == IntPtr.Zero)
sl@0
   645
					return;
sl@0
   646
sl@0
   647
                //Now read our RAWINPUT data
sl@0
   648
				if (GetRawInputData(message.LParam,	RID_INPUT, buffer, ref dwSize, (uint) Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
sl@0
   649
				{
sl@0
   650
					return;
sl@0
   651
				}
sl@0
   652
sl@0
   653
                //Cast our buffer
sl@0
   654
                RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(buffer, typeof(RAWINPUT));
sl@0
   655
sl@0
   656
                //Check that our raw input is HID
sl@0
   657
                if (raw.header.dwType == RIM_TYPEHID && raw.hid.dwSizeHid>0)
sl@0
   658
				{
sl@0
   659
                    //Allocate a buffer for one HID message
sl@0
   660
					byte[] bRawData = new byte[raw.hid.dwSizeHid];
sl@0
   661
sl@0
   662
                    //Compute the address from which to copy our HID message
sl@0
   663
                    int pRawData = 0;
sl@0
   664
                    unsafe
sl@0
   665
                    {
sl@0
   666
                        byte* source = (byte*)buffer;
sl@0
   667
                        source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID);
sl@0
   668
                        pRawData = (int)source;
sl@0
   669
                    }
sl@0
   670
sl@4
   671
                    //Copy HID message into our buffer
sl@0
   672
                    Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizeHid);
sl@4
   673
                    //bRawData[0] //Not sure what's the meaning of the code at offset 0
sl@4
   674
                    //TODO: check size before access
sl@0
   675
                    int rawData = bRawData[1]; //Get button code
sl@4
   676
                    //Print HID codes in our debug output
sl@2
   677
                    Debug.WriteLine("HID " + raw.hid.dwCount + "/" + raw.hid.dwSizeHid + ":" + bRawData[0].ToString("X2") + bRawData[1].ToString("X2"));
sl@0
   678
sl@3
   679
                    if (Enum.IsDefined(typeof(MceButton), rawData) && rawData!=0) //Our button is a known MCE button
sl@3
   680
                    {
sl@3
   681
                        if (this.ButtonPressed != null) //What's that?
sl@3
   682
                        {
sl@3
   683
                            this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32())));
sl@3
   684
                        }
sl@3
   685
                    }
sl@0
   686
				}
sl@0
   687
				else if(raw.header.dwType == RIM_TYPEMOUSE)
sl@0
   688
				{
sl@0
   689
					// do mouse handling...
sl@0
   690
				}
sl@0
   691
				else if(raw.header.dwType == RIM_TYPEKEYBOARD)
sl@0
   692
				{
sl@0
   693
					// do keyboard handling...
sl@0
   694
				}
sl@0
   695
			}
sl@0
   696
			finally
sl@0
   697
			{
sl@0
   698
				Marshal.FreeHGlobal(buffer);
sl@0
   699
			}
sl@0
   700
		}
sl@0
   701
sl@0
   702
sl@0
   703
		private InputDevice GetDevice(int param)
sl@0
   704
		{
sl@0
   705
			InputDevice inputDevice;
sl@0
   706
sl@0
   707
			switch ((int) (((ushort) (param >> 16)) & FAPPCOMMAND_MASK))
sl@0
   708
			{
sl@0
   709
				case FAPPCOMMAND_OEM:
sl@0
   710
					inputDevice = InputDevice.OEM;
sl@0
   711
					break;
sl@0
   712
				case FAPPCOMMAND_MOUSE:
sl@0
   713
					inputDevice = InputDevice.Mouse;
sl@0
   714
					break;
sl@0
   715
				default:
sl@0
   716
					inputDevice = InputDevice.Key;
sl@0
   717
					break;
sl@0
   718
			}
sl@0
   719
sl@0
   720
			return inputDevice;
sl@0
   721
		}
sl@0
   722
	}
sl@0
   723
}