cec: fix win32 compilation (new parameter)
[deb_libcec.git] / src / LibCecSharp / LibCecSharp.cpp
index 03c0009cea20e7bc51dd1d26449eb1ffac5417dd..3aa1253512034786373e2ad432bfeff429ae623a 100644 (file)
@@ -38,6 +38,7 @@
 #using <System.dll>
 
 using namespace System;
+using namespace System::Runtime::InteropServices;
 using namespace CEC;
 using namespace msclr::interop;
 
@@ -228,6 +229,101 @@ public enum class CecUserControlCode
   Unknown
 };
 
+public enum class CecVendorId
+{
+  Samsung   = 0x00F0,
+  LG        = 0xE091,
+  Panasonic = 0x8045,
+  Pioneer   = 0xE036,
+  Onkyo     = 0x09B0,
+  Yamaha    = 0xA0DE,
+  Philips   = 0x903E,
+  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 ref class CecAdapter
 {
 public:
@@ -264,6 +360,11 @@ public:
       Addresses[iPtr] = CecLogicalAddress::Unregistered;
   }
 
+  bool IsSet(CecLogicalAddress iAddress)
+  {
+    return Addresses[(unsigned int)iAddress] != CecLogicalAddress::Unregistered;
+  }
+
   property array<CecLogicalAddress> ^ Addresses;
 };
 
@@ -292,7 +393,7 @@ public:
 public ref class CecCommand
 {
 public:
-  CecCommand(CecLogicalAddress iInitiator, CecLogicalAddress iDestination, bool bAck, bool bEom, int8_t iOpcode, int32_t iTransmitTimeout)
+  CecCommand(CecLogicalAddress iInitiator, CecLogicalAddress iDestination, bool bAck, bool bEom, CecOpcode iOpcode, int32_t iTransmitTimeout)
   {
     Initiator       = iInitiator;
     Destination     = iDestination;
@@ -311,7 +412,7 @@ public:
     Destination     = CecLogicalAddress::Unknown;
     Ack             = false;
     Eom             = false;
-    Opcode          = 0;
+    Opcode          = CecOpcode::None;
     OpcodeSet       = false;
     TransmitTimeout = 0;
     Parameters      = gcnew CecDatapacket;
@@ -328,7 +429,7 @@ public:
     else if (!OpcodeSet)
     {
       OpcodeSet = true;
-      Opcode    = data;
+      Opcode    = (CecOpcode)data;
     }
     else
     {
@@ -341,7 +442,7 @@ public:
   property CecLogicalAddress  Destination;
   property bool               Ack;
   property bool               Eom;
-  property int8_t             Opcode;
+  property CecOpcode          Opcode;
   property CecDatapacket ^    Parameters;
   property bool               OpcodeSet;
   property int32_t            TransmitTimeout;
@@ -394,25 +495,102 @@ public:
   property int64_t     Time;
 };
 
+public ref class CecCallbackMethods
+{
+public:
+  virtual int ReceiveLogMessage(CecLogMessage ^ message)
+  {
+    return 0;
+  }
+
+  virtual int ReceiveKeypress(CecKeypress ^ key)
+  {
+    return 0;
+  }
+
+  virtual int ReceiveCommand(CecCommand ^ command)
+  {
+    return 0;
+  }
+};
+
+#pragma unmanaged
+// unmanaged callback methods
+typedef int (__stdcall *LOGCB)    (const cec_log_message &message);
+typedef int (__stdcall *KEYCB)    (const cec_keypress &key);
+typedef int (__stdcall *COMMANDCB)(const cec_command &command);
+
+static LOGCB         g_logCB;
+static KEYCB         g_keyCB;
+static COMMANDCB     g_commandCB;
+static ICECCallbacks g_cecCallbacks;
+
+int CecLogMessageCB(void *cbParam, const cec_log_message &message)
+{
+  if (g_logCB)
+    return g_logCB(message);
+  return 0;
+}
+
+int CecKeyPressCB(void *cbParam, const cec_keypress &key)
+{
+  if (g_keyCB)
+    return g_keyCB(key);
+  return 0;
+}
+
+int CecCommandCB(void *cbParam, const cec_command &command)
+{
+  if (g_commandCB)
+    return g_commandCB(command);
+  return 0;
+}
+
+#pragma managed
+// delegates for the unmanaged callback methods
+public delegate int CecLogMessageManagedDelegate(const cec_log_message &);
+public delegate int CecKeyPressManagedDelegate(const cec_keypress &);
+public delegate int CecCommandManagedDelegate(const cec_command &);
+
 public ref class LibCecSharp
 {
 public:
-   LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
-   {
-     marshal_context ^ context = gcnew marshal_context();
+  LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
+  {
+    marshal_context ^ context = gcnew marshal_context();
+    m_bHasCallbacks = false;
+    const char* strDeviceNameC = context->marshal_as<const char*>(strDeviceName);
 
-     const char* strDeviceNameC = context->marshal_as<const char*>(strDeviceName);
+    cec_device_type_list types;
+    for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+      types.types[iPtr] = (cec_device_type)deviceTypes->Types[iPtr];
+    m_libCec = (ICECAdapter *) CECInit(strDeviceNameC, types);
+
+    // create the delegate method for the log message callback
+    m_logMessageDelegate           = gcnew CecLogMessageManagedDelegate(this, &LibCecSharp::CecLogMessageManaged);
+    m_logMessageGCHandle           = GCHandle::Alloc(m_logMessageDelegate);
+    g_logCB                        = static_cast<LOGCB>(Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer());
+    g_cecCallbacks.CBCecLogMessage = CecLogMessageCB;
+
+    // create the delegate method for the keypress callback
+    m_keypressDelegate           = gcnew CecKeyPressManagedDelegate(this, &LibCecSharp::CecKeyPressManaged);
+    m_keypressGCHandle           = GCHandle::Alloc(m_keypressDelegate);
+    g_keyCB                      = static_cast<KEYCB>(Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer());
+    g_cecCallbacks.CBCecKeyPress = CecKeyPressCB;
+
+    // create the delegate method for the command callback
+    m_commandDelegate           = gcnew CecCommandManagedDelegate(this, &LibCecSharp::CecCommandManaged);
+    m_commandGCHandle           = GCHandle::Alloc(m_commandDelegate);
+    g_commandCB                 = static_cast<COMMANDCB>(Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer());
+    g_cecCallbacks.CBCecCommand = CecCommandCB;
 
-     cec_device_type_list types;
-     for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
-       types.types[iPtr] = (cec_device_type)deviceTypes->Types[iPtr];
-     m_libCec = (ICECAdapter *) CECInit(strDeviceNameC, types);
-     delete context;
-   }
+    delete context;
+  }
    
    ~LibCecSharp(void)
    {
      CECDestroy(m_libCec);
+     DestroyDelegates();
      m_libCec = NULL;
    }
 
@@ -420,6 +598,7 @@ protected:
    !LibCecSharp(void)
    {
      CECDestroy(m_libCec);
+     DestroyDelegates();
      m_libCec = NULL;
    }
 
@@ -456,6 +635,18 @@ public:
     m_libCec->Close();
   }
 
+  bool EnableCallbacks(CecCallbackMethods ^ callbacks)
+  {
+    if (m_libCec && !m_bHasCallbacks)
+    {
+      m_bHasCallbacks = true;
+      m_callbacks = callbacks;
+      return m_libCec->EnableCallbacks(NULL, &g_cecCallbacks);
+    }
+
+    return false;
+  }
+
   bool PingAdapter(void)
   {
     return m_libCec->PingAdapter();
@@ -508,7 +699,7 @@ public:
     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, command.opcode, command.transmit_timeout);
+      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;
@@ -612,9 +803,9 @@ public:
     return gcnew String("");
   }
 
-  uint64_t GetDeviceVendorId(CecLogicalAddress logicalAddress)
+  CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
   {
-    return m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
+    return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
   }
 
   CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
@@ -676,12 +867,138 @@ public:
     return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
   }
 
-  String ^ GetOSDName(CecLogicalAddress logicalAddress)
+  String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
   {
-    cec_osd_name osd = m_libCec->GetOSDName((cec_logical_address) logicalAddress);
+    cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
     return gcnew String(osd.name);
   }
 
+  CecLogicalAddress GetActiveSource()
+  {
+    return (CecLogicalAddress)m_libCec->GetActiveSource();
+  }
+
+  bool IsActiveSource(CecLogicalAddress logicalAddress)
+  {
+    return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
+  }
+
+  uint16_t GetDevicePhysicalAddress(CecLogicalAddress iAddress)
+  {
+    return m_libCec->GetDevicePhysicalAddress((cec_logical_address)iAddress);
+  }
+
+  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);
+  }
+
 private:
-   ICECAdapter *m_libCec;
+  void DestroyDelegates()
+  {
+    m_logMessageGCHandle.Free();
+    m_keypressGCHandle.Free();
+    m_commandGCHandle.Free();
+  }
+
+  // managed callback methods
+  int CecLogMessageManaged(const cec_log_message &message)
+  {
+    int iReturn(0);
+    if (m_bHasCallbacks)
+      iReturn = m_callbacks->ReceiveLogMessage(gcnew CecLogMessage(gcnew String(message.message), (CecLogLevel)message.level, message.time));
+    return iReturn;
+  }
+
+  int CecKeyPressManaged(const cec_keypress &key)
+  {
+    int iReturn(0);
+    if (m_bHasCallbacks)
+      iReturn = m_callbacks->ReceiveKeypress(gcnew CecKeypress(key.keycode, key.duration));
+    return iReturn;
+  }
+
+  int CecCommandManaged(const 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;
+  }
+
+  ICECAdapter *        m_libCec;
+  CecCallbackMethods ^ m_callbacks;
+  bool                 m_bHasCallbacks;
+
+  CecLogMessageManagedDelegate ^ m_logMessageDelegate;
+  static GCHandle                m_logMessageGCHandle;
+  LOGCB                          m_logMessageCallback;
+
+  CecKeyPressManagedDelegate ^   m_keypressDelegate;
+  static GCHandle                m_keypressGCHandle;
+  KEYCB                          m_keypressCallback;
+
+  CecCommandManagedDelegate ^    m_commandDelegate;
+  static GCHandle                m_commandGCHandle;
+  COMMANDCB                      m_commandCallback;
 };