updated documentation, formatting
authorLars Op den Kamp <lars@opdenkamp.eu>
Mon, 1 Oct 2012 10:57:43 +0000 (12:57 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Mon, 1 Oct 2012 11:12:04 +0000 (13:12 +0200)
include/cec.h
src/LibCecSharp/CecSharpTypes.h
src/LibCecSharp/LibCecSharp.cpp

index e7ee890dcc3e360e4f7c6ff0069d43a011b55e62..40df4ce0267d7764ba891901e8062e2e94c6e36e 100644 (file)
 
 namespace CEC
 {
+  /*!
+   * To create a new libCEC instance, call CECInitialise() and pass the
+   * configuration as argument. Then call Open() to open a connection to the
+   * adapter. Close() closes the connection and CECDestroy() cleans up the
+   * libCEC instance.
+   *
+   * libCEC can send commands to other devices on the CEC bus via the methods
+   * on this interface, and all commands that libCEC received are sent back
+   * to the application via callback methods. The callback methods can be
+   * found in cectypes.h, ICECCallbacks.
+   */
   class ICECAdapter
   {
   public:
index 52c0b2020797bfd702ddbc4aa293395f49947f27..368c52e5399d3c408542b710ba15b56c0b6abf63 100644 (file)
@@ -1,35 +1,35 @@
 #pragma once
 /*
- * This file is part of the libCEC(R) library.
- *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
- * libCEC(R) is an original work, containing original code.
- *
- * libCEC(R) is a trademark of Pulse-Eight Limited.
- *
- * This program is dual-licensed; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Alternatively, you can license this library under a commercial license,
- * please contact Pulse-Eight Licensing for more information.
- *
- * For more information contact:
- * Pulse-Eight Licensing       <license@pulse-eight.com>
- *     http://www.pulse-eight.com/
- *     http://www.pulse-eight.net/
- */
+* This file is part of the libCEC(R) library.
+*
+* libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+* libCEC(R) is an original work, containing original code.
+*
+* libCEC(R) is a trademark of Pulse-Eight Limited.
+*
+* This program is dual-licensed; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*
+* Alternatively, you can license this library under a commercial license,
+* please contact Pulse-Eight Licensing for more information.
+*
+* For more information contact:
+* Pulse-Eight Licensing       <license@pulse-eight.com>
+*     http://www.pulse-eight.com/
+*     http://www.pulse-eight.net/
+*/
 
 #include "../lib/platform/threads/mutex.h"
 #include <vcclr.h>
 
 namespace CecSharp
 {
-       public enum class CecDeviceType
-       {
-               Tv              = 0,
-               RecordingDevice = 1,
-               Reserved        = 2,
-               Tuner           = 3,
-               PlaybackDevice  = 4,
-               AudioSystem     = 5
-       };
-
-       public enum class CecLogLevel
-       {
-               None    = 0,
-               Error   = 1,
-               Warning = 2,
-               Notice  = 4,
-               Traffic = 8,
-               Debug   = 16,
-               All     = 31
-       };
-
-       public enum class CecLogicalAddress
-       {
-               Unknown          = -1, //not a valid logical address
-               Tv               = 0,
-               RecordingDevice1 = 1,
-               RecordingDevice2 = 2,
-               Tuner1           = 3,
-               PlaybackDevice1  = 4,
-               AudioSystem      = 5,
-               Tuner2           = 6,
-               Tuner3           = 7,
-               PlaybackDevice2  = 8,
-               RecordingDevice3 = 9,
-               Tuner4           = 10,
-               PlaybackDevice3  = 11,
-               Reserved1        = 12,
-               Reserved2        = 13,
-               FreeUse          = 14,
-               Unregistered     = 15,
-               Broadcast        = 15
-       };
-
-       public enum class CecAlert
-       {
-               ServiceDevice = 1
-       };
-
-       public enum class CecParameterType
-       {
-               ParameterTypeString = 1
-       };
-
-       public ref class CecParameter
-       {
-       public:
-               CecParameter(CecParameterType type, System::String ^ strData)
-               {
-                       Type = type;
-                       Data = strData;
-               }
-
-               property CecParameterType Type;
-               property System::String ^ Data;
-       };
-
-       public enum class CecPowerStatus
-       {
-               On                      = 0x00,
-               Standby                 = 0x01,
-               InTransitionStandbyToOn = 0x02,
-               InTransitionOnToStandby = 0x03,
-               Unknown                 = 0x99
-       };
-
-       public enum class CecVersion
-       {
-               Unknown = 0x00,
-               V1_2    = 0x01,
-               V1_2A   = 0x02,
-               V1_3    = 0x03,
-               V1_3A   = 0x04,
-               V1_4    = 0x05
-       };
-
-       public enum class CecDisplayControl
-       {
-               DisplayForDefaultTime = 0x00,
-               DisplayUntilCleared   = 0x40,
-               ClearPreviousMessage  = 0x80,
-               ReservedForFutureUse  = 0xC0
-       };
-
-       public enum class CecMenuState
-       {
-               Activated   = 0,
-               Deactivated = 1
-       };
-
-       public enum class CecDeckControlMode
-       {
-               SkipForwardWind   = 1,
-               SkipReverseRewind = 2,
-               Stop              = 3,
-               Eject             = 4
-       };
-
-       public enum class CecDeckInfo
-       {
-               Play               = 0x11,
-               Record             = 0x12,
-               Reverse            = 0x13,
-               Still              = 0x14,
-               Slow               = 0x15,
-               SlowReverse        = 0x16,
-               FastForward        = 0x17,
-               FastReverse        = 0x18,
-               NoMedia            = 0x19,
-               Stop               = 0x1A,
-               SkipForwardWind    = 0x1B,
-               SkipReverseRewind  = 0x1C,
-               IndexSearchForward = 0x1D,
-               IndexSearchReverse = 0x1E,
-               OtherStatus        = 0x1F
-       };
-
-       public enum class CecUserControlCode
-       {
-               Select                      = 0x00,
-               Up                          = 0x01,
-               Down                        = 0x02,
-               Left                        = 0x03,
-               Right                       = 0x04,
-               RightUp                     = 0x05,
-               RightDown                   = 0x06,
-               LeftUp                      = 0x07,
-               LeftDown                    = 0x08,
-               RootMenu                    = 0x09,
-               SetupMenu                   = 0x0A,
-               ContentsMenu                = 0x0B,
-               FavoriteMenu                = 0x0C,
-               Exit                        = 0x0D,
-               Number0                     = 0x20,
-               Number1                     = 0x21,
-               Number2                     = 0x22,
-               Number3                     = 0x23,
-               Number4                     = 0x24,
-               Number5                     = 0x25,
-               Number6                     = 0x26,
-               Number7                     = 0x27,
-               Number8                     = 0x28,
-               Number9                     = 0x29,
-               Dot                         = 0x2A,
-               Enter                       = 0x2B,
-               Clear                       = 0x2C,
-               NextFavorite                = 0x2F,
-               ChannelUp                   = 0x30,
-               ChannelDown                 = 0x31,
-               PreviousChannel             = 0x32,
-               SoundSelect                 = 0x33,
-               InputSelect                 = 0x34,
-               DisplayInformation          = 0x35,
-               Help                        = 0x36,
-               PageUp                      = 0x37,
-               PageDown                    = 0x38,
-               Power                       = 0x40,
-               VolumeUp                    = 0x41,
-               VolumeDown                  = 0x42,
-               Mute                        = 0x43,
-               Play                        = 0x44,
-               Stop                        = 0x45,
-               Pause                       = 0x46,
-               Record                      = 0x47,
-               Rewind                      = 0x48,
-               FastForward                 = 0x49,
-               Eject                       = 0x4A,
-               Forward                     = 0x4B,
-               Backward                    = 0x4C,
-               StopRecord                  = 0x4D,
-               PauseRecord                 = 0x4E,
-               Angle                       = 0x50,
-               SubPicture                  = 0x51,
-               VideoOnDemand               = 0x52,
-               ElectronicProgramGuide      = 0x53,
-               TimerProgramming            = 0x54,
-               InitialConfiguration        = 0x55,
-               PlayFunction                = 0x60,
-               PausePlayFunction           = 0x61,
-               RecordFunction              = 0x62,
-               PauseRecordFunction         = 0x63,
-               StopFunction                = 0x64,
-               MuteFunction                = 0x65,
-               RestoreVolumeFunction       = 0x66,
-               TuneFunction                = 0x67,
-               SelectMediaFunction         = 0x68,
-               SelectAVInputFunction       = 0x69,
-               SelectAudioInputFunction    = 0x6A,
-               PowerToggleFunction         = 0x6B,
-               PowerOffFunction            = 0x6C,
-               PowerOnFunction             = 0x6D,
-               F1Blue                      = 0x71,
-               F2Red                       = 0X72,
-               F3Green                     = 0x73,
-               F4Yellow                    = 0x74,
-               F5                          = 0x75,
-               Data                        = 0x76,
-               Max                         = 0x76,
-               SamsungReturn               = 0x91,
-               Unknown
-       };
-
-       public enum class CecVendorId
-       {
-               Samsung   = 0x0000F0,
-               LG        = 0x00E091,
-               Panasonic = 0x008045,
-               Pioneer   = 0x00E036,
-               Onkyo     = 0x0009B0,
-               Yamaha    = 0x00A0DE,
-               Philips   = 0x00903E,
-               Sony      = 0x080046,
-               Toshiba   = 0x000039,
-               Akai      = 0x0020C7,
-               Benq      = 0x8065E9,
-               Daewoo    = 0x009053,
-               Grundig   = 0x00D0D5,
-               Medion    = 0x000CB8,
-               Sharp     = 0x08001F,
-               Vizio     = 0x6B746D,
-               Unknown   = 0
-       };
-
-       public enum class CecAudioStatus
-       {
-               MuteStatusMask      = 0x80,
-               VolumeStatusMask    = 0x7F,
-               VolumeMin           = 0x00,
-               VolumeMax           = 0x64,
-               VolumeStatusUnknown = 0x7F
-       };
-
-       public enum class CecOpcode
-       {
-               ActiveSource                  = 0x82,
-               ImageViewOn                   = 0x04,
-               TextViewOn                    = 0x0D,
-               InactiveSource                = 0x9D,
-               RequestActiveSource           = 0x85,
-               RoutingChange                 = 0x80,
-               RoutingInformation            = 0x81,
-               SetStreamPath                 = 0x86,
-               Standby                       = 0x36,
-               RecordOff                     = 0x0B,
-               RecordOn                      = 0x09,
-               RecordStatus                  = 0x0A,
-               RecordTvScreen                = 0x0F,
-               ClearAnalogueTimer            = 0x33,
-               ClearDigitalTimer             = 0x99,
-               ClearExternalTimer            = 0xA1,
-               SetAnalogueTimer              = 0x34,
-               SetDigitalTimer               = 0x97,
-               SetExternalTimer              = 0xA2,
-               SetTimerProgramTitle          = 0x67,
-               TimerClearedStatus            = 0x43,
-               TimerStatus                   = 0x35,
-               CecVersion                    = 0x9E,
-               GetCecVersion                 = 0x9F,
-               GivePhysicalAddress           = 0x83,
-               GetMenuLanguage               = 0x91,
-               ReportPhysicalAddress         = 0x84,
-               SetMenuLanguage               = 0x32,
-               DeckControl                   = 0x42,
-               DeckStatus                    = 0x1B,
-               GiveDeckStatus                = 0x1A,
-               Play                          = 0x41,
-               GiveTunerDeviceStatus         = 0x08,
-               SelectAnalogueService         = 0x92,
-               SelectDigtalService           = 0x93,
-               TunerDeviceStatus             = 0x07,
-               TunerStepDecrement            = 0x06,
-               TunerStepIncrement            = 0x05,
-               DeviceVendorId                = 0x87,
-               GiveDeviceVendorId            = 0x8C,
-               VendorCommand                 = 0x89,
-               VendorCommandWithId           = 0xA0,
-               VendorRemoteButtonDown        = 0x8A,
-               VendorRemoteButtonUp          = 0x8B,
-               SetOsdString                  = 0x64,
-               GiveOsdName                   = 0x46,
-               SetOsdName                    = 0x47,
-               MenuRequest                   = 0x8D,
-               MenuStatus                    = 0x8E,
-               UserControlPressed            = 0x44,
-               UserControlRelease            = 0x45,
-               GiveDevicePowerStatus         = 0x8F,
-               ReportPowerStatus             = 0x90,
-               FeatureAbort                  = 0x00,
-               Abort                         = 0xFF,
-               GiveAudioStatus               = 0x71,
-               GiveSystemAudioMode           = 0x7D,
-               ReportAudioStatus             = 0x7A,
-               SetSystemAudioMode            = 0x72,
-               SystemAudioModeRequest        = 0x70,
-               SystemAudioModeStatus         = 0x7E,
-               SetAudioRate                  = 0x9A,
-               /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
-               None                          = 0xFD
-       };
-
-       public enum class CecSystemAudioStatus
-       {
-               Off = 0,
-               On  = 1
-       };
-
-       public enum class CecClientVersion
-       {
-               VersionPre1_5 = 0,
-               Version1_5_0  = 0x1500,
-               Version1_5_1  = 0x1501,
-               Version1_5_2  = 0x1502,
-               Version1_5_3  = 0x1503,
-               Version1_6_0  = 0x1600,
-               Version1_6_1  = 0x1601,
-               Version1_6_2  = 0x1602,
-               Version1_6_3  = 0x1603,
-               Version1_7_0  = 0x1700,
-               Version1_7_1  = 0x1701,
-               Version1_7_2  = 0x1702,
-               Version1_8_0  = 0x1800,
-               Version1_8_1  = 0x1801,
-               Version1_8_2  = 0x1802,
-               Version1_9_0  = 0x1900
-       };
-
-       public enum class CecServerVersion
-       {
-               VersionPre1_5 = 0,
-               Version1_5_0  = 0x1500,
-               Version1_5_1  = 0x1501,
-               Version1_5_2  = 0x1502,
-               Version1_5_3  = 0x1503,
-               Version1_6_0  = 0x1600,
-               Version1_6_1  = 0x1601,
-               Version1_6_2  = 0x1602,
-               Version1_6_3  = 0x1603,
-               Version1_7_0  = 0x1700,
-               Version1_7_1  = 0x1701,
-               Version1_7_2  = 0x1702,
-               Version1_8_0  = 0x1800,
-               Version1_8_1  = 0x1801,
-               Version1_8_2  = 0x1802,
-               Version1_9_0  = 0x1900
-       };
-
-       public ref class CecAdapter
-       {
-       public:
-               CecAdapter(System::String ^ strPath, System::String ^ strComPort)
-               {
-                       Path = strPath;
-                       ComPort = strComPort;
-               }
-
-               property System::String ^ Path;
-               property System::String ^ ComPort;
-       };
-
-       public ref class CecDeviceTypeList
-       {
-       public:
-               CecDeviceTypeList(void)
-               {
-                       Types = gcnew array<CecDeviceType>(5);
-                       for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
-                               Types[iPtr] = CecDeviceType::Reserved;
-               }
-
-               property array<CecDeviceType> ^ Types;
-       };
-
-       public ref class CecLogicalAddresses
-       {
-       public:
-               CecLogicalAddresses(void)
-               {
-                       Addresses = gcnew array<CecLogicalAddress>(16);
-                       Clear();
-               }
-
-               void Clear(void)
-               {
-                       Primary = CecLogicalAddress::Unknown;
-                       for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
-                               Addresses[iPtr] = CecLogicalAddress::Unknown;
-               }
-
-               bool IsSet(CecLogicalAddress iAddress)
-               {
-                       return Addresses[(unsigned int)iAddress] != CecLogicalAddress::Unknown;
-               }
-
-         void Set(CecLogicalAddress iAddress)
-               {
-                       Addresses[(unsigned int)iAddress] = iAddress;
-                       if (Primary == CecLogicalAddress::Unknown)
-                               Primary = iAddress;
-               }
-
-               property CecLogicalAddress          Primary;
-               property array<CecLogicalAddress> ^ Addresses;
-       };
-
-       public ref class CecDatapacket
-       {
-       public:
-               CecDatapacket(void)
-               {
-                       Data = gcnew array<uint8_t>(100);
-                       Size = 0;
-               }
-
-               void PushBack(uint8_t data)
-               {
-                       if (Size < 100)
-                       {
-                               Data[Size] = data;
-                               Size++;
-                       }
-               }
-
-               property array<uint8_t> ^ Data;
-               property uint8_t          Size;
-       };
-
-       public ref class CecCommand
-       {
-       public:
-               CecCommand(CecLogicalAddress iInitiator, CecLogicalAddress iDestination, bool bAck, bool bEom, CecOpcode iOpcode, int32_t iTransmitTimeout)
-               {
-                       Initiator       = iInitiator;
-                       Destination     = iDestination;
-                       Ack             = bAck;
-                       Eom             = bEom;
-                       Opcode          = iOpcode;
-                       OpcodeSet       = true;
-                       TransmitTimeout = iTransmitTimeout;
-                       Parameters      = gcnew CecDatapacket;
-                       Empty           = false;
-               }
-
-               CecCommand(void)
-               {
-                       Initiator       = CecLogicalAddress::Unknown;
-                       Destination     = CecLogicalAddress::Unknown;
-                       Ack             = false;
-                       Eom             = false;
-                       Opcode          = CecOpcode::None;
-                       OpcodeSet       = false;
-                       TransmitTimeout = 0;
-                       Parameters      = gcnew CecDatapacket;
-                       Empty           = true;
-               }
-
-               void PushBack(uint8_t data)
-               {
-                       if (Initiator == CecLogicalAddress::Unknown && Destination == CecLogicalAddress::Unknown)
-                       {
-                               Initiator   = (CecLogicalAddress) (data >> 4);
-                               Destination = (CecLogicalAddress) (data & 0xF);
-                       }
-                       else if (!OpcodeSet)
-                       {
-                               OpcodeSet = true;
-                               Opcode    = (CecOpcode)data;
-                       }
-                       else
-                       {
-                               Parameters->PushBack(data);
-                       }
-               }
-
-               property bool               Empty;
-               property CecLogicalAddress  Initiator;
-               property CecLogicalAddress  Destination;
-               property bool               Ack;
-               property bool               Eom;
-               property CecOpcode          Opcode;
-               property CecDatapacket ^    Parameters;
-               property bool               OpcodeSet;
-               property int32_t            TransmitTimeout;
-       };
-
-       public ref class CecKeypress
-       {
-       public:
-               CecKeypress(CecUserControlCode iKeycode, unsigned int iDuration)
-               {
-                       Keycode  = iKeycode;
-                       Duration = iDuration;
-                       Empty    = false;
-               }
-
-               CecKeypress(void)
-               {
-                       Keycode  = CecUserControlCode::Unknown;
-                       Duration = 0;
-                       Empty    = true;
-               }
-
-               property bool               Empty;
-               property CecUserControlCode Keycode;
-               property unsigned int       Duration;
-       };
-
-       public ref class CecLogMessage
-       {
-       public:
-               CecLogMessage(System::String ^ strMessage, CecLogLevel iLevel, int64_t iTime)
-               {
-                       Message = strMessage;
-                       Level   = iLevel;
-                       Time    = iTime;
-                       Empty   = false;
-               }
-
-               CecLogMessage(void)
-               {
-                       Message = "";
-                       Level   = CecLogLevel::None;
-                       Time    = 0;
-                       Empty   = true;
-               }
-
-               property bool            Empty;
-               property System::String ^Message;
-               property CecLogLevel     Level;
-               property int64_t         Time;
-       };
-
-       ref class CecCallbackMethods; //forward
-       public ref class LibCECConfiguration
-       {
-       public:
-               LibCECConfiguration(void)
-               {
-                       DeviceName          = "";
-                       DeviceTypes         = gcnew CecDeviceTypeList();
-                       AutodetectAddress  = true;
-                       PhysicalAddress     = CEC_DEFAULT_PHYSICAL_ADDRESS;
-                       BaseDevice          = (CecLogicalAddress)CEC_DEFAULT_BASE_DEVICE;
-                       HDMIPort            = CEC_DEFAULT_HDMI_PORT;
-                       ClientVersion       = CecClientVersion::VersionPre1_5;
-                       ServerVersion       = CecServerVersion::VersionPre1_5;
-                       TvVendor            = CecVendorId::Unknown;
-
-                       GetSettingsFromROM  = false;
-                       UseTVMenuLanguage   = CEC_DEFAULT_SETTING_USE_TV_MENU_LANGUAGE == 1;
-                       ActivateSource      = CEC_DEFAULT_SETTING_ACTIVATE_SOURCE == 1;
-
-                       WakeDevices         = gcnew CecLogicalAddresses();
-                       if (CEC_DEFAULT_SETTING_ACTIVATE_SOURCE == 1)
-                               WakeDevices->Set(CecLogicalAddress::Tv);
-
-                       PowerOffDevices     = gcnew CecLogicalAddresses();
-                       if (CEC_DEFAULT_SETTING_POWER_OFF_SHUTDOWN == 1)
-                               PowerOffDevices->Set(CecLogicalAddress::Broadcast);
-
-                       PowerOffScreensaver = CEC_DEFAULT_SETTING_POWER_OFF_SCREENSAVER == 1;
-                       PowerOffOnStandby   = CEC_DEFAULT_SETTING_POWER_OFF_ON_STANDBY == 1;
-
-                       SendInactiveSource  = CEC_DEFAULT_SETTING_SEND_INACTIVE_SOURCE == 1;
-                       LogicalAddresses    = gcnew CecLogicalAddresses();
-                       FirmwareVersion     = 1;
-                       PowerOffDevicesOnStandby = CEC_DEFAULT_SETTING_POWER_OFF_DEVICES_STANDBY == 1;
-                       ShutdownOnStandby   = CEC_DEFAULT_SETTING_SHUTDOWN_ON_STANDBY == 1;
-                       DeviceLanguage      = "";
-               }
-
-               void SetCallbacks(CecCallbackMethods ^callbacks)
-               {
-                       Callbacks = callbacks;
-               }
-
-               void Update(const CEC::libcec_configuration &config)
-               {
-                       DeviceName = gcnew System::String(config.strDeviceName);
-
-                       for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
-                               DeviceTypes->Types[iPtr] = (CecDeviceType)config.deviceTypes.types[iPtr];
-
-                       AutodetectAddress  = config.bAutodetectAddress == 1;
-                       PhysicalAddress    = config.iPhysicalAddress;
-                       BaseDevice         = (CecLogicalAddress)config.baseDevice;
-                       HDMIPort           = config.iHDMIPort;
-                       ClientVersion      = (CecClientVersion)config.clientVersion;
-                       ServerVersion      = (CecServerVersion)config.serverVersion;
-                       TvVendor           = (CecVendorId)config.tvVendor;
-
-                       // player specific settings
-                       GetSettingsFromROM = config.bGetSettingsFromROM == 1;
-                       UseTVMenuLanguage = config.bUseTVMenuLanguage == 1;
-                       ActivateSource = config.bActivateSource == 1;
-
-                       WakeDevices->Clear();
-                       for (uint8_t iPtr = 0; iPtr <= 16; iPtr++)
-                               if (config.wakeDevices[iPtr])
-                                       WakeDevices->Set((CecLogicalAddress)iPtr);
-
-                       PowerOffDevices->Clear();
-                       for (uint8_t iPtr = 0; iPtr <= 16; iPtr++)
-                               if (config.powerOffDevices[iPtr])
-                                       PowerOffDevices->Set((CecLogicalAddress)iPtr);
-
-                       PowerOffScreensaver = config.bPowerOffScreensaver == 1;
-                       PowerOffOnStandby = config.bPowerOffOnStandby == 1;
-
-                       if (ServerVersion >= CecServerVersion::Version1_5_1)
-                               SendInactiveSource = config.bSendInactiveSource == 1;
-
-                       if (ServerVersion >= CecServerVersion::Version1_5_3)
-                       {
-                               LogicalAddresses->Clear();
-                               for (uint8_t iPtr = 0; iPtr <= 16; iPtr++)
-                                       if (config.logicalAddresses[iPtr])
-                                               LogicalAddresses->Set((CecLogicalAddress)iPtr);
-                       }
-
-                       if (ServerVersion >= CecServerVersion::Version1_6_0)
-                       {
-                               FirmwareVersion          = config.iFirmwareVersion;
-                               PowerOffDevicesOnStandby = config.bPowerOffDevicesOnStandby == 1;
-                               ShutdownOnStandby        = config.bShutdownOnStandby == 1;
-                       }
-
-                       if (ServerVersion >= CecServerVersion::Version1_6_2)
-                               DeviceLanguage = gcnew System::String(config.strDeviceLanguage);
-
-                       if (ServerVersion >= CecServerVersion::Version1_6_3)
-                         MonitorOnlyClient = config.bMonitorOnly == 1;
-               }
-
-               property System::String ^     DeviceName;
-               property CecDeviceTypeList ^  DeviceTypes;
-               property bool                 AutodetectAddress;
-               property uint16_t             PhysicalAddress;
-               property CecLogicalAddress    BaseDevice;
-               property uint8_t              HDMIPort;
-               property CecClientVersion     ClientVersion;
-               property CecServerVersion     ServerVersion;
-               property CecVendorId          TvVendor;
-
-               // player specific settings
-               property bool                 GetSettingsFromROM;
-               property bool                 UseTVMenuLanguage;
-               property bool                 ActivateSource;
-               property CecLogicalAddresses ^WakeDevices;
-               property CecLogicalAddresses ^PowerOffDevices;
-               property bool                 PowerOffScreensaver;
-               property bool                 PowerOffOnStandby;
-               property bool                 SendInactiveSource;
-               property CecLogicalAddresses ^LogicalAddresses;
-               property uint16_t             FirmwareVersion;
-               property bool                 PowerOffDevicesOnStandby;
-               property bool                 ShutdownOnStandby;
-               property bool                 MonitorOnlyClient;
-               property System::String ^     DeviceLanguage;
-               property CecCallbackMethods ^ Callbacks;
-       };
-
-       // the callback methods are called by unmanaged code, so we need some delegates for this
-       #pragma unmanaged
-       // unmanaged callback methods
-       typedef int (__stdcall *LOGCB)    (const CEC::cec_log_message &message);
-       typedef int (__stdcall *KEYCB)    (const CEC::cec_keypress &key);
-       typedef int (__stdcall *COMMANDCB)(const CEC::cec_command &command);
-       typedef int (__stdcall *CONFIGCB) (const CEC::libcec_configuration &config);
-       typedef int (__stdcall *ALERTCB)  (const CEC::libcec_alert, const CEC::libcec_parameter &data);
-       typedef int (__stdcall *MENUCB)   (const CEC::cec_menu_state newVal);
-       typedef void (__stdcall *ACTICB)  (const CEC::cec_logical_address logicalAddress, const uint8_t bActivated);
-
-       typedef struct
-       {
-               LOGCB     logCB;
-               KEYCB     keyCB;
-               COMMANDCB commandCB;
-               CONFIGCB  configCB;
-               ALERTCB   alertCB;
-               MENUCB    menuCB;
-               ACTICB    sourceActivatedCB;
-       } UnmanagedCecCallbacks;
-
-       static PLATFORM::CMutex                   g_callbackMutex;
-       static std::vector<UnmanagedCecCallbacks> g_unmanagedCallbacks;
+  public enum class CecDeviceType
+  {
+    Tv              = 0,
+    RecordingDevice = 1,
+    Reserved        = 2,
+    Tuner           = 3,
+    PlaybackDevice  = 4,
+    AudioSystem     = 5
+  };
+
+  public enum class CecLogLevel
+  {
+    None    = 0,
+    Error   = 1,
+    Warning = 2,
+    Notice  = 4,
+    Traffic = 8,
+    Debug   = 16,
+    All     = 31
+  };
+
+  public enum class CecLogicalAddress
+  {
+    Unknown          = -1, //not a valid logical address
+    Tv               = 0,
+    RecordingDevice1 = 1,
+    RecordingDevice2 = 2,
+    Tuner1           = 3,
+    PlaybackDevice1  = 4,
+    AudioSystem      = 5,
+    Tuner2           = 6,
+    Tuner3           = 7,
+    PlaybackDevice2  = 8,
+    RecordingDevice3 = 9,
+    Tuner4           = 10,
+    PlaybackDevice3  = 11,
+    Reserved1        = 12,
+    Reserved2        = 13,
+    FreeUse          = 14,
+    Unregistered     = 15,
+    Broadcast        = 15
+  };
+
+  public enum class CecAlert
+  {
+    ServiceDevice = 1
+  };
+
+  public enum class CecParameterType
+  {
+    ParameterTypeString = 1
+  };
+
+  public ref class CecParameter
+  {
+  public:
+    CecParameter(CecParameterType type, System::String ^ strData)
+    {
+      Type = type;
+      Data = strData;
+    }
+
+    property CecParameterType Type;
+    property System::String ^ Data;
+  };
+
+  public enum class CecPowerStatus
+  {
+    On                      = 0x00,
+    Standby                 = 0x01,
+    InTransitionStandbyToOn = 0x02,
+    InTransitionOnToStandby = 0x03,
+    Unknown                 = 0x99
+  };
+
+  public enum class CecVersion
+  {
+    Unknown = 0x00,
+    V1_2    = 0x01,
+    V1_2A   = 0x02,
+    V1_3    = 0x03,
+    V1_3A   = 0x04,
+    V1_4    = 0x05
+  };
+
+  public enum class CecDisplayControl
+  {
+    DisplayForDefaultTime = 0x00,
+    DisplayUntilCleared   = 0x40,
+    ClearPreviousMessage  = 0x80,
+    ReservedForFutureUse  = 0xC0
+  };
+
+  public enum class CecMenuState
+  {
+    Activated   = 0,
+    Deactivated = 1
+  };
+
+  public enum class CecDeckControlMode
+  {
+    SkipForwardWind   = 1,
+    SkipReverseRewind = 2,
+    Stop              = 3,
+    Eject             = 4
+  };
+
+  public enum class CecDeckInfo
+  {
+    Play               = 0x11,
+    Record             = 0x12,
+    Reverse            = 0x13,
+    Still              = 0x14,
+    Slow               = 0x15,
+    SlowReverse        = 0x16,
+    FastForward        = 0x17,
+    FastReverse        = 0x18,
+    NoMedia            = 0x19,
+    Stop               = 0x1A,
+    SkipForwardWind    = 0x1B,
+    SkipReverseRewind  = 0x1C,
+    IndexSearchForward = 0x1D,
+    IndexSearchReverse = 0x1E,
+    OtherStatus        = 0x1F
+  };
+
+  public enum class CecUserControlCode
+  {
+    Select                      = 0x00,
+    Up                          = 0x01,
+    Down                        = 0x02,
+    Left                        = 0x03,
+    Right                       = 0x04,
+    RightUp                     = 0x05,
+    RightDown                   = 0x06,
+    LeftUp                      = 0x07,
+    LeftDown                    = 0x08,
+    RootMenu                    = 0x09,
+    SetupMenu                   = 0x0A,
+    ContentsMenu                = 0x0B,
+    FavoriteMenu                = 0x0C,
+    Exit                        = 0x0D,
+    Number0                     = 0x20,
+    Number1                     = 0x21,
+    Number2                     = 0x22,
+    Number3                     = 0x23,
+    Number4                     = 0x24,
+    Number5                     = 0x25,
+    Number6                     = 0x26,
+    Number7                     = 0x27,
+    Number8                     = 0x28,
+    Number9                     = 0x29,
+    Dot                         = 0x2A,
+    Enter                       = 0x2B,
+    Clear                       = 0x2C,
+    NextFavorite                = 0x2F,
+    ChannelUp                   = 0x30,
+    ChannelDown                 = 0x31,
+    PreviousChannel             = 0x32,
+    SoundSelect                 = 0x33,
+    InputSelect                 = 0x34,
+    DisplayInformation          = 0x35,
+    Help                        = 0x36,
+    PageUp                      = 0x37,
+    PageDown                    = 0x38,
+    Power                       = 0x40,
+    VolumeUp                    = 0x41,
+    VolumeDown                  = 0x42,
+    Mute                        = 0x43,
+    Play                        = 0x44,
+    Stop                        = 0x45,
+    Pause                       = 0x46,
+    Record                      = 0x47,
+    Rewind                      = 0x48,
+    FastForward                 = 0x49,
+    Eject                       = 0x4A,
+    Forward                     = 0x4B,
+    Backward                    = 0x4C,
+    StopRecord                  = 0x4D,
+    PauseRecord                 = 0x4E,
+    Angle                       = 0x50,
+    SubPicture                  = 0x51,
+    VideoOnDemand               = 0x52,
+    ElectronicProgramGuide      = 0x53,
+    TimerProgramming            = 0x54,
+    InitialConfiguration        = 0x55,
+    PlayFunction                = 0x60,
+    PausePlayFunction           = 0x61,
+    RecordFunction              = 0x62,
+    PauseRecordFunction         = 0x63,
+    StopFunction                = 0x64,
+    MuteFunction                = 0x65,
+    RestoreVolumeFunction       = 0x66,
+    TuneFunction                = 0x67,
+    SelectMediaFunction         = 0x68,
+    SelectAVInputFunction       = 0x69,
+    SelectAudioInputFunction    = 0x6A,
+    PowerToggleFunction         = 0x6B,
+    PowerOffFunction            = 0x6C,
+    PowerOnFunction             = 0x6D,
+    F1Blue                      = 0x71,
+    F2Red                       = 0X72,
+    F3Green                     = 0x73,
+    F4Yellow                    = 0x74,
+    F5                          = 0x75,
+    Data                        = 0x76,
+    Max                         = 0x76,
+    SamsungReturn               = 0x91,
+    Unknown
+  };
+
+  public enum class CecVendorId
+  {
+    Samsung   = 0x0000F0,
+    LG        = 0x00E091,
+    Panasonic = 0x008045,
+    Pioneer   = 0x00E036,
+    Onkyo     = 0x0009B0,
+    Yamaha    = 0x00A0DE,
+    Philips   = 0x00903E,
+    Sony      = 0x080046,
+    Toshiba   = 0x000039,
+    Akai      = 0x0020C7,
+    Benq      = 0x8065E9,
+    Daewoo    = 0x009053,
+    Grundig   = 0x00D0D5,
+    Medion    = 0x000CB8,
+    Sharp     = 0x08001F,
+    Vizio     = 0x6B746D,
+    Unknown   = 0
+  };
+
+  public enum class CecAudioStatus
+  {
+    MuteStatusMask      = 0x80,
+    VolumeStatusMask    = 0x7F,
+    VolumeMin           = 0x00,
+    VolumeMax           = 0x64,
+    VolumeStatusUnknown = 0x7F
+  };
+
+  public enum class CecOpcode
+  {
+    ActiveSource                  = 0x82,
+    ImageViewOn                   = 0x04,
+    TextViewOn                    = 0x0D,
+    InactiveSource                = 0x9D,
+    RequestActiveSource           = 0x85,
+    RoutingChange                 = 0x80,
+    RoutingInformation            = 0x81,
+    SetStreamPath                 = 0x86,
+    Standby                       = 0x36,
+    RecordOff                     = 0x0B,
+    RecordOn                      = 0x09,
+    RecordStatus                  = 0x0A,
+    RecordTvScreen                = 0x0F,
+    ClearAnalogueTimer            = 0x33,
+    ClearDigitalTimer             = 0x99,
+    ClearExternalTimer            = 0xA1,
+    SetAnalogueTimer              = 0x34,
+    SetDigitalTimer               = 0x97,
+    SetExternalTimer              = 0xA2,
+    SetTimerProgramTitle          = 0x67,
+    TimerClearedStatus            = 0x43,
+    TimerStatus                   = 0x35,
+    CecVersion                    = 0x9E,
+    GetCecVersion                 = 0x9F,
+    GivePhysicalAddress           = 0x83,
+    GetMenuLanguage               = 0x91,
+    ReportPhysicalAddress         = 0x84,
+    SetMenuLanguage               = 0x32,
+    DeckControl                   = 0x42,
+    DeckStatus                    = 0x1B,
+    GiveDeckStatus                = 0x1A,
+    Play                          = 0x41,
+    GiveTunerDeviceStatus         = 0x08,
+    SelectAnalogueService         = 0x92,
+    SelectDigtalService           = 0x93,
+    TunerDeviceStatus             = 0x07,
+    TunerStepDecrement            = 0x06,
+    TunerStepIncrement            = 0x05,
+    DeviceVendorId                = 0x87,
+    GiveDeviceVendorId            = 0x8C,
+    VendorCommand                 = 0x89,
+    VendorCommandWithId           = 0xA0,
+    VendorRemoteButtonDown        = 0x8A,
+    VendorRemoteButtonUp          = 0x8B,
+    SetOsdString                  = 0x64,
+    GiveOsdName                   = 0x46,
+    SetOsdName                    = 0x47,
+    MenuRequest                   = 0x8D,
+    MenuStatus                    = 0x8E,
+    UserControlPressed            = 0x44,
+    UserControlRelease            = 0x45,
+    GiveDevicePowerStatus         = 0x8F,
+    ReportPowerStatus             = 0x90,
+    FeatureAbort                  = 0x00,
+    Abort                         = 0xFF,
+    GiveAudioStatus               = 0x71,
+    GiveSystemAudioMode           = 0x7D,
+    ReportAudioStatus             = 0x7A,
+    SetSystemAudioMode            = 0x72,
+    SystemAudioModeRequest        = 0x70,
+    SystemAudioModeStatus         = 0x7E,
+    SetAudioRate                  = 0x9A,
+    /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
+    None                          = 0xFD
+  };
+
+  public enum class CecSystemAudioStatus
+  {
+    Off = 0,
+    On  = 1
+  };
+
+  public enum class CecClientVersion
+  {
+    VersionPre1_5 = 0,
+    Version1_5_0  = 0x1500,
+    Version1_5_1  = 0x1501,
+    Version1_5_2  = 0x1502,
+    Version1_5_3  = 0x1503,
+    Version1_6_0  = 0x1600,
+    Version1_6_1  = 0x1601,
+    Version1_6_2  = 0x1602,
+    Version1_6_3  = 0x1603,
+    Version1_7_0  = 0x1700,
+    Version1_7_1  = 0x1701,
+    Version1_7_2  = 0x1702,
+    Version1_8_0  = 0x1800,
+    Version1_8_1  = 0x1801,
+    Version1_8_2  = 0x1802,
+    Version1_9_0  = 0x1900
+  };
+
+  public enum class CecServerVersion
+  {
+    VersionPre1_5 = 0,
+    Version1_5_0  = 0x1500,
+    Version1_5_1  = 0x1501,
+    Version1_5_2  = 0x1502,
+    Version1_5_3  = 0x1503,
+    Version1_6_0  = 0x1600,
+    Version1_6_1  = 0x1601,
+    Version1_6_2  = 0x1602,
+    Version1_6_3  = 0x1603,
+    Version1_7_0  = 0x1700,
+    Version1_7_1  = 0x1701,
+    Version1_7_2  = 0x1702,
+    Version1_8_0  = 0x1800,
+    Version1_8_1  = 0x1801,
+    Version1_8_2  = 0x1802,
+    Version1_9_0  = 0x1900
+  };
+
+  /// <summary>
+  /// Descriptor of a CEC adapter, 
+  /// </summary>
+  public ref class CecAdapter
+  {
+  public:
+    /// <summary>
+    /// Create a new CEC adapter descriptor
+    /// </summary>
+    /// <param name="path"> The path descriptor for this CEC adapter</param>
+    /// <param name="comPort">The COM port of this CEC adapter</param>
+    CecAdapter(System::String ^ path, System::String ^ comPort)
+    {
+      Path = path;
+      ComPort = comPort;
+    }
+
+    /// <summary>
+    /// The path descriptor for this CEC adapter
+    /// </summary>
+    property System::String ^ Path;
+
+    /// <summary>
+    /// The COM port of this CEC adapter
+    /// </summary>
+    property System::String ^ ComPort;
+  };
+
+  /// <summary>
+  /// A list of CEC device types
+  /// </summary>
+  public ref class CecDeviceTypeList
+  {
+  public:
+    /// <summary>
+    /// Create a new empty list of CEC device types
+    /// </summary>
+    CecDeviceTypeList(void)
+    {
+      Types = gcnew array<CecDeviceType>(5);
+      for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+        Types[iPtr] = CecDeviceType::Reserved;
+    }
+
+    /// <summary>
+    /// The array with CecDeviceType instances in this list.
+    /// </summary>
+    property array<CecDeviceType> ^ Types;
+  };
+
+  /// <summary>
+  /// A list of logical addresses
+  /// </summary>
+  public ref class CecLogicalAddresses
+  {
+  public:
+    /// <summary>
+    /// Create a new empty list of logical addresses
+    /// </summary>
+    CecLogicalAddresses(void)
+    {
+      Addresses = gcnew array<CecLogicalAddress>(16);
+      Clear();
+    }
+
+    /// <summary>
+    /// Clears this list
+    /// </summary>
+    void Clear(void)
+    {
+      Primary = CecLogicalAddress::Unknown;
+      for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+        Addresses[iPtr] = CecLogicalAddress::Unknown;
+    }
+
+    /// <summary>
+    /// Checks whether a logical address is set in this list.
+    /// </summary>
+    /// <param name="address">The address to check.</param>
+    /// <returns>True when set, false otherwise</returns>
+    bool IsSet(CecLogicalAddress address)
+    {
+      return Addresses[(unsigned int)address] != CecLogicalAddress::Unknown;
+    }
+
+    /// <summary>
+    /// Add a logical address to this list (if it's not set already)
+    /// </summary>
+    /// <param name="address">The address to add.</param>
+    void Set(CecLogicalAddress address)
+    {
+      Addresses[(unsigned int)address] = address;
+      if (Primary == CecLogicalAddress::Unknown)
+        Primary = address;
+    }
+
+    /// <summary>
+    /// The primary (first) address in this list
+    /// </summary>
+    property CecLogicalAddress          Primary;
+
+    /// <summary>
+    /// The list of addresses
+    /// </summary>
+    property array<CecLogicalAddress> ^ Addresses;
+  };
+
+
+  /// <summary>
+  /// Byte array used for CEC command parameters
+  /// </summary>
+  public ref class CecDatapacket
+  {
+  public:
+    /// <summary>
+    /// Create a new byte array with maximum size 100
+    /// </summary>
+    CecDatapacket(void)
+    {
+      Data = gcnew array<uint8_t>(100);
+      Size = 0;
+    }
+
+    /// <summary>
+    /// Adds a byte to this byte array
+    /// </summary>
+    /// <param name="data">The byte to add.</param>
+    void PushBack(uint8_t data)
+    {
+      if (Size < 100)
+      {
+        Data[Size] = data;
+        Size++;
+      }
+    }
+
+    /// <summary>
+    /// Array data
+    /// </summary>
+    property array<uint8_t> ^ Data;
+
+    /// <summary>
+    /// Current data size
+    /// </summary>
+    property uint8_t          Size;
+  };
+
+  /// <summary>
+  /// A CEC command that is received or transmitted over the CEC bus
+  /// </summary>
+  public ref class CecCommand
+  {
+  public:
+    /// <summary>
+    /// Create a new CEC command instance
+    /// </summary>
+    /// <param name="initiator">The initiator of the command</param>
+    /// <param name="destination">The receiver of the command</param>
+    /// <param name="ack">True when the ack bit is set, false otherwise</param>
+    /// <param name="eom">True when the eom bit is set, false otherwise</param>
+    /// <param name="opcode">The CEC opcode of this command</param>
+    /// <param name="transmitTimeout">The timeout to use when transmitting a command</param>
+    CecCommand(CecLogicalAddress initiator, CecLogicalAddress destination, bool ack, bool eom, CecOpcode opcode, int32_t transmitTimeout)
+    {
+      Initiator       = initiator;
+      Destination     = destination;
+      Ack             = ack;
+      Eom             = eom;
+      Opcode          = opcode;
+      OpcodeSet       = true;
+      TransmitTimeout = transmitTimeout;
+      Parameters      = gcnew CecDatapacket;
+      Empty           = false;
+    }
+
+    /// <summary>
+    /// Create a new empty CEC command instance
+    /// </summary>
+    CecCommand(void)
+    {
+      Initiator       = CecLogicalAddress::Unknown;
+      Destination     = CecLogicalAddress::Unknown;
+      Ack             = false;
+      Eom             = false;
+      Opcode          = CecOpcode::None;
+      OpcodeSet       = false;
+      TransmitTimeout = 0;
+      Parameters      = gcnew CecDatapacket;
+      Empty           = true;
+    }
+
+    /// <summary>
+    /// Pushes a byte of data to this CEC command
+    /// </summary>
+    /// <param name="data">The byte to add</param>
+    void PushBack(uint8_t data)
+    {
+      if (Initiator == CecLogicalAddress::Unknown && Destination == CecLogicalAddress::Unknown)
+      {
+        Initiator   = (CecLogicalAddress) (data >> 4);
+        Destination = (CecLogicalAddress) (data & 0xF);
+      }
+      else if (!OpcodeSet)
+      {
+        OpcodeSet = true;
+        Opcode    = (CecOpcode)data;
+      }
+      else
+      {
+        Parameters->PushBack(data);
+      }
+    }
+
+    /// <summary>
+    /// True when this command is empty, false otherwise.
+    /// </summary>
+    property bool               Empty;
+    /// <summary>
+    /// The initiator of the command
+    /// </summary>
+    property CecLogicalAddress  Initiator;
+    /// <summary>
+    /// The destination of the command
+    /// </summary>
+    property CecLogicalAddress  Destination;
+    /// <summary>
+    /// True when the ack bit is set, false otherwise
+    /// </summary>
+    property bool               Ack;
+    /// <summary>
+    /// True when the eom bit is set, false otherwise
+    /// </summary>
+    property bool               Eom;
+    /// <summary>
+    /// The CEC opcode of the command
+    /// </summary>
+    property CecOpcode          Opcode;
+    /// <summary>
+    /// The parameters of this command
+    /// </summary>
+    property CecDatapacket ^    Parameters;
+    /// <summary>
+    /// True when an opcode is set, false otherwise (poll message)
+    /// </summary>
+    property bool               OpcodeSet;
+    /// <summary>
+    /// The timeout to use when transmitting a command
+    /// </summary>
+    property int32_t            TransmitTimeout;
+  };
+
+  /// <summary>
+  /// A key press that was received
+  /// </summary>
+  public ref class CecKeypress
+  {
+  public:
+    /// <summary>
+    /// Create a new key press instance
+    /// </summary>
+    /// <param name="keycode">The key code of this key press</param>
+    /// <param name="duration">The duration of this key press in milliseconds</param>
+    CecKeypress(CecUserControlCode keycode, unsigned int duration)
+    {
+      Keycode  = keycode;
+      Duration = duration;
+      Empty    = false;
+    }
+
+    /// <summary>
+    /// Create a new empty key press instance
+    /// </summary>
+    CecKeypress(void)
+    {
+      Keycode  = CecUserControlCode::Unknown;
+      Duration = 0;
+      Empty    = true;
+    }
+
+    /// <summary>
+    /// True when empty, false otherwise
+    /// </summary>
+    property bool               Empty;
+    /// <summary>
+    /// The key code of this key press
+    /// </summary>
+    property CecUserControlCode Keycode;
+    /// <summary>
+    /// The duration of this key press in milliseconds
+    /// </summary>
+    property unsigned int       Duration;
+  };
+
+  /// <summary>
+  /// A log message that libCEC generated
+  /// </summary>
+  public ref class CecLogMessage
+  {
+  public:
+    /// <summary>
+    /// Create a new log message
+    /// </summary>
+    /// <param name="message">The actual message</param>
+    /// <param name="level">The log level, so the application can choose what type information to display</param>
+    /// <param name="time">The timestamp of this message, in milliseconds after connecting</param>
+    CecLogMessage(System::String ^ message, CecLogLevel level, int64_t time)
+    {
+      Message = message;
+      Level   = level;
+      Time    = time;
+      Empty   = false;
+    }
+
+    /// <summary>
+    /// Create a new empty log message
+    /// </summary>
+    CecLogMessage(void)
+    {
+      Message = "";
+      Level   = CecLogLevel::None;
+      Time    = 0;
+      Empty   = true;
+    }
+
+    /// <summary>
+    /// True when empty, false otherwise.
+    /// </summary>
+    property bool            Empty;
+    /// <summary>
+    /// The actual message
+    /// </summary>
+    property System::String ^Message;
+    /// <summary>
+    /// The log level, so the application can choose what type information to display
+    /// </summary>
+    property CecLogLevel     Level;
+    /// <summary>
+    /// The timestamp of this message, in milliseconds after connecting
+    /// </summary>
+    property int64_t         Time;
+  };
+
+  ref class CecCallbackMethods; //forward declaration
+
+  /// <summary>
+  /// The configuration that libCEC uses.
+  /// </summary>
+  public ref class LibCECConfiguration
+  {
+  public:
+    /// <summary>
+    /// Create a new configuration instance with default settings.
+    /// </summary>
+    LibCECConfiguration(void)
+    {
+      DeviceName          = "";
+      DeviceTypes         = gcnew CecDeviceTypeList();
+      AutodetectAddress  = true;
+      PhysicalAddress     = CEC_DEFAULT_PHYSICAL_ADDRESS;
+      BaseDevice          = (CecLogicalAddress)CEC_DEFAULT_BASE_DEVICE;
+      HDMIPort            = CEC_DEFAULT_HDMI_PORT;
+      ClientVersion       = CecClientVersion::VersionPre1_5;
+      ServerVersion       = CecServerVersion::VersionPre1_5;
+      TvVendor            = CecVendorId::Unknown;
+
+      GetSettingsFromROM  = false;
+      UseTVMenuLanguage   = CEC_DEFAULT_SETTING_USE_TV_MENU_LANGUAGE == 1;
+      ActivateSource      = CEC_DEFAULT_SETTING_ACTIVATE_SOURCE == 1;
+
+      WakeDevices         = gcnew CecLogicalAddresses();
+      if (CEC_DEFAULT_SETTING_ACTIVATE_SOURCE == 1)
+        WakeDevices->Set(CecLogicalAddress::Tv);
+
+      PowerOffDevices     = gcnew CecLogicalAddresses();
+      if (CEC_DEFAULT_SETTING_POWER_OFF_SHUTDOWN == 1)
+        PowerOffDevices->Set(CecLogicalAddress::Broadcast);
+
+      PowerOffScreensaver = CEC_DEFAULT_SETTING_POWER_OFF_SCREENSAVER == 1;
+      PowerOffOnStandby   = CEC_DEFAULT_SETTING_POWER_OFF_ON_STANDBY == 1;
+
+      SendInactiveSource  = CEC_DEFAULT_SETTING_SEND_INACTIVE_SOURCE == 1;
+      LogicalAddresses    = gcnew CecLogicalAddresses();
+      FirmwareVersion     = 1;
+      PowerOffDevicesOnStandby = CEC_DEFAULT_SETTING_POWER_OFF_DEVICES_STANDBY == 1;
+      ShutdownOnStandby   = CEC_DEFAULT_SETTING_SHUTDOWN_ON_STANDBY == 1;
+      DeviceLanguage      = "";
+    }
+
+    /// <summary>
+    /// Change the callback method pointers in this configuration instance.
+    /// </summary>
+    /// <param name="callbacks">The new callbacks</param>
+    void SetCallbacks(CecCallbackMethods ^callbacks)
+    {
+      Callbacks = callbacks;
+    }
+
+    /// <summary>
+    /// Update this configuration with data received from libCEC
+    /// </summary>
+    /// <param name="config">The configuration that was received from libCEC</param>
+    void Update(const CEC::libcec_configuration &config)
+    {
+      DeviceName = gcnew System::String(config.strDeviceName);
+
+      for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+        DeviceTypes->Types[iPtr] = (CecDeviceType)config.deviceTypes.types[iPtr];
+
+      AutodetectAddress  = config.bAutodetectAddress == 1;
+      PhysicalAddress    = config.iPhysicalAddress;
+      BaseDevice         = (CecLogicalAddress)config.baseDevice;
+      HDMIPort           = config.iHDMIPort;
+      ClientVersion      = (CecClientVersion)config.clientVersion;
+      ServerVersion      = (CecServerVersion)config.serverVersion;
+      TvVendor           = (CecVendorId)config.tvVendor;
+
+      // player specific settings
+      GetSettingsFromROM = config.bGetSettingsFromROM == 1;
+      UseTVMenuLanguage = config.bUseTVMenuLanguage == 1;
+      ActivateSource = config.bActivateSource == 1;
+
+      WakeDevices->Clear();
+      for (uint8_t iPtr = 0; iPtr <= 16; iPtr++)
+        if (config.wakeDevices[iPtr])
+          WakeDevices->Set((CecLogicalAddress)iPtr);
+
+      PowerOffDevices->Clear();
+      for (uint8_t iPtr = 0; iPtr <= 16; iPtr++)
+        if (config.powerOffDevices[iPtr])
+          PowerOffDevices->Set((CecLogicalAddress)iPtr);
+
+      PowerOffScreensaver = config.bPowerOffScreensaver == 1;
+      PowerOffOnStandby = config.bPowerOffOnStandby == 1;
+
+      if (ServerVersion >= CecServerVersion::Version1_5_1)
+        SendInactiveSource = config.bSendInactiveSource == 1;
+
+      if (ServerVersion >= CecServerVersion::Version1_5_3)
+      {
+        LogicalAddresses->Clear();
+        for (uint8_t iPtr = 0; iPtr <= 16; iPtr++)
+          if (config.logicalAddresses[iPtr])
+            LogicalAddresses->Set((CecLogicalAddress)iPtr);
+      }
+
+      if (ServerVersion >= CecServerVersion::Version1_6_0)
+      {
+        FirmwareVersion          = config.iFirmwareVersion;
+        PowerOffDevicesOnStandby = config.bPowerOffDevicesOnStandby == 1;
+        ShutdownOnStandby        = config.bShutdownOnStandby == 1;
+      }
+
+      if (ServerVersion >= CecServerVersion::Version1_6_2)
+        DeviceLanguage = gcnew System::String(config.strDeviceLanguage);
+
+      if (ServerVersion >= CecServerVersion::Version1_6_3)
+        MonitorOnlyClient = config.bMonitorOnly == 1;
+    }
+
+    /// <summary>
+    /// The device name to use on the CEC bus
+    /// </summary>
+    property System::String ^     DeviceName;
+
+    /// <summary>
+    /// The device type(s) to use on the CEC bus for libCEC
+    /// </summary>
+    property CecDeviceTypeList ^  DeviceTypes;
+
+    /// <summary>
+    /// True to try to autodetect the physical address, false otherwise
+    /// </summary>
+    property bool                 AutodetectAddress;
+
+    /// <summary>
+    /// The physical address that libCEC uses on the CEC bus
+    /// </summary>
+    property uint16_t             PhysicalAddress;
+
+    /// <summary>
+    /// The logical address of the device to which the CEC adapter is connected, only used when PhysicalAddress isn't set
+    /// </summary>
+    property CecLogicalAddress    BaseDevice;
+
+    /// <summary>
+    /// The hdmi port number on the device to which the CEC adapter is connected, only used when PhysicalAddress isn't set
+    /// </summary>
+    property uint8_t              HDMIPort;
+
+    /// <summary>
+    /// The client API version to use
+    /// </summary>
+    property CecClientVersion     ClientVersion;
+
+    /// <summary>
+    /// The version of libCEC
+    /// </summary>
+    property CecServerVersion     ServerVersion;
+
+    /// <summary>
+    /// Override the vendor ID of the TV when set (for quirks mode)
+    /// </summary>
+    property CecVendorId          TvVendor;
+
+    /// <summary>
+    /// True to read the settings from the EEPROM, which possibly override the settings passed here
+    /// </summary>
+    property bool                 GetSettingsFromROM;
+
+    /// <summary>
+    /// Use the language setting of the TV in the client application. Must be implemented by the client application.
+    /// </summary>
+    property bool                 UseTVMenuLanguage;
+
+    /// <summary>
+    /// Make libCEC the active source when starting the client application
+    /// </summary>
+    property bool                 ActivateSource;
+
+    /// <summary>
+    /// List of devices to send a power on command to when starting the client application
+    /// </summary>
+    property CecLogicalAddresses ^WakeDevices;
+
+    /// <summary>
+    /// List of devices to send a standby command to when exiting the client application
+    /// </summary>
+    property CecLogicalAddresses ^PowerOffDevices;
+
+    /// <summary>
+    /// Send standby commands when the client application activates the screensaver. Must be implemented by the client application.
+    /// </summary>
+    property bool                 PowerOffScreensaver;
+
+    /// <summary>
+    /// Power off the PC when the TV powers off. Must be implemented by the client application.
+    /// </summary>
+    property bool                 PowerOffOnStandby;
+
+    /// <summary>
+    /// Send an inactive source message when exiting the client application.
+    /// </summary>
+    property bool                 SendInactiveSource;
+
+    /// <summary>
+    /// The list of logical addresses that libCEC is using
+    /// </summary>
+    property CecLogicalAddresses ^LogicalAddresses;
+
+    /// <summary>
+    /// The firmware version of the adapter to which libCEC is connected
+    /// </summary>
+    property uint16_t             FirmwareVersion;
+
+    /// <summary>
+    /// Send standby commands when the client application activates standby mode (S3). Must be implemented by the client application.
+    /// </summary>
+    property bool                 PowerOffDevicesOnStandby;
+    property bool                 ShutdownOnStandby;
+
+    /// <summary>
+    /// True to start a monitor-only client, false to start a standard client.
+    /// </summary>
+    property bool                 MonitorOnlyClient;
+
+    /// <summary>
+    /// The language code of the menu language that libCEC reports to other devices.
+    /// </summary>
+    property System::String ^     DeviceLanguage;
+
+    /// <summary>
+    /// The callback methods to use.
+    /// </summary>
+    property CecCallbackMethods ^ Callbacks;
+  };
+
+  // the callback methods are called by unmanaged code, so we need some delegates for this
+#pragma unmanaged
+  // unmanaged callback methods
+  typedef int (__stdcall *LOGCB)    (const CEC::cec_log_message &message);
+  typedef int (__stdcall *KEYCB)    (const CEC::cec_keypress &key);
+  typedef int (__stdcall *COMMANDCB)(const CEC::cec_command &command);
+  typedef int (__stdcall *CONFIGCB) (const CEC::libcec_configuration &config);
+  typedef int (__stdcall *ALERTCB)  (const CEC::libcec_alert, const CEC::libcec_parameter &data);
+  typedef int (__stdcall *MENUCB)   (const CEC::cec_menu_state newVal);
+  typedef void (__stdcall *ACTICB)  (const CEC::cec_logical_address logicalAddress, const uint8_t bActivated);
+
+  typedef struct
+  {
+    LOGCB     logCB;
+    KEYCB     keyCB;
+    COMMANDCB commandCB;
+    CONFIGCB  configCB;
+    ALERTCB   alertCB;
+    MENUCB    menuCB;
+    ACTICB    sourceActivatedCB;
+  } UnmanagedCecCallbacks;
+
+  static PLATFORM::CMutex                   g_callbackMutex;
+  static std::vector<UnmanagedCecCallbacks> g_unmanagedCallbacks;
   static CEC::ICECCallbacks                 g_cecCallbacks;
 
-       int CecLogMessageCB(void *cbParam, const CEC::cec_log_message &message)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               return g_unmanagedCallbacks[iPtr].logCB(message);
-               }
-               return 0;
-       }
-
-       int CecKeyPressCB(void *cbParam, const CEC::cec_keypress &key)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               return g_unmanagedCallbacks[iPtr].keyCB(key);
-               }
-               return 0;
-       }
-
-       int CecCommandCB(void *cbParam, const CEC::cec_command &command)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               return g_unmanagedCallbacks[iPtr].commandCB(command);
-               }
-               return 0;
-       }
+  int CecLogMessageCB(void *cbParam, const CEC::cec_log_message &message)
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        return g_unmanagedCallbacks[iPtr].logCB(message);
+    }
+    return 0;
+  }
+
+  int CecKeyPressCB(void *cbParam, const CEC::cec_keypress &key)
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        return g_unmanagedCallbacks[iPtr].keyCB(key);
+    }
+    return 0;
+  }
+
+  int CecCommandCB(void *cbParam, const CEC::cec_command &command)
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        return g_unmanagedCallbacks[iPtr].commandCB(command);
+    }
+    return 0;
+  }
 
   int CecConfigCB(void *cbParam, const CEC::libcec_configuration &config)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               return g_unmanagedCallbacks[iPtr].configCB(config);
-               }
-               return 0;
-       }
-
-       int CecAlertCB(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter &data)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               return g_unmanagedCallbacks[iPtr].alertCB(alert, data);
-               }
-               return 0;
-       }
-
-       int CecMenuCB(void *cbParam, const CEC::cec_menu_state newVal)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               return g_unmanagedCallbacks[iPtr].menuCB(newVal);
-               }
-               return 0;
-       }
-
-       void CecSourceActivatedCB(void *cbParam, const CEC::cec_logical_address logicalAddress, const uint8_t bActivated)
-       {
-               if (cbParam)
-               {
-                       size_t iPtr = (size_t)cbParam;
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
-                               g_unmanagedCallbacks[iPtr].sourceActivatedCB(logicalAddress, bActivated);
-               }
-       }
-
-       #pragma managed
-       // delegates for the unmanaged callback methods
-       public delegate int  CecLogMessageManagedDelegate(const CEC::cec_log_message &);
-       public delegate int  CecKeyPressManagedDelegate(const CEC::cec_keypress &);
-       public delegate int  CecCommandManagedDelegate(const CEC::cec_command &);
-       public delegate int  CecConfigManagedDelegate(const CEC::libcec_configuration &);
-       public delegate int  CecAlertManagedDelegate(const CEC::libcec_alert, const CEC::libcec_parameter &);
-       public delegate int  CecMenuManagedDelegate(const CEC::cec_menu_state newVal);
-       public delegate void CecSourceActivatedManagedDelegate(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated);
-
-       void AssignCallbacks()
-       {
-               g_cecCallbacks.CBCecLogMessage           = CecLogMessageCB;
-               g_cecCallbacks.CBCecKeyPress             = CecKeyPressCB;
-               g_cecCallbacks.CBCecCommand              = CecCommandCB;
-               g_cecCallbacks.CBCecConfigurationChanged = CecConfigCB;
-               g_cecCallbacks.CBCecAlert                = CecAlertCB;
-               g_cecCallbacks.CBCecMenuStateChanged     = CecMenuCB;
-    g_cecCallbacks.CBCecSourceActivated      = CecSourceActivatedCB;
-       }
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        return g_unmanagedCallbacks[iPtr].configCB(config);
+    }
+    return 0;
+  }
+
+  int CecAlertCB(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter &data)
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        return g_unmanagedCallbacks[iPtr].alertCB(alert, data);
+    }
+    return 0;
+  }
+
+  int CecMenuCB(void *cbParam, const CEC::cec_menu_state newVal)
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        return g_unmanagedCallbacks[iPtr].menuCB(newVal);
+    }
+    return 0;
+  }
 
-       // callback method interface
-       public ref class CecCallbackMethods
-       {
-       public:
+  void CecSourceActivatedCB(void *cbParam, const CEC::cec_logical_address logicalAddress, const uint8_t bActivated)
+  {
+    if (cbParam)
+    {
+      size_t iPtr = (size_t)cbParam;
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size())
+        g_unmanagedCallbacks[iPtr].sourceActivatedCB(logicalAddress, bActivated);
+    }
+  }
+
+#pragma managed
+  // delegates for the unmanaged callback methods
+  public delegate int  CecLogMessageManagedDelegate(const CEC::cec_log_message &);
+  public delegate int  CecKeyPressManagedDelegate(const CEC::cec_keypress &);
+  public delegate int  CecCommandManagedDelegate(const CEC::cec_command &);
+  public delegate int  CecConfigManagedDelegate(const CEC::libcec_configuration &);
+  public delegate int  CecAlertManagedDelegate(const CEC::libcec_alert, const CEC::libcec_parameter &);
+  public delegate int  CecMenuManagedDelegate(const CEC::cec_menu_state newVal);
+  public delegate void CecSourceActivatedManagedDelegate(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated);
+
+  void AssignCallbacks()
+  {
+    g_cecCallbacks.CBCecLogMessage           = CecLogMessageCB;
+    g_cecCallbacks.CBCecKeyPress             = CecKeyPressCB;
+    g_cecCallbacks.CBCecCommand              = CecCommandCB;
+    g_cecCallbacks.CBCecConfigurationChanged = CecConfigCB;
+    g_cecCallbacks.CBCecAlert                = CecAlertCB;
+    g_cecCallbacks.CBCecMenuStateChanged     = CecMenuCB;
+    g_cecCallbacks.CBCecSourceActivated      = CecSourceActivatedCB;
+  }
+
+  /// <summary>
+  /// The callback methods that libCEC uses
+  /// </summary>
+  public ref class CecCallbackMethods
+  {
+  public:
     CecCallbackMethods(void)
     {
-                       m_iCallbackPtr = -1;
-                       AssignCallbacks();
+      m_iCallbackPtr = -1;
+      AssignCallbacks();
       m_bHasCallbacks = false;
       m_bDelegatesCreated = false;
     }
 
-         ~CecCallbackMethods(void)
+    ~CecCallbackMethods(void)
     {
       DestroyDelegates();
     }
 
-               size_t GetCallbackPtr(void)
-               {
-                       PLATFORM::CLockObject lock(g_callbackMutex);
-                       return m_iCallbackPtr;
-               }
-
-       protected:
-   !CecCallbackMethods(void)
-   {
-     DestroyDelegates();
-   }
-
-       public:
-               virtual void DisableCallbacks(void)
-               {
-                       DestroyDelegates();
-               }
-
-               virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks)
-               {
+    size_t GetCallbackPtr(void)
+    {
+      PLATFORM::CLockObject lock(g_callbackMutex);
+      return m_iCallbackPtr;
+    }
+
+  protected:
+    !CecCallbackMethods(void)
+    {
+      DestroyDelegates();
+    }
+
+  public:
+    virtual void DisableCallbacks(void)
+    {
+      DestroyDelegates();
+    }
+
+    virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks)
+    {
       CreateDelegates();
-                       if (!m_bHasCallbacks)
-                       {
-                               m_bHasCallbacks = true;
-                               m_callbacks = callbacks;
-                               return true;
-                       }
-
-                       return false;
-               }
-
-               virtual int ReceiveLogMessage(CecLogMessage ^ message)
-               {
-                       return 0;
-               }
-
-               virtual int ReceiveKeypress(CecKeypress ^ key)
-               {
-                       return 0;
-               }
-
-               virtual int ReceiveCommand(CecCommand ^ command)
-               {
-                       return 0;
-               }
-
-               virtual int ConfigurationChanged(LibCECConfiguration ^ config)
-               {
-                       return 0;
-               }
-
-               virtual int ReceiveAlert(CecAlert alert, CecParameter ^ data)
-               {
-                       return 0;
-               }
-
-               virtual int ReceiveMenuStateChange(CecMenuState newVal)
-               {
-                       return 0;
-               }
-
-               virtual void SourceActivated(CecLogicalAddress logicalAddress, bool bActivated)
-               {
-               }
-
-       protected:
-               // managed callback methods
-               int CecLogMessageManaged(const CEC::cec_log_message &message)
-               {
-                       int iReturn(0);
-                       if (m_bHasCallbacks)
-                               iReturn = m_callbacks->ReceiveLogMessage(gcnew CecLogMessage(gcnew System::String(message.message), (CecLogLevel)message.level, message.time));
-                       return iReturn;
-               }
-
-               int CecKeyPressManaged(const CEC::cec_keypress &key)
-               {
-                       int iReturn(0);
-                       if (m_bHasCallbacks)
-                               iReturn = m_callbacks->ReceiveKeypress(gcnew CecKeypress((CecUserControlCode)key.keycode, key.duration));
-                       return iReturn;
-               }
-
-               int CecCommandManaged(const CEC::cec_command &command)
-               {
-                       int iReturn(0);
-                       if (m_bHasCallbacks)
-                       {
-                               CecCommand ^ newCommand = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout);
-                               for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
-                                       newCommand->Parameters->PushBack(command.parameters[iPtr]);
-                               iReturn = m_callbacks->ReceiveCommand(newCommand);
-                       }
-                       return iReturn;
-               }
-
-               int CecConfigManaged(const CEC::libcec_configuration &config)
-               {
-                       int iReturn(0);
-                       if (m_bHasCallbacks)
-                       {
-                               LibCECConfiguration ^netConfig = gcnew LibCECConfiguration();
-                               netConfig->Update(config);
-                               iReturn = m_callbacks->ConfigurationChanged(netConfig);
-                       }
-                       return iReturn;
-               }
-
-               int CecAlertManaged(const CEC::libcec_alert alert, const CEC::libcec_parameter &data)
-               {
-                       int iReturn(0);
-                       if (m_bHasCallbacks)
-                       {
-                               CecParameterType newType = (CecParameterType)data.paramType;
-                               if (newType == CecParameterType::ParameterTypeString)
-                               {
-                                       System::String ^ newData = gcnew System::String((const char *)data.paramData, 0, 128);
-                                       CecParameter ^ newParam = gcnew CecParameter(newType, newData);
-                                   iReturn = m_callbacks->ReceiveAlert((CecAlert)alert, newParam);
-                               }
-                       }
-                       return iReturn;
-               }
-
-               int CecMenuManaged(const CEC::cec_menu_state newVal)
-               {
-                       int iReturn(0);
-                       if (m_bHasCallbacks)
-                       {
-                               iReturn = m_callbacks->ReceiveMenuStateChange((CecMenuState)newVal);
-                       }
-                       return iReturn;
-               }
-
-               void CecSourceActivatedManaged(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated)
-               {
-                       if (m_bHasCallbacks)
-                               m_callbacks->SourceActivated((CecLogicalAddress)logicalAddress, bActivated == 1);
-               }
-
-               void DestroyDelegates()
-               {
+      if (!m_bHasCallbacks)
+      {
+        m_bHasCallbacks = true;
+        m_callbacks = callbacks;
+        return true;
+      }
+
+      return false;
+    }
+
+    /// <summary>
+    /// Called by libCEC to send back a log message to the application
+    /// </summary>
+    /// <param name="message">The log message</param>
+    virtual int ReceiveLogMessage(CecLogMessage ^ message)
+    {
+      return 0;
+    }
+
+    /// <summary>
+    /// Called by libCEC to send back a key press to the application
+    /// </summary>
+    /// <param name="key">The key press command that libCEC received</param>
+    virtual int ReceiveKeypress(CecKeypress ^ key)
+    {
+      return 0;
+    }
+
+    /// <summary>
+    /// Called by libCEC to send back raw CEC data to the application
+    /// </summary>
+    /// <param name="command">The raw CEC data</param>
+    virtual int ReceiveCommand(CecCommand ^ command)
+    {
+      return 0;
+    }
+
+    /// <summary>
+    /// Called by libCEC to send back an updated configuration to the application
+    /// </summary>
+    /// <param name="config">The new configuration</param>
+    virtual int ConfigurationChanged(LibCECConfiguration ^ config)
+    {
+      return 0;
+    }
+
+    /// <summary>
+    /// Called by libCEC to send back an alert message to the application
+    /// </summary>
+    /// <param name="data">The alert message</param>
+    virtual int ReceiveAlert(CecAlert alert, CecParameter ^ data)
+    {
+      return 0;
+    }
+
+    /// <summary>
+    /// Called by libCEC to send back a menu stata change to the application
+    /// </summary>
+    /// <param name="newVal">The new menu state</param>
+    virtual int ReceiveMenuStateChange(CecMenuState newVal)
+    {
+      return 0;
+    }
+
+    /// <summary>
+    /// Called by libCEC to notify the application that the source that is handled by libCEC was (de)activated
+    /// </summary>
+    /// <param name="logicalAddress">The logical address that was (de)activated</param>
+    /// <param name="activated">True when activated, false when deactivated</param>
+    virtual void SourceActivated(CecLogicalAddress logicalAddress, bool activated)
+    {
+    }
+
+  protected:
+    // managed callback methods
+    int CecLogMessageManaged(const CEC::cec_log_message &message)
+    {
+      int iReturn(0);
+      if (m_bHasCallbacks)
+        iReturn = m_callbacks->ReceiveLogMessage(gcnew CecLogMessage(gcnew System::String(message.message), (CecLogLevel)message.level, message.time));
+      return iReturn;
+    }
+
+    int CecKeyPressManaged(const CEC::cec_keypress &key)
+    {
+      int iReturn(0);
+      if (m_bHasCallbacks)
+        iReturn = m_callbacks->ReceiveKeypress(gcnew CecKeypress((CecUserControlCode)key.keycode, key.duration));
+      return iReturn;
+    }
+
+    int CecCommandManaged(const CEC::cec_command &command)
+    {
+      int iReturn(0);
+      if (m_bHasCallbacks)
+      {
+        CecCommand ^ newCommand = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout);
+        for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
+          newCommand->Parameters->PushBack(command.parameters[iPtr]);
+        iReturn = m_callbacks->ReceiveCommand(newCommand);
+      }
+      return iReturn;
+    }
+
+    int CecConfigManaged(const CEC::libcec_configuration &config)
+    {
+      int iReturn(0);
+      if (m_bHasCallbacks)
+      {
+        LibCECConfiguration ^netConfig = gcnew LibCECConfiguration();
+        netConfig->Update(config);
+        iReturn = m_callbacks->ConfigurationChanged(netConfig);
+      }
+      return iReturn;
+    }
+
+    int CecAlertManaged(const CEC::libcec_alert alert, const CEC::libcec_parameter &data)
+    {
+      int iReturn(0);
+      if (m_bHasCallbacks)
+      {
+        CecParameterType newType = (CecParameterType)data.paramType;
+        if (newType == CecParameterType::ParameterTypeString)
+        {
+          System::String ^ newData = gcnew System::String((const char *)data.paramData, 0, 128);
+          CecParameter ^ newParam = gcnew CecParameter(newType, newData);
+          iReturn = m_callbacks->ReceiveAlert((CecAlert)alert, newParam);
+        }
+      }
+      return iReturn;
+    }
+
+    int CecMenuManaged(const CEC::cec_menu_state newVal)
+    {
+      int iReturn(0);
+      if (m_bHasCallbacks)
+      {
+        iReturn = m_callbacks->ReceiveMenuStateChange((CecMenuState)newVal);
+      }
+      return iReturn;
+    }
+
+    void CecSourceActivatedManaged(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated)
+    {
+      if (m_bHasCallbacks)
+        m_callbacks->SourceActivated((CecLogicalAddress)logicalAddress, bActivated == 1);
+    }
+
+    void DestroyDelegates()
+    {
       m_bHasCallbacks = false;
-                       if (m_bDelegatesCreated)
-                       {
+      if (m_bDelegatesCreated)
+      {
         m_bDelegatesCreated = false;
-                               m_logMessageGCHandle.Free();
-                               m_keypressGCHandle.Free();
-                               m_commandGCHandle.Free();
-                               m_alertGCHandle.Free();
-                               m_menuGCHandle.Free();
-                               m_sourceActivatedGCHandle.Free();
-                       }
-               }
+        m_logMessageGCHandle.Free();
+        m_keypressGCHandle.Free();
+        m_commandGCHandle.Free();
+        m_alertGCHandle.Free();
+        m_menuGCHandle.Free();
+        m_sourceActivatedGCHandle.Free();
+      }
+    }
 
     void CreateDelegates()
     {
@@ -1024,87 +1316,87 @@ namespace CecSharp
         // create the delegate method for the log message callback
         m_logMessageDelegate      = gcnew CecLogMessageManagedDelegate(this, &CecCallbackMethods::CecLogMessageManaged);
         m_logMessageGCHandle      = System::Runtime::InteropServices::GCHandle::Alloc(m_logMessageDelegate);
-                               m_logMessageCallback      = static_cast<LOGCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer());
+        m_logMessageCallback      = static_cast<LOGCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer());
 
         // create the delegate method for the keypress callback
         m_keypressDelegate        = gcnew CecKeyPressManagedDelegate(this, &CecCallbackMethods::CecKeyPressManaged);
         m_keypressGCHandle        = System::Runtime::InteropServices::GCHandle::Alloc(m_keypressDelegate);
-                               m_keypressCallback        = static_cast<KEYCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer());
+        m_keypressCallback        = static_cast<KEYCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer());
 
         // create the delegate method for the command callback
         m_commandDelegate         = gcnew CecCommandManagedDelegate(this, &CecCallbackMethods::CecCommandManaged);
         m_commandGCHandle         = System::Runtime::InteropServices::GCHandle::Alloc(m_commandDelegate);
-                               m_commandCallback         = static_cast<COMMANDCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer());
+        m_commandCallback         = static_cast<COMMANDCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer());
 
         // create the delegate method for the configuration change callback
         m_configDelegate          = gcnew CecConfigManagedDelegate(this, &CecCallbackMethods::CecConfigManaged);
         m_configGCHandle          = System::Runtime::InteropServices::GCHandle::Alloc(m_configDelegate);
-                               m_configCallback          = static_cast<CONFIGCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_configDelegate).ToPointer());
+        m_configCallback          = static_cast<CONFIGCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_configDelegate).ToPointer());
 
         // create the delegate method for the alert callback
         m_alertDelegate           = gcnew CecAlertManagedDelegate(this, &CecCallbackMethods::CecAlertManaged);
         m_alertGCHandle           = System::Runtime::InteropServices::GCHandle::Alloc(m_alertDelegate);
-                               m_alertCallback           = static_cast<ALERTCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_alertDelegate).ToPointer());
+        m_alertCallback           = static_cast<ALERTCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_alertDelegate).ToPointer());
 
         // create the delegate method for the menu callback
         m_menuDelegate            = gcnew CecMenuManagedDelegate(this, &CecCallbackMethods::CecMenuManaged);
         m_menuGCHandle            = System::Runtime::InteropServices::GCHandle::Alloc(m_menuDelegate);
-                               m_menuCallback            = static_cast<MENUCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_menuDelegate).ToPointer());
+        m_menuCallback            = static_cast<MENUCB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_menuDelegate).ToPointer());
 
-                         // create the delegate method for the source activated callback
+        // create the delegate method for the source activated callback
         m_sourceActivatedDelegate = gcnew CecSourceActivatedManagedDelegate(this, &CecCallbackMethods::CecSourceActivatedManaged);
         m_sourceActivatedGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_sourceActivatedDelegate);
-                               m_sourceActivatedCallback = static_cast<ACTICB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_sourceActivatedDelegate).ToPointer());
+        m_sourceActivatedCallback = static_cast<ACTICB>(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_sourceActivatedDelegate).ToPointer());
 
         delete context;
 
-                               UnmanagedCecCallbacks unmanagedCallbacks;
-                               unmanagedCallbacks.logCB             = m_logMessageCallback;
-                               unmanagedCallbacks.keyCB             = m_keypressCallback;
-                               unmanagedCallbacks.commandCB         = m_commandCallback;
-                               unmanagedCallbacks.configCB          = m_configCallback;
-                               unmanagedCallbacks.alertCB           = m_alertCallback;
-                               unmanagedCallbacks.menuCB            = m_menuCallback;
-                               unmanagedCallbacks.sourceActivatedCB = m_sourceActivatedCallback;
-
-                               PLATFORM::CLockObject lock(g_callbackMutex);
-                               g_unmanagedCallbacks.push_back(unmanagedCallbacks);
-                               m_iCallbackPtr = g_unmanagedCallbacks.size() - 1;
-                               m_bDelegatesCreated = true;
+        UnmanagedCecCallbacks unmanagedCallbacks;
+        unmanagedCallbacks.logCB             = m_logMessageCallback;
+        unmanagedCallbacks.keyCB             = m_keypressCallback;
+        unmanagedCallbacks.commandCB         = m_commandCallback;
+        unmanagedCallbacks.configCB          = m_configCallback;
+        unmanagedCallbacks.alertCB           = m_alertCallback;
+        unmanagedCallbacks.menuCB            = m_menuCallback;
+        unmanagedCallbacks.sourceActivatedCB = m_sourceActivatedCallback;
+
+        PLATFORM::CLockObject lock(g_callbackMutex);
+        g_unmanagedCallbacks.push_back(unmanagedCallbacks);
+        m_iCallbackPtr = g_unmanagedCallbacks.size() - 1;
+        m_bDelegatesCreated = true;
       }
     }
 
-               CecLogMessageManagedDelegate ^                    m_logMessageDelegate;
-               static System::Runtime::InteropServices::GCHandle m_logMessageGCHandle;
-               LOGCB                                             m_logMessageCallback;
+    CecLogMessageManagedDelegate ^                    m_logMessageDelegate;
+    static System::Runtime::InteropServices::GCHandle m_logMessageGCHandle;
+    LOGCB                                             m_logMessageCallback;
 
-               CecKeyPressManagedDelegate ^                      m_keypressDelegate;
-               static System::Runtime::InteropServices::GCHandle m_keypressGCHandle;
-               KEYCB                                             m_keypressCallback;
+    CecKeyPressManagedDelegate ^                      m_keypressDelegate;
+    static System::Runtime::InteropServices::GCHandle m_keypressGCHandle;
+    KEYCB                                             m_keypressCallback;
 
-               CecCommandManagedDelegate ^                       m_commandDelegate;
-               static System::Runtime::InteropServices::GCHandle m_commandGCHandle;
-               COMMANDCB                                         m_commandCallback;
+    CecCommandManagedDelegate ^                       m_commandDelegate;
+    static System::Runtime::InteropServices::GCHandle m_commandGCHandle;
+    COMMANDCB                                         m_commandCallback;
 
-         CecConfigManagedDelegate ^                        m_configDelegate;
-               static System::Runtime::InteropServices::GCHandle m_configGCHandle;
-               CONFIGCB                                          m_configCallback;
+    CecConfigManagedDelegate ^                        m_configDelegate;
+    static System::Runtime::InteropServices::GCHandle m_configGCHandle;
+    CONFIGCB                                          m_configCallback;
 
-               CecAlertManagedDelegate ^                         m_alertDelegate;
-               static System::Runtime::InteropServices::GCHandle m_alertGCHandle;
-               ALERTCB                                           m_alertCallback;
+    CecAlertManagedDelegate ^                         m_alertDelegate;
+    static System::Runtime::InteropServices::GCHandle m_alertGCHandle;
+    ALERTCB                                           m_alertCallback;
 
-               CecMenuManagedDelegate ^                          m_menuDelegate;
-               static System::Runtime::InteropServices::GCHandle m_menuGCHandle;
-               MENUCB                                            m_menuCallback;
+    CecMenuManagedDelegate ^                          m_menuDelegate;
+    static System::Runtime::InteropServices::GCHandle m_menuGCHandle;
+    MENUCB                                            m_menuCallback;
 
-               CecSourceActivatedManagedDelegate ^               m_sourceActivatedDelegate;
-               static System::Runtime::InteropServices::GCHandle m_sourceActivatedGCHandle;
-               ACTICB                                            m_sourceActivatedCallback;
+    CecSourceActivatedManagedDelegate ^               m_sourceActivatedDelegate;
+    static System::Runtime::InteropServices::GCHandle m_sourceActivatedGCHandle;
+    ACTICB                                            m_sourceActivatedCallback;
 
-               CecCallbackMethods ^ m_callbacks;
-         bool                 m_bHasCallbacks;
+    CecCallbackMethods ^ m_callbacks;
+    bool                 m_bHasCallbacks;
     bool                 m_bDelegatesCreated;
-               size_t               m_iCallbackPtr;
-       };
+    size_t               m_iCallbackPtr;
+  };
 }
index bf33d1f43c9d148c5c471499813e0e60a7471314..073ae774f926ea0b5e87a460a0437ae65409389f 100644 (file)
@@ -1,34 +1,34 @@
 /*
- * This file is part of the libCEC(R) library.
- *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
- * libCEC(R) is an original work, containing original code.
- *
- * libCEC(R) is a trademark of Pulse-Eight Limited.
- *
- * This program is dual-licensed; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * Alternatively, you can license this library under a commercial license,
- * please contact Pulse-Eight Licensing for more information.
- *
- * For more information contact:
- * Pulse-Eight Licensing       <license@pulse-eight.com>
- *     http://www.pulse-eight.com/
- *     http://www.pulse-eight.net/
- */
+* This file is part of the libCEC(R) library.
+*
+* libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+* libCEC(R) is an original work, containing original code.
+*
+* libCEC(R) is a trademark of Pulse-Eight Limited.
+*
+* This program is dual-licensed; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*
+* Alternatively, you can license this library under a commercial license,
+* please contact Pulse-Eight Licensing for more information.
+*
+* For more information contact:
+* Pulse-Eight Licensing       <license@pulse-eight.com>
+*     http://www.pulse-eight.com/
+*     http://www.pulse-eight.net/
+*/
 
 #include "CecSharpTypes.h"
 #using <System.dll>
@@ -40,720 +40,568 @@ using namespace msclr::interop;
 
 namespace CecSharp
 {
-       public ref class LibCecSharp : public CecCallbackMethods
-       {
-       public:
-         LibCecSharp(LibCECConfiguration ^config)
-               {
+  /// <summary>
+  /// Create a LibCecSharp instance and pass the configuration as argument.
+  /// Then call Open() to open a connection to the adapter. Close() closes the
+  /// connection.
+  ///
+  /// libCEC can send commands to other devices on the CEC bus via the methods
+  /// on this interface, and all commands that libCEC received are sent back
+  /// to the application via callback methods. The callback methods can be
+  /// found in CecSharpTypes.h, CecCallbackMethods.
+  /// </summary>
+  public ref class LibCecSharp : public CecCallbackMethods
+  {
+  public:
+    /// <summary>
+    /// Create a new LibCecSharp instance.
+    /// </summary>
+    /// <param name="config">The configuration to pass to libCEC.</param>
+    LibCecSharp(LibCECConfiguration ^config)
+    {
       m_callbacks = config->Callbacks;
-                       CecCallbackMethods::EnableCallbacks(m_callbacks);
-                       if (!InitialiseLibCec(config))
-                               throw gcnew Exception("Could not initialise LibCecSharp");
-               }
-
-               LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
-               {
-      m_callbacks = gcnew CecCallbackMethods();
-                       LibCECConfiguration ^config = gcnew LibCECConfiguration();
-                       config->SetCallbacks(this);
-                       config->DeviceName  = strDeviceName;
-                       config->DeviceTypes = deviceTypes;
-                       if (!InitialiseLibCec(config))
-                               throw gcnew Exception("Could not initialise LibCecSharp");
-               }
-          
-               ~LibCecSharp(void)
-               {
-                       Close();
-                       m_libCec = NULL;
-               }
-
-       private:
-               !LibCecSharp(void)
-               {
-                       Close();
-                       m_libCec = NULL;
-               }
-
-               bool InitialiseLibCec(LibCECConfiguration ^config)
-               {
-                       marshal_context ^ context = gcnew marshal_context();
-                       libcec_configuration libCecConfig;
-                       ConvertConfiguration(context, config, libCecConfig);
-
-                       m_libCec = (ICECAdapter *) CECInitialise(&libCecConfig);
-                       config->Update(libCecConfig);
-
-                       delete context;
-                       return m_libCec != NULL;
-               }
-
-         void ConvertConfiguration(marshal_context ^context, LibCECConfiguration ^netConfig, CEC::libcec_configuration &config)
-               {
-                       config.Clear();
-
-                       const char *strDeviceName = context->marshal_as<const char*>(netConfig->DeviceName);
-                       memcpy_s(config.strDeviceName, 13, strDeviceName, 13);
-                       for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
-                               config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr];
-
-                       config.bAutodetectAddress   = netConfig->AutodetectAddress ? 1 : 0;
-                       config.iPhysicalAddress     = netConfig->PhysicalAddress;
-                       config.baseDevice           = (cec_logical_address)netConfig->BaseDevice;
-                       config.iHDMIPort            = netConfig->HDMIPort;
-                       config.clientVersion        = (cec_client_version)netConfig->ClientVersion;
-                       config.bGetSettingsFromROM  = netConfig->GetSettingsFromROM ? 1 : 0;
-                       config.bActivateSource      = netConfig->ActivateSource ? 1 : 0;
-                       config.tvVendor             = (cec_vendor_id)netConfig->TvVendor;
-                       config.wakeDevices.Clear();
-                       for (int iPtr = 0; iPtr < 16; iPtr++)
-                       {
-                               if (netConfig->WakeDevices->IsSet((CecLogicalAddress)iPtr))
-                                       config.wakeDevices.Set((cec_logical_address)iPtr);
-                       }
-                       config.powerOffDevices.Clear();
-                       for (int iPtr = 0; iPtr < 16; iPtr++)
-                       {
-                               if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr))
-                                       config.powerOffDevices.Set((cec_logical_address)iPtr);
-                       }
-                       config.bPowerOffScreensaver = netConfig->PowerOffScreensaver ? 1 : 0;
-                       config.bPowerOffOnStandby   = netConfig->PowerOffOnStandby ? 1 : 0;
-
-                       if (netConfig->ServerVersion >= CecServerVersion::Version1_5_1)
-                               config.bSendInactiveSource  = netConfig->SendInactiveSource ? 1 : 0;
-
-                       if (netConfig->ServerVersion >= CecServerVersion::Version1_6_0)
-                       {
-                               config.bPowerOffDevicesOnStandby  = netConfig->PowerOffDevicesOnStandby ? 1 : 0;
-                               config.bShutdownOnStandby         = netConfig->ShutdownOnStandby ? 1 : 0;
-                       }
-
-                       if (netConfig->ServerVersion >= CecServerVersion::Version1_6_2)
-                       {
-                               const char *strDeviceLanguage = context->marshal_as<const char*>(netConfig->DeviceLanguage);
-                               memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3);
-                       }
-
-                       if (netConfig->ServerVersion >= CecServerVersion::Version1_6_3)
-                         config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0;
-
-                       config.callbacks = &g_cecCallbacks;
-               }
-
-       public:
-               /// <summary>
+      CecCallbackMethods::EnableCallbacks(m_callbacks);
+      if (!InitialiseLibCec(config))
+        throw gcnew Exception("Could not initialise LibCecSharp");
+    }
+
+    ~LibCecSharp(void)
+    {
+      Close();
+      m_libCec = NULL;
+    }
+
+    /// <summary>
     /// Try to find all connected CEC adapters.
     /// </summary>
     /// <param name="path">The path filter for adapters. Leave empty to return all adapters.</param>
     /// <returns>The adapters that were found.</returns>
-               array<CecAdapter ^> ^ FindAdapters(String ^ path)
-               {
-                       cec_adapter *devices = new cec_adapter[10];
+    array<CecAdapter ^> ^ FindAdapters(String ^ path)
+    {
+      cec_adapter *devices = new cec_adapter[10];
 
-                       marshal_context ^ context = gcnew marshal_context();
-                       const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
+      marshal_context ^ context = gcnew marshal_context();
+      const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
 
-                       uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
+      uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
 
-                       array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
-                       for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
-                               adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
+      array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
+      for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
+        adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
 
-                       delete devices;
-                       delete context;
-                       return adapters;
-               }
+      delete devices;
+      delete context;
+      return adapters;
+    }
 
     /// <summary>
     /// Open a connection to the CEC adapter.
     /// </summary>
-               /// <param name="strPort">The COM port of the adapter</param>
-               /// <param name="iTimeoutMs">Connection timeout in milliseconds</param>
+    /// <param name="strPort">The COM port of the adapter</param>
+    /// <param name="iTimeoutMs">Connection timeout in milliseconds</param>
     /// <returns>True when a connection was opened, false otherwise.</returns>
-               bool Open(String ^ strPort, int iTimeoutMs)
-               {
+    bool Open(String ^ strPort, int iTimeoutMs)
+    {
       CecCallbackMethods::EnableCallbacks(m_callbacks);
       EnableCallbacks(m_callbacks);
-                       marshal_context ^ context = gcnew marshal_context();
-                       const char* strPortC = context->marshal_as<const char*>(strPort);
-                       bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
-                       delete context;
-                       return bReturn;
-               }
-
-               /// <summary>
+      marshal_context ^ context = gcnew marshal_context();
+      const char* strPortC = context->marshal_as<const char*>(strPort);
+      bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
+      delete context;
+      return bReturn;
+    }
+
+    /// <summary>
     /// Close the connection to the CEC adapter
     /// </summary>
-               void Close(void)
-               {
-                       DisableCallbacks();
-                       m_libCec->Close();
-               }
+    void Close(void)
+    {
+      DisableCallbacks();
+      m_libCec->Close();
+    }
 
-               /// <summary>
+    /// <summary>
     /// Disable all calls to callback methods.
     /// </summary>
-               virtual void DisableCallbacks(void) override
-               {
-                       // delete the callbacks, since these might already have been destroyed in .NET
-                       CecCallbackMethods::DisableCallbacks();
-                       if (m_libCec)
-                               m_libCec->EnableCallbacks(NULL, NULL);
-               }
+    virtual void DisableCallbacks(void) override
+    {
+      // delete the callbacks, since these might already have been destroyed in .NET
+      CecCallbackMethods::DisableCallbacks();
+      if (m_libCec)
+        m_libCec->EnableCallbacks(NULL, NULL);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Enable or change the callback methods that libCEC uses to send changes to the client application.
     /// </summary>
     /// <param name="callbacks">The new callback methods to use.</param>
     /// <returns>True when the callbacks were changed, false otherwise</returns>
-               virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override
-               {
-                       if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks))
-                               return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks);
+    virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override
+    {
+      if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks))
+        return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks);
 
-                       return false;
-               }
+      return false;
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sends a ping command to the adapter, to check if it's responding.
     /// </summary>
     /// <returns>True when the ping was succesful, false otherwise</returns>
-               bool PingAdapter(void)
-               {
-                       return m_libCec->PingAdapter();
-               }
+    bool PingAdapter(void)
+    {
+      return m_libCec->PingAdapter();
+    }
 
-               /// <summary>
+    /// <summary>
     /// Start the bootloader of the CEC adapter. Closes the connection when successful.
     /// </summary>
     /// <returns>True when the command was sent successfully, false otherwise.</returns>
-               bool StartBootloader(void)
-               {
-                       return m_libCec->StartBootloader();
-               }
-
-               /// <summary>
-    /// Get the minimal version of libCEC that this version of libCEC can interface with.
-    /// </summary>
-               /// <remarks>Deprecated: use LibCECConfiguration instead</remarks>
-    /// <returns>The minimal version</returns>
-               int GetMinLibVersion(void)
-               {
-                       return m_libCec->GetMinLibVersion();
-               }
-
-               /// <summary>
-    /// Get the major version of libCEC.
-    /// </summary>
-               /// <remarks>Deprecated: use LibCECConfiguration instead</remarks>
-    /// <returns>The major version</returns>
-               int GetLibVersionMajor(void)
-               {
-                       return m_libCec->GetLibVersionMajor();
-               }
-
-               /// <summary>
-    /// Get the minor version of libCEC.
-    /// </summary>
-               /// <remarks>Deprecated: use LibCECConfiguration instead</remarks>
-    /// <returns>The minor version</returns>
-               int GetLibVersionMinor(void)
-               {
-                       return m_libCec->GetLibVersionMinor();
-               }
-
-    /// <summary>
-    /// Get the next log message from the buffer, if there is one.
-    /// </summary>
-               /// <remarks>Deprecated: use callback methods instead</remarks>
-    /// <returns>The next log message in the buffer, or an empty message if there is none</returns>
-               CecLogMessage ^ GetNextLogMessage(void)
-               {
-                       cec_log_message msg;
-                       if (m_libCec->GetNextLogMessage(&msg))
-                       {
-                               return gcnew CecLogMessage(gcnew String(msg.message), (CecLogLevel)msg.level, msg.time);
-                       }
-
-                       return gcnew CecLogMessage();
-               }
-
-    /// <summary>
-    /// Get the next keypress from the buffer, if there is one.
-    /// </summary>
-               /// <remarks>Deprecated: use callback methods instead</remarks>
-    /// <returns>The next keypress in the buffer, or an empty keypress if there is none</returns>
-               CecKeypress ^ GetNextKeypress(void)
-               {
-                       cec_keypress key;
-                       if (m_libCec->GetNextKeypress(&key))
-                       {
-                               return gcnew CecKeypress((CecUserControlCode)key.keycode, key.duration);
-                       }
-
-                       return gcnew CecKeypress();
-               }
-
-               /// <summary>
-    /// Get the next CEC command that was received from the buffer, if there is one.
-    /// </summary>
-               /// <remarks>Deprecated: use callback methods instead</remarks>
-    /// <returns>The next CEC command in the buffer, or an empty CEC command if there is none</returns>
-               CecCommand ^ GetNextCommand(void)
-               {
-                       cec_command command;
-                       if (m_libCec->GetNextCommand(&command))
-                       {
-                               CecCommand ^ retVal = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout);
-                               for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
-                                       retVal->Parameters->PushBack(command.parameters[iPtr]);
-                               return retVal;
-                       }
-
-                       return gcnew CecCommand();
-               }
-
-               /// <summary>
+    bool StartBootloader(void)
+    {
+      return m_libCec->StartBootloader();
+    }
+
+    /// <summary>
     /// Transmit a raw CEC command over the CEC line.
     /// </summary>
     /// <param name="command">The command to transmit</param>
     /// <returns>True when the data was sent and acked, false otherwise.</returns>
-               bool Transmit(CecCommand ^ command)
-               {
-                       cec_command ccommand;
-                       cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
-                       ccommand.transmit_timeout = command->TransmitTimeout;
-                       ccommand.eom              = command->Eom;
-                       ccommand.ack              = command->Ack;
-                       for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
-                               ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
-
-                       return m_libCec->Transmit(ccommand);
-               }
-
-               /// <summary>
+    bool Transmit(CecCommand ^ command)
+    {
+      cec_command ccommand;
+      cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
+      ccommand.transmit_timeout = command->TransmitTimeout;
+      ccommand.eom              = command->Eom;
+      ccommand.ack              = command->Ack;
+      for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
+        ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
+
+      return m_libCec->Transmit(ccommand);
+    }
+
+    /// <summary>
     /// Change the logical address on the CEC bus of the CEC adapter. libCEC automatically assigns a logical address, and this method is only available for debugging purposes.
     /// </summary>
     /// <param name="logicalAddress">The CEC adapter's new logical address.</param>
     /// <returns>True when the logical address was set successfully, false otherwise.</returns>
-               bool SetLogicalAddress(CecLogicalAddress logicalAddress)
-               {
-                       return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
-               }
+    bool SetLogicalAddress(CecLogicalAddress logicalAddress)
+    {
+      return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Change the physical address (HDMI port) of the CEC adapter. libCEC will try to autodetect the physical address when connecting. If it did, it's set in libcec_configuration.
     /// </summary>
     /// <param name="physicalAddress">The CEC adapter's new physical address.</param>
     /// <returns>True when the physical address was set successfully, false otherwise.</returns>
-               bool SetPhysicalAddress(uint16_t physicalAddress)
-               {
-                       return m_libCec->SetPhysicalAddress(physicalAddress);
-               }
+    bool SetPhysicalAddress(uint16_t physicalAddress)
+    {
+      return m_libCec->SetPhysicalAddress(physicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Power on the given CEC capable devices. If CECDEVICE_BROADCAST is used, then wakeDevice in libcec_configuration will be used.
     /// </summary>
     /// <param name="logicalAddress">The logical address to power on.</param>
     /// <returns>True when the command was sent succesfully, false otherwise.</returns>
-               bool PowerOnDevices(CecLogicalAddress logicalAddress)
-               {
-                       return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
-               }
+    bool PowerOnDevices(CecLogicalAddress logicalAddress)
+    {
+      return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Put the given CEC capable devices in standby mode. If CECDEVICE_BROADCAST is used, then standbyDevices in libcec_configuration will be used.
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to put in standby.</param>
     /// <returns>True when the command was sent succesfully, false otherwise.</returns>
-               bool StandbyDevices(CecLogicalAddress logicalAddress)
-               {
-                       return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
-               }
+    bool StandbyDevices(CecLogicalAddress logicalAddress)
+    {
+      return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sends a POLL message to a device, to check if it's present and responding.
     /// </summary>
     /// <param name="logicalAddress">The device to send the message to.</param>
     /// <returns>True if the POLL was acked, false otherwise.</returns>
-               bool PollDevice(CecLogicalAddress logicalAddress)
-               {
-                       return m_libCec->PollDevice((cec_logical_address) logicalAddress);
-               }
+    bool PollDevice(CecLogicalAddress logicalAddress)
+    {
+      return m_libCec->PollDevice((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Change the active source to a device type handled by libCEC. Use CEC_DEVICE_TYPE_RESERVED to make the default type used by libCEC active.
     /// </summary>
     /// <param name="type">The new active source. Use CEC_DEVICE_TYPE_RESERVED to use the primary type</param>
     /// <returns>True when the command was sent succesfully, false otherwise.</returns>
-               bool SetActiveSource(CecDeviceType type)
-               {
-                       return m_libCec->SetActiveSource((cec_device_type) type);
-               }
+    bool SetActiveSource(CecDeviceType type)
+    {
+      return m_libCec->SetActiveSource((cec_device_type) type);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Change the deck control mode, if this adapter is registered as playback or recording device.
     /// </summary>
     /// <param name="mode">The new control mode.</param>
-               /// <param name="sendUpdate">True to send the new status over the CEC line.</param>
+    /// <param name="sendUpdate">True to send the new status over the CEC line.</param>
     /// <returns>True if set, false otherwise.</returns>
-               bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
-               {
-                       return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
-               }
+    bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
+    {
+      return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Change the deck info, if this adapter is a playback or recording device.
     /// </summary>
     /// <param name="info">The new deck info.</param>
-               /// <param name="sendUpdate">True to send the new status over the CEC line.</param>
+    /// <param name="sendUpdate">True to send the new status over the CEC line.</param>
     /// <returns>True if set, false otherwise.</returns>
-               bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
-               {
-                       return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
-               }
+    bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
+    {
+      return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Broadcast a message that notifies connected CEC capable devices that this device is no longer the active source.
     /// </summary>
     /// <returns>True when the command was sent succesfully, false otherwise.</returns>
-               bool SetInactiveView(void)
-               {
-                       return m_libCec->SetInactiveView();
-               }
+    bool SetInactiveView(void)
+    {
+      return m_libCec->SetInactiveView();
+    }
 
-               /// <summary>
+    /// <summary>
     /// Change the menu state. This value is already changed by libCEC automatically if a device is (de)activated.
     /// </summary>
     /// <param name="state">The new state.</param>
-               /// <param name="sendUpdate">True to send the new status over the CEC line.</param>
+    /// <param name="sendUpdate">True to send the new status over the CEC line.</param>
     /// <returns>True if set, false otherwise.</returns>
-               bool SetMenuState(CecMenuState state, bool sendUpdate)
-               {
-                       return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
-               }
+    bool SetMenuState(CecMenuState state, bool sendUpdate)
+    {
+      return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Display a message on the device with the given logical address. Not supported by most TVs.
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to display the message on.</param>
-               /// <param name="duration">The duration of the message</param>
-               /// <param name="message">The message to display.</param>
+    /// <param name="duration">The duration of the message</param>
+    /// <param name="message">The message to display.</param>
     /// <returns>True when the command was sent, false otherwise.</returns>
-               bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
-               {
-                       marshal_context ^ context = gcnew marshal_context();
-                       const char* strMessageC = context->marshal_as<const char*>(message);
+    bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
+    {
+      marshal_context ^ context = gcnew marshal_context();
+      const char* strMessageC = context->marshal_as<const char*>(message);
 
-                       bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
+      bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
 
-                       delete context;
-                       return bReturn;
-               }
+      delete context;
+      return bReturn;
+    }
 
-               /// <summary>
+    /// <summary>
     /// Enable or disable monitoring mode, for debugging purposes. If monitoring mode is enabled, libCEC won't respond to any command, but only log incoming data.
     /// </summary>
     /// <param name="enable">True to enable, false to disable.</param>
     /// <returns>True when switched successfully, false otherwise.</returns>
-               bool SwitchMonitoring(bool enable)
-               {
-                       return m_libCec->SwitchMonitoring(enable);
-               }
+    bool SwitchMonitoring(bool enable)
+    {
+      return m_libCec->SwitchMonitoring(enable);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the CEC version of the device with the given logical address
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to get the CEC version for.</param>
     /// <returns>The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched.</returns>
-               CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
-               {
-                       return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
-               }
+    CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
+    {
+      return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the menu language of the device with the given logical address
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to get the menu language for.</param>
     /// <returns>The requested menu language.</returns>
-               String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
-               {
-                       cec_menu_language lang;
-                       if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
-                       {
-                               return gcnew String(lang.language);
-                       }
-
-                       return gcnew String("");
-               }
-
-               /// <summary>
+    String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
+    {
+      cec_menu_language lang;
+      if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
+      {
+        return gcnew String(lang.language);
+      }
+
+      return gcnew String("");
+    }
+
+    /// <summary>
     /// Get the vendor ID of the device with the given logical address.
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to get the vendor ID for.</param>
     /// <returns>The vendor ID or 0 if it wasn't found.</returns>
-               CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
-               {
-                       return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
-               }
+    CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
+    {
+      return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the power status of the device with the given logical address.
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to get the power status for.</param>
     /// <returns>The power status or CEC_POWER_STATUS_UNKNOWN if it wasn't found.</returns>
-               CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
-               {
-                       return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
-               }
+    CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
+    {
+      return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Tell libCEC to poll for active devices on the bus.
     /// </summary>
-               void RescanActiveDevices(void)
-               {
-                       m_libCec->RescanActiveDevices();
-               }
+    void RescanActiveDevices(void)
+    {
+      m_libCec->RescanActiveDevices();
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the logical addresses of the devices that are active on the bus, including those handled by libCEC.
     /// </summary>
     /// <returns>The logical addresses of the active devices</returns>
-               CecLogicalAddresses ^ GetActiveDevices(void)
-               {
-                       CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
-                       unsigned int iDevices = 0;
+    CecLogicalAddresses ^ GetActiveDevices(void)
+    {
+      CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
+      unsigned int iDevices = 0;
 
-                       cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
+      cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
 
-                       for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
-                               if (activeDevices[iPtr])
-                                       retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
+      for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+        if (activeDevices[iPtr])
+          retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
 
-                       return retVal;
-               }
+      return retVal;
+    }
 
-               /// <summary>
+    /// <summary>
     /// Check whether a device is active on the bus.
     /// </summary>
     /// <param name="logicalAddress">The address to check.</param>
     /// <returns>True when active, false otherwise.</returns>
-               bool IsActiveDevice(CecLogicalAddress logicalAddress)
-               {
-                       return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
-               }
+    bool IsActiveDevice(CecLogicalAddress logicalAddress)
+    {
+      return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Check whether a device of the given type is active on the bus.
     /// </summary>
     /// <param name="type">The type to check.</param>
     /// <returns>True when active, false otherwise.</returns>
-               bool IsActiveDeviceType(CecDeviceType type)
-               {
-                       return m_libCec->IsActiveDeviceType((cec_device_type)type);
-               }
+    bool IsActiveDeviceType(CecDeviceType type)
+    {
+      return m_libCec->IsActiveDeviceType((cec_device_type)type);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Changes the active HDMI port.
     /// </summary>
     /// <param name="address">The device to which this libCEC is connected.</param>
-               /// <param name="port">The new port number.</param>
+    /// <param name="port">The new port number.</param>
     /// <returns>True when changed, false otherwise.</returns>
-               bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
-               {
-                       return m_libCec->SetHDMIPort((cec_logical_address)address, port);
-               }
+    bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
+    {
+      return m_libCec->SetHDMIPort((cec_logical_address)address, port);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sends a volume up keypress to an audiosystem if it's present.
     /// </summary>
     /// <param name="sendRelease">Send a key release after the keypress.</param>
     /// <returns>The new audio status.</returns>
-               uint8_t VolumeUp(bool sendRelease)
-               {
-                       return m_libCec->VolumeUp(sendRelease);
-               }
+    uint8_t VolumeUp(bool sendRelease)
+    {
+      return m_libCec->VolumeUp(sendRelease);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sends a volume down keypress to an audiosystem if it's present.
     /// </summary>
     /// <param name="sendRelease">Send a key release after the keypress.</param>
     /// <returns>The new audio status.</returns>
-               uint8_t VolumeDown(bool sendRelease)
-               {
-                       return m_libCec->VolumeDown(sendRelease);
-               }
+    uint8_t VolumeDown(bool sendRelease)
+    {
+      return m_libCec->VolumeDown(sendRelease);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sends a mute keypress to an audiosystem if it's present.
     /// </summary>
     /// <param name="sendRelease">Send a key release after the keypress.</param>
     /// <returns>The new audio status.</returns>
-               uint8_t MuteAudio(bool sendRelease)
-               {
-                       return m_libCec->MuteAudio(sendRelease);
-               }
+    uint8_t MuteAudio(bool sendRelease)
+    {
+      return m_libCec->MuteAudio(sendRelease);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Send a keypress to a device on the CEC bus.
     /// </summary>
     /// <param name="destination">The logical address of the device to send the message to.</param>
-               /// <param name="key">The key to send.</param>
-               /// <param name="wait">True to wait for a response, false otherwise.</param>
+    /// <param name="key">The key to send.</param>
+    /// <param name="wait">True to wait for a response, false otherwise.</param>
     /// <returns>True when the keypress was acked, false otherwise.</returns>
-               bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
-               {
-                       return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
-               }
+    bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
+    {
+      return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Send a key release to a device on the CEC bus.
     /// </summary>
     /// <param name="destination">The logical address of the device to send the message to.</param>
-               /// <param name="wait">True to wait for a response, false otherwise.</param>
+    /// <param name="wait">True to wait for a response, false otherwise.</param>
     /// <returns>True when the key release was acked, false otherwise.</returns>
-               bool SendKeyRelease(CecLogicalAddress destination, bool wait)
-               {
-                       return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
-               }
+    bool SendKeyRelease(CecLogicalAddress destination, bool wait)
+    {
+      return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the OSD name of a device on the CEC bus.
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to get the OSD name for.</param>
     /// <returns>The OSD name.</returns>
-               String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
-               {
-                       cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
-                       return gcnew String(osd.name);
-               }
+    String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
+    {
+      cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
+      return gcnew String(osd.name);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the logical address of the device that is currently the active source on the CEC bus.
     /// </summary>
     /// <returns>The active source or CECDEVICE_UNKNOWN when unknown.</returns>
-               CecLogicalAddress GetActiveSource()
-               {
-                       return (CecLogicalAddress)m_libCec->GetActiveSource();
-               }
+    CecLogicalAddress GetActiveSource()
+    {
+      return (CecLogicalAddress)m_libCec->GetActiveSource();
+    }
 
-               /// <summary>
+    /// <summary>
     /// Check whether a device is currently the active source on the CEC bus.
     /// </summary>
     /// <param name="logicalAddress">The logical address of the device to check.</param>
     /// <returns>True when it is the active source, false otherwise.</returns>
-               bool IsActiveSource(CecLogicalAddress logicalAddress)
-               {
-                       return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
-               }
+    bool IsActiveSource(CecLogicalAddress logicalAddress)
+    {
+      return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the physical address of the device with the given logical address.
     /// </summary>
     /// <param name="address">The logical address of the device to get the physical address for.</param>
     /// <returns>The physical address or 0 if it wasn't found.</returns>
-               uint16_t GetDevicePhysicalAddress(CecLogicalAddress address)
-               {
-                       return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address);
-               }
+    uint16_t GetDevicePhysicalAddress(CecLogicalAddress address)
+    {
+      return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sets the stream path to the device on the given logical address.
     /// </summary>
     /// <param name="address">The address to activate.</param>
     /// <returns>True when the command was sent, false otherwise.</returns>
-               bool SetStreamPath(CecLogicalAddress address)
-               {
-                       return m_libCec->SetStreamPath((cec_logical_address)address);
-               }
+    bool SetStreamPath(CecLogicalAddress address)
+    {
+      return m_libCec->SetStreamPath((cec_logical_address)address);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Sets the stream path to the device on the given physical address.
     /// </summary>
     /// <param name="physicalAddress">The address to activate.</param>
     /// <returns>True when the command was sent, false otherwise.</returns>
-               bool SetStreamPath(uint16_t physicalAddress)
-               {
-                       return m_libCec->SetStreamPath(physicalAddress);
-               }
+    bool SetStreamPath(uint16_t physicalAddress)
+    {
+      return m_libCec->SetStreamPath(physicalAddress);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Get the list of logical addresses that libCEC is controlling
     /// </summary>
     /// <returns>The list of logical addresses that libCEC is controlling</returns>
-               CecLogicalAddresses ^GetLogicalAddresses(void)
-               {
-                       CecLogicalAddresses ^addr = gcnew CecLogicalAddresses();
-                       cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses();
-                       for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
-                               addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr];
-                       addr->Primary = (CecLogicalAddress)libAddr.primary;
-                       return addr;
-               }
-
-               /// <summary>
+    CecLogicalAddresses ^GetLogicalAddresses(void)
+    {
+      CecLogicalAddresses ^addr = gcnew CecLogicalAddresses();
+      cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses();
+      for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+        addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr];
+      addr->Primary = (CecLogicalAddress)libAddr.primary;
+      return addr;
+    }
+
+    /// <summary>
     /// Get libCEC's current configuration.
     /// </summary>
     /// <param name="configuration">The configuration.</param>
     /// <returns>True when the configuration was updated, false otherwise.</returns>
-               bool GetCurrentConfiguration(LibCECConfiguration ^configuration)
-               {
-                       libcec_configuration config;
-                       config.Clear();
-
-                       if (m_libCec->GetCurrentConfiguration(&config))
-                       {
-                               configuration->Update(config);
-                               return true;
-                       }
-                       return false;
-               }
-
-               /// <summary>
+    bool GetCurrentConfiguration(LibCECConfiguration ^configuration)
+    {
+      libcec_configuration config;
+      config.Clear();
+
+      if (m_libCec->GetCurrentConfiguration(&config))
+      {
+        configuration->Update(config);
+        return true;
+      }
+      return false;
+    }
+
+    /// <summary>
     /// Check whether the CEC adapter can persist a configuration.
     /// </summary>
     /// <returns>True when this CEC adapter can persist the user configuration, false otherwise.</returns>
     bool CanPersistConfiguration(void)
-               {
-                       return m_libCec->CanPersistConfiguration();
-               }
+    {
+      return m_libCec->CanPersistConfiguration();
+    }
 
-               /// <summary>
+    /// <summary>
     /// Persist the given configuration in adapter (if supported)
     /// </summary>
     /// <param name="configuration">The configuration to store.</param>
     /// <returns>True when the configuration was persisted, false otherwise.</returns>
     bool PersistConfiguration(LibCECConfiguration ^configuration)
-               {
-                       marshal_context ^ context = gcnew marshal_context();
-                       libcec_configuration config;
-                       ConvertConfiguration(context, configuration, config);
+    {
+      marshal_context ^ context = gcnew marshal_context();
+      libcec_configuration config;
+      ConvertConfiguration(context, configuration, config);
 
-                       bool bReturn = m_libCec->PersistConfiguration(&config);
+      bool bReturn = m_libCec->PersistConfiguration(&config);
 
-                       delete context;
-                       return bReturn;
-               }
+      delete context;
+      return bReturn;
+    }
 
-               /// <summary>
+    /// <summary>
     /// Change libCEC's configuration.
     /// </summary>
     /// <param name="configuration">The new configuration.</param>
     /// <returns>True when the configuration was changed successfully, false otherwise.</returns>
-               bool SetConfiguration(LibCECConfiguration ^configuration)
-               {
-                       marshal_context ^ context = gcnew marshal_context();
-                       libcec_configuration config;
-                       ConvertConfiguration(context, configuration, config);
+    bool SetConfiguration(LibCECConfiguration ^configuration)
+    {
+      marshal_context ^ context = gcnew marshal_context();
+      libcec_configuration config;
+      ConvertConfiguration(context, configuration, config);
 
-                       bool bReturn = m_libCec->SetConfiguration(&config);
+      bool bReturn = m_libCec->SetConfiguration(&config);
 
-                       delete context;
-                       return bReturn;
-               }
+      delete context;
+      return bReturn;
+    }
 
-               /// <summary>
+    /// <summary>
     /// Check whether libCEC is the active source on the bus.
     /// </summary>
     /// <returns>True when libCEC is the active source on the bus, false otherwise.</returns>
@@ -762,12 +610,12 @@ namespace CecSharp
       return m_libCec->IsLibCECActiveSource();
     }
 
-               /// <summary>
+    /// <summary>
     /// Get information about the given CEC adapter.
     /// </summary>
     /// <param name="port">The COM port to which the device is connected</param>
-               /// <param name="configuration">The device configuration</param>
-               /// <param name="timeoutMs">The timeout in milliseconds</param>
+    /// <param name="configuration">The device configuration</param>
+    /// <param name="timeoutMs">The timeout in milliseconds</param>
     /// <returns>True when the device was found, false otherwise</returns>
     bool GetDeviceInformation(String ^ port, LibCECConfiguration ^configuration, uint32_t timeoutMs)
     {
@@ -775,116 +623,189 @@ namespace CecSharp
       marshal_context ^ context = gcnew marshal_context();
 
       libcec_configuration config;
-                       config.Clear();
+      config.Clear();
 
       const char* strPortC = port->Length > 0 ? context->marshal_as<const char*>(port) : NULL;
 
       if (m_libCec->GetDeviceInformation(strPortC, &config, timeoutMs))
-                       {
-                               configuration->Update(config);
+      {
+        configuration->Update(config);
         bReturn = true;
-                       }
+      }
 
       delete context;
       return bReturn;
     }
 
-               String ^ ToString(CecLogicalAddress iAddress)
-               {
-                       const char *retVal = m_libCec->ToString((cec_logical_address)iAddress);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecVendorId iVendorId)
-               {
-                       const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecVersion iVersion)
-               {
-                       const char *retVal = m_libCec->ToString((cec_version)iVersion);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecPowerStatus iState)
-               {
-                       const char *retVal = m_libCec->ToString((cec_power_status)iState);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecMenuState iState)
-               {
-                       const char *retVal = m_libCec->ToString((cec_menu_state)iState);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecDeckControlMode iMode)
-               {
-                       const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecDeckInfo status)
-               {
-                       const char *retVal = m_libCec->ToString((cec_deck_info)status);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecOpcode opcode)
-               {
-                       const char *retVal = m_libCec->ToString((cec_opcode)opcode);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecSystemAudioStatus mode)
-               {
-                       const char *retVal = m_libCec->ToString((cec_system_audio_status)mode);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecAudioStatus status)
-               {
-                       const char *retVal = m_libCec->ToString((cec_audio_status)status);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecClientVersion version)
-               {
-                       const char *retVal = m_libCec->ToString((cec_client_version)version);
-                       return gcnew String(retVal);
-               }
-
-               String ^ ToString(CecServerVersion version)
-               {
-                       const char *retVal = m_libCec->ToString((cec_server_version)version);
-                       return gcnew String(retVal);
-               }
-
-               /// <summary>
+    String ^ ToString(CecLogicalAddress iAddress)
+    {
+      const char *retVal = m_libCec->ToString((cec_logical_address)iAddress);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecVendorId iVendorId)
+    {
+      const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecVersion iVersion)
+    {
+      const char *retVal = m_libCec->ToString((cec_version)iVersion);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecPowerStatus iState)
+    {
+      const char *retVal = m_libCec->ToString((cec_power_status)iState);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecMenuState iState)
+    {
+      const char *retVal = m_libCec->ToString((cec_menu_state)iState);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecDeckControlMode iMode)
+    {
+      const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecDeckInfo status)
+    {
+      const char *retVal = m_libCec->ToString((cec_deck_info)status);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecOpcode opcode)
+    {
+      const char *retVal = m_libCec->ToString((cec_opcode)opcode);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecSystemAudioStatus mode)
+    {
+      const char *retVal = m_libCec->ToString((cec_system_audio_status)mode);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecAudioStatus status)
+    {
+      const char *retVal = m_libCec->ToString((cec_audio_status)status);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecClientVersion version)
+    {
+      const char *retVal = m_libCec->ToString((cec_client_version)version);
+      return gcnew String(retVal);
+    }
+
+    String ^ ToString(CecServerVersion version)
+    {
+      const char *retVal = m_libCec->ToString((cec_server_version)version);
+      return gcnew String(retVal);
+    }
+
+    /// <summary>
     /// Get a string with information about how libCEC was compiled.
     /// </summary>
     /// <returns>A string with information about how libCEC was compiled.</returns>
-               String ^ GetLibInfo()
-               {
-                       const char *retVal = m_libCec->GetLibInfo();
-                       return gcnew String(retVal);
-               }
+    String ^ GetLibInfo()
+    {
+      const char *retVal = m_libCec->GetLibInfo();
+      return gcnew String(retVal);
+    }
 
-               /// <summary>
+    /// <summary>
     /// Calling this method will initialise the host on which libCEC is running.
-               /// On the RPi, it calls bcm_host_init(), which may only be called once per process, and is called by any process using
+    /// On the RPi, it calls bcm_host_init(), which may only be called once per process, and is called by any process using
     /// the video api on that system. So only call this method if libCEC is used in an application that
     /// does not already initialise the video api.
     /// </summary>
     /// <remarks>Should be called as first call to libCEC, directly after CECInitialise() and before using Open()</remarks>
-               void InitVideoStandalone()
-               {
-                       m_libCec->InitVideoStandalone();
-               }
+    void InitVideoStandalone()
+    {
+      m_libCec->InitVideoStandalone();
+    }
+
+  private:
+    !LibCecSharp(void)
+    {
+      Close();
+      m_libCec = NULL;
+    }
+
+    bool InitialiseLibCec(LibCECConfiguration ^config)
+    {
+      marshal_context ^ context = gcnew marshal_context();
+      libcec_configuration libCecConfig;
+      ConvertConfiguration(context, config, libCecConfig);
+
+      m_libCec = (ICECAdapter *) CECInitialise(&libCecConfig);
+      config->Update(libCecConfig);
+
+      delete context;
+      return m_libCec != NULL;
+    }
+
+    void ConvertConfiguration(marshal_context ^context, LibCECConfiguration ^netConfig, CEC::libcec_configuration &config)
+    {
+      config.Clear();
+
+      const char *strDeviceName = context->marshal_as<const char*>(netConfig->DeviceName);
+      memcpy_s(config.strDeviceName, 13, strDeviceName, 13);
+      for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+        config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr];
+
+      config.bAutodetectAddress   = netConfig->AutodetectAddress ? 1 : 0;
+      config.iPhysicalAddress     = netConfig->PhysicalAddress;
+      config.baseDevice           = (cec_logical_address)netConfig->BaseDevice;
+      config.iHDMIPort            = netConfig->HDMIPort;
+      config.clientVersion        = (cec_client_version)netConfig->ClientVersion;
+      config.bGetSettingsFromROM  = netConfig->GetSettingsFromROM ? 1 : 0;
+      config.bActivateSource      = netConfig->ActivateSource ? 1 : 0;
+      config.tvVendor             = (cec_vendor_id)netConfig->TvVendor;
+      config.wakeDevices.Clear();
+      for (int iPtr = 0; iPtr < 16; iPtr++)
+      {
+        if (netConfig->WakeDevices->IsSet((CecLogicalAddress)iPtr))
+          config.wakeDevices.Set((cec_logical_address)iPtr);
+      }
+      config.powerOffDevices.Clear();
+      for (int iPtr = 0; iPtr < 16; iPtr++)
+      {
+        if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr))
+          config.powerOffDevices.Set((cec_logical_address)iPtr);
+      }
+      config.bPowerOffScreensaver = netConfig->PowerOffScreensaver ? 1 : 0;
+      config.bPowerOffOnStandby   = netConfig->PowerOffOnStandby ? 1 : 0;
+
+      if (netConfig->ServerVersion >= CecServerVersion::Version1_5_1)
+        config.bSendInactiveSource  = netConfig->SendInactiveSource ? 1 : 0;
+
+      if (netConfig->ServerVersion >= CecServerVersion::Version1_6_0)
+      {
+        config.bPowerOffDevicesOnStandby  = netConfig->PowerOffDevicesOnStandby ? 1 : 0;
+        config.bShutdownOnStandby         = netConfig->ShutdownOnStandby ? 1 : 0;
+      }
+
+      if (netConfig->ServerVersion >= CecServerVersion::Version1_6_2)
+      {
+        const char *strDeviceLanguage = context->marshal_as<const char*>(netConfig->DeviceLanguage);
+        memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3);
+      }
+
+      if (netConfig->ServerVersion >= CecServerVersion::Version1_6_3)
+        config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0;
+
+      config.callbacks = &g_cecCallbacks;
+    }
+
 
-       private:
-               ICECAdapter *        m_libCec;
+    ICECAdapter *        m_libCec;
     CecCallbackMethods ^ m_callbacks;
-       };
+  };
 }