X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2FLibCecSharp%2FLibCecSharp.cpp;h=0bae3eaca39e9d820f49b605968b6e39d78fa580;hb=b5bd4ac08c3fb4f6e2e101dd3ca84a08a7a9fb8c;hp=fb723236eb0fa4fd3892dbc7b65c8ff3aa050d9f;hpb=1d0b2f179049bb299227a311b2323024622b7826;p=deb_libcec.git diff --git a/src/LibCecSharp/LibCecSharp.cpp b/src/LibCecSharp/LibCecSharp.cpp index fb72323..0bae3ea 100644 --- a/src/LibCecSharp/LibCecSharp.cpp +++ b/src/LibCecSharp/LibCecSharp.cpp @@ -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 - * 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-2013 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 +* http://www.pulse-eight.com/ +* http://www.pulse-eight.net/ +*/ #include "CecSharpTypes.h" #using @@ -40,562 +40,800 @@ using namespace msclr::interop; namespace CecSharp { - public ref class LibCecSharp : public CecCallbackMethods - { - public: - LibCecSharp(LibCECConfiguration ^config) - { + /// + /// 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. + /// + public ref class LibCecSharp : public CecCallbackMethods + { + public: + /// + /// Create a new LibCecSharp instance. + /// + /// The configuration to pass to libCEC. + 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); - - 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(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(netConfig->DeviceLanguage); - memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3); - } - - config.callbacks = &g_cecCallbacks; - } - - public: - array ^ 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(path) : NULL; - - uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL); - - array ^ adapters = gcnew array(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; - } - - bool Open(String ^ strPort, int iTimeoutMs) - { + CecCallbackMethods::EnableCallbacks(m_callbacks); + if (!InitialiseLibCec(config)) + throw gcnew Exception("Could not initialise LibCecSharp"); + } + + ~LibCecSharp(void) + { + Close(); + m_libCec = NULL; + } + + /// + /// Try to find all connected CEC adapters. + /// + /// The path filter for adapters. Leave empty to return all adapters. + /// The adapters that were found. + array ^ 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(path) : NULL; + + uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL); + + array ^ adapters = gcnew array(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; + } + + /// + /// Open a connection to the CEC adapter. + /// + /// The COM port of the adapter + /// Connection timeout in milliseconds + /// True when a connection was opened, false otherwise. + 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(strPort); - bool bReturn = m_libCec->Open(strPortC, iTimeoutMs); - delete context; - return bReturn; - } - - void Close(void) - { - DisableCallbacks(); - m_libCec->Close(); - } - - 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 bool EnableCallbacks(CecCallbackMethods ^ callbacks) override - { - if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks)) - return m_libCec->EnableCallbacks(NULL, &g_cecCallbacks); - - return false; - } - - bool PingAdapter(void) - { - return m_libCec->PingAdapter(); - } - - bool StartBootloader(void) - { - return m_libCec->StartBootloader(); - } - - int GetMinLibVersion(void) - { - return m_libCec->GetMinLibVersion(); - } - - int GetLibVersionMajor(void) - { - return m_libCec->GetLibVersionMajor(); - } - - int GetLibVersionMinor(void) - { - return m_libCec->GetLibVersionMinor(); - } - - 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(); - } - - CecKeypress ^ GetNextKeypress(void) - { - cec_keypress key; - if (m_libCec->GetNextKeypress(&key)) - { - return gcnew CecKeypress(key.keycode, key.duration); - } - - return gcnew CecKeypress(); - } - - 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(); - } - - 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); - } - - bool SetLogicalAddress(CecLogicalAddress logicalAddress) - { - return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress); - } - - bool SetPhysicalAddress(uint16_t physicalAddress) - { - return m_libCec->SetPhysicalAddress(physicalAddress); - } - - bool PowerOnDevices(CecLogicalAddress logicalAddress) - { - return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress); - } - - bool StandbyDevices(CecLogicalAddress logicalAddress) - { - return m_libCec->StandbyDevices((cec_logical_address) logicalAddress); - } - - bool PollDevice(CecLogicalAddress logicalAddress) - { - return m_libCec->PollDevice((cec_logical_address) logicalAddress); - } - - bool SetActiveSource(CecDeviceType type) - { - return m_libCec->SetActiveSource((cec_device_type) type); - } - - bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate) - { - return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate); - } - - bool SetDeckInfo(CecDeckInfo info, bool sendUpdate) - { - return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate); - } - - bool SetInactiveView(void) - { - return m_libCec->SetInactiveView(); - } - - bool SetMenuState(CecMenuState state, bool sendUpdate) - { - return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate); - } - - bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message) - { - marshal_context ^ context = gcnew marshal_context(); - const char* strMessageC = context->marshal_as(message); - - bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC); - - delete context; - return bReturn; - } - - bool SwitchMonitoring(bool enable) - { - return m_libCec->SwitchMonitoring(enable); - } - - CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress) - { - return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress); - } - - 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(""); - } - - CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress) - { - return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress); - } - - CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress) - { - return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress); - } - - void RescanActiveDevices(void) - { - m_libCec->RescanActiveDevices(); - } - - CecLogicalAddresses ^ GetActiveDevices(void) - { - CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses(); - unsigned int iDevices = 0; - - cec_logical_addresses activeDevices = m_libCec->GetActiveDevices(); - - for (uint8_t iPtr = 0; iPtr < 16; iPtr++) - if (activeDevices[iPtr]) - retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr; - - return retVal; - } - - bool IsActiveDevice(CecLogicalAddress logicalAddress) - { - return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); - } - - bool IsActiveDeviceType(CecDeviceType type) - { - return m_libCec->IsActiveDeviceType((cec_device_type)type); - } - - bool SetHDMIPort(CecLogicalAddress address, uint8_t port) - { - return m_libCec->SetHDMIPort((cec_logical_address)address, port); - } - - uint8_t VolumeUp(bool wait) - { - return m_libCec->VolumeUp(wait); - } - - uint8_t VolumeDown(bool wait) - { - return m_libCec->VolumeDown(wait); - } - - uint8_t MuteAudio(bool wait) - { - return m_libCec->MuteAudio(wait); - } - - bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait) - { - return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait); - } - - bool SendKeyRelease(CecLogicalAddress destination, bool wait) - { - return m_libCec->SendKeyRelease((cec_logical_address)destination, wait); - } - - String ^ GetDeviceOSDName(CecLogicalAddress 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); - } - - bool SetStreamPath(CecLogicalAddress iAddress) - { - return m_libCec->SetStreamPath((cec_logical_address)iAddress); - } - - bool SetStreamPath(uint16_t iPhysicalAddress) - { - return m_libCec->SetStreamPath(iPhysicalAddress); - } - - 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; - } - - bool GetCurrentConfiguration(LibCECConfiguration ^configuration) - { - libcec_configuration config; - config.Clear(); - - if (m_libCec->GetCurrentConfiguration(&config)) - { - configuration->Update(config); - return true; - } - return false; - } + marshal_context ^ context = gcnew marshal_context(); + const char* strPortC = context->marshal_as(strPort); + bool bReturn = m_libCec->Open(strPortC, iTimeoutMs); + delete context; + return bReturn; + } + + /// + /// Close the connection to the CEC adapter + /// + void Close(void) + { + DisableCallbacks(); + m_libCec->Close(); + } + + /// + /// Disable all calls to callback methods. + /// + 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); + } + + /// + /// Enable or change the callback methods that libCEC uses to send changes to the client application. + /// + /// The new callback methods to use. + /// True when the callbacks were changed, false otherwise + virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override + { + if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks)) + return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks); + + return false; + } + + /// + /// Sends a ping command to the adapter, to check if it's responding. + /// + /// True when the ping was succesful, false otherwise + bool PingAdapter(void) + { + return m_libCec->PingAdapter(); + } + + /// + /// Start the bootloader of the CEC adapter. Closes the connection when successful. + /// + /// True when the command was sent successfully, false otherwise. + bool StartBootloader(void) + { + return m_libCec->StartBootloader(); + } + + /// + /// Transmit a raw CEC command over the CEC line. + /// + /// The command to transmit + /// True when the data was sent and acked, false otherwise. + 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); + } + + /// + /// 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. + /// + /// The CEC adapter's new logical address. + /// True when the logical address was set successfully, false otherwise. + bool SetLogicalAddress(CecLogicalAddress logicalAddress) + { + return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress); + } + + /// + /// 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. + /// + /// The CEC adapter's new physical address. + /// True when the physical address was set successfully, false otherwise. + bool SetPhysicalAddress(uint16_t physicalAddress) + { + return m_libCec->SetPhysicalAddress(physicalAddress); + } + + /// + /// Power on the given CEC capable devices. If CECDEVICE_BROADCAST is used, then wakeDevice in libcec_configuration will be used. + /// + /// The logical address to power on. + /// True when the command was sent succesfully, false otherwise. + bool PowerOnDevices(CecLogicalAddress logicalAddress) + { + return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress); + } + + /// + /// Put the given CEC capable devices in standby mode. If CECDEVICE_BROADCAST is used, then standbyDevices in libcec_configuration will be used. + /// + /// The logical address of the device to put in standby. + /// True when the command was sent succesfully, false otherwise. + bool StandbyDevices(CecLogicalAddress logicalAddress) + { + return m_libCec->StandbyDevices((cec_logical_address) logicalAddress); + } + + /// + /// Sends a POLL message to a device, to check if it's present and responding. + /// + /// The device to send the message to. + /// True if the POLL was acked, false otherwise. + bool PollDevice(CecLogicalAddress logicalAddress) + { + return m_libCec->PollDevice((cec_logical_address) logicalAddress); + } + + /// + /// 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. + /// + /// The new active source. Use CEC_DEVICE_TYPE_RESERVED to use the primary type + /// True when the command was sent succesfully, false otherwise. + bool SetActiveSource(CecDeviceType type) + { + return m_libCec->SetActiveSource((cec_device_type) type); + } + + /// + /// Change the deck control mode, if this adapter is registered as playback or recording device. + /// + /// The new control mode. + /// True to send the new status over the CEC line. + /// True if set, false otherwise. + bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate) + { + return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate); + } + + /// + /// Change the deck info, if this adapter is a playback or recording device. + /// + /// The new deck info. + /// True to send the new status over the CEC line. + /// True if set, false otherwise. + bool SetDeckInfo(CecDeckInfo info, bool sendUpdate) + { + return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate); + } + + /// + /// Broadcast a message that notifies connected CEC capable devices that this device is no longer the active source. + /// + /// True when the command was sent succesfully, false otherwise. + bool SetInactiveView(void) + { + return m_libCec->SetInactiveView(); + } + + /// + /// Change the menu state. This value is already changed by libCEC automatically if a device is (de)activated. + /// + /// The new state. + /// True to send the new status over the CEC line. + /// True if set, false otherwise. + bool SetMenuState(CecMenuState state, bool sendUpdate) + { + return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate); + } + + /// + /// Display a message on the device with the given logical address. Not supported by most TVs. + /// + /// The logical address of the device to display the message on. + /// The duration of the message + /// The message to display. + /// True when the command was sent, false otherwise. + bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message) + { + marshal_context ^ context = gcnew marshal_context(); + const char* strMessageC = context->marshal_as(message); + + bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC); + + delete context; + return bReturn; + } + + /// + /// 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. + /// + /// True to enable, false to disable. + /// True when switched successfully, false otherwise. + bool SwitchMonitoring(bool enable) + { + return m_libCec->SwitchMonitoring(enable); + } + + /// + /// Get the CEC version of the device with the given logical address + /// + /// The logical address of the device to get the CEC version for. + /// The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched. + CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress) + { + return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress); + } + + /// + /// Get the menu language of the device with the given logical address + /// + /// The logical address of the device to get the menu language for. + /// The requested menu language. + 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(""); + } + + /// + /// Get the vendor ID of the device with the given logical address. + /// + /// The logical address of the device to get the vendor ID for. + /// The vendor ID or 0 if it wasn't found. + CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress) + { + return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress); + } + + /// + /// Get the power status of the device with the given logical address. + /// + /// The logical address of the device to get the power status for. + /// The power status or CEC_POWER_STATUS_UNKNOWN if it wasn't found. + CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress) + { + return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress); + } + + /// + /// Tell libCEC to poll for active devices on the bus. + /// + void RescanActiveDevices(void) + { + m_libCec->RescanActiveDevices(); + } + + /// + /// Get the logical addresses of the devices that are active on the bus, including those handled by libCEC. + /// + /// The logical addresses of the active devices + CecLogicalAddresses ^ GetActiveDevices(void) + { + CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses(); + unsigned int iDevices = 0; + + cec_logical_addresses activeDevices = m_libCec->GetActiveDevices(); + + for (uint8_t iPtr = 0; iPtr < 16; iPtr++) + if (activeDevices[iPtr]) + retVal->Set((CecLogicalAddress)iPtr); + + return retVal; + } + + /// + /// Check whether a device is active on the bus. + /// + /// The address to check. + /// True when active, false otherwise. + bool IsActiveDevice(CecLogicalAddress logicalAddress) + { + return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); + } + + /// + /// Check whether a device of the given type is active on the bus. + /// + /// The type to check. + /// True when active, false otherwise. + bool IsActiveDeviceType(CecDeviceType type) + { + return m_libCec->IsActiveDeviceType((cec_device_type)type); + } + + /// + /// Changes the active HDMI port. + /// + /// The device to which this libCEC is connected. + /// The new port number. + /// True when changed, false otherwise. + bool SetHDMIPort(CecLogicalAddress address, uint8_t port) + { + return m_libCec->SetHDMIPort((cec_logical_address)address, port); + } + + /// + /// Sends a volume up keypress to an audiosystem if it's present. + /// + /// Send a key release after the keypress. + /// The new audio status. + uint8_t VolumeUp(bool sendRelease) + { + return m_libCec->VolumeUp(sendRelease); + } + + /// + /// Sends a volume down keypress to an audiosystem if it's present. + /// + /// Send a key release after the keypress. + /// The new audio status. + uint8_t VolumeDown(bool sendRelease) + { + return m_libCec->VolumeDown(sendRelease); + } + /// + /// Sends a mute keypress to an audiosystem if it's present. + /// + /// Send a key release after the keypress. + /// The new audio status. + uint8_t MuteAudio(bool sendRelease) + { + return m_libCec->MuteAudio(sendRelease); + } + + /// + /// Send a keypress to a device on the CEC bus. + /// + /// The logical address of the device to send the message to. + /// The key to send. + /// True to wait for a response, false otherwise. + /// True when the keypress was acked, false otherwise. + bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait) + { + return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait); + } + + /// + /// Send a key release to a device on the CEC bus. + /// + /// The logical address of the device to send the message to. + /// True to wait for a response, false otherwise. + /// True when the key release was acked, false otherwise. + bool SendKeyRelease(CecLogicalAddress destination, bool wait) + { + return m_libCec->SendKeyRelease((cec_logical_address)destination, wait); + } + + /// + /// Get the OSD name of a device on the CEC bus. + /// + /// The logical address of the device to get the OSD name for. + /// The OSD name. + String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress) + { + cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress); + // we need to terminate with \0, and we only got 14 chars in osd.name + char strOsdName[15]; + memset(strOsdName, 0, sizeof(strOsdName)); + memcpy(strOsdName, osd.name, sizeof(osd.name)); + return gcnew String(strOsdName); + } + + /// + /// Get the logical address of the device that is currently the active source on the CEC bus. + /// + /// The active source or CECDEVICE_UNKNOWN when unknown. + CecLogicalAddress GetActiveSource() + { + return (CecLogicalAddress)m_libCec->GetActiveSource(); + } + + /// + /// Check whether a device is currently the active source on the CEC bus. + /// + /// The logical address of the device to check. + /// True when it is the active source, false otherwise. + bool IsActiveSource(CecLogicalAddress logicalAddress) + { + return m_libCec->IsActiveSource((cec_logical_address)logicalAddress); + } + + /// + /// Get the physical address of the device with the given logical address. + /// + /// The logical address of the device to get the physical address for. + /// The physical address or 0 if it wasn't found. + uint16_t GetDevicePhysicalAddress(CecLogicalAddress address) + { + return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address); + } + + /// + /// Sets the stream path to the device on the given logical address. + /// + /// The address to activate. + /// True when the command was sent, false otherwise. + bool SetStreamPath(CecLogicalAddress address) + { + return m_libCec->SetStreamPath((cec_logical_address)address); + } + + /// + /// Sets the stream path to the device on the given physical address. + /// + /// The address to activate. + /// True when the command was sent, false otherwise. + bool SetStreamPath(uint16_t physicalAddress) + { + return m_libCec->SetStreamPath(physicalAddress); + } + + /// + /// Get the list of logical addresses that libCEC is controlling + /// + /// The list of logical addresses that libCEC is controlling + 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; + } + + /// + /// Get libCEC's current configuration. + /// + /// The configuration. + /// True when the configuration was updated, false otherwise. + bool GetCurrentConfiguration(LibCECConfiguration ^configuration) + { + libcec_configuration config; + config.Clear(); + + if (m_libCec->GetCurrentConfiguration(&config)) + { + configuration->Update(config); + return true; + } + return false; + } + + /// + /// Check whether the CEC adapter can persist a configuration. + /// + /// True when this CEC adapter can persist the user configuration, false otherwise. bool CanPersistConfiguration(void) - { - return m_libCec->CanPersistConfiguration(); - } + { + return m_libCec->CanPersistConfiguration(); + } + /// + /// Persist the given configuration in adapter (if supported) + /// + /// The configuration to store. + /// True when the configuration was persisted, false otherwise. 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; + } - bool SetConfiguration(LibCECConfiguration ^configuration) - { - marshal_context ^ context = gcnew marshal_context(); - libcec_configuration config; - ConvertConfiguration(context, configuration, config); + /// + /// Change libCEC's configuration. + /// + /// The new configuration. + /// True when the configuration was changed successfully, false otherwise. + 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; + } + /// + /// Check whether libCEC is the active source on the bus. + /// + /// True when libCEC is the active source on the bus, false otherwise. bool IsLibCECActiveSource() { return m_libCec->IsLibCECActiveSource(); } + /// + /// Get information about the given CEC adapter. + /// + /// The COM port to which the device is connected + /// The device configuration + /// The timeout in milliseconds + /// True when the device was found, false otherwise bool GetDeviceInformation(String ^ port, LibCECConfiguration ^configuration, uint32_t timeoutMs) { bool bReturn(false); marshal_context ^ context = gcnew marshal_context(); libcec_configuration config; - config.Clear(); + config.Clear(); const char* strPortC = port->Length > 0 ? context->marshal_as(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); - } - - private: - ICECAdapter * m_libCec; + 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); + } + + /// + /// Get a string with information about how libCEC was compiled. + /// + /// A string with information about how libCEC was compiled. + String ^ GetLibInfo() + { + const char *retVal = m_libCec->GetLibInfo(); + return gcnew String(retVal); + } + + /// + /// 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 + /// 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. + /// + /// Should be called as first call to libCEC, directly after CECInitialise() and before using Open() + void InitVideoStandalone() + { + m_libCec->InitVideoStandalone(); + } + + /// + /// Get the (virtual) USB vendor id + /// + /// The (virtual) USB vendor id + uint16_t GetAdapterVendorId() + { + return m_libCec->GetAdapterVendorId(); + } + + /// + /// Get the (virtual) USB product id + /// + /// The (virtual) USB product id + uint16_t GetAdapterProductId() + { + return m_libCec->GetAdapterProductId(); + } + + 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(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(netConfig->DeviceLanguage); + memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3); + } + + if (netConfig->ServerVersion >= CecServerVersion::Version1_6_3) + config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0; + + if (netConfig->ServerVersion >= CecServerVersion::Version1_8_0) + config.cecVersion = (cec_version)netConfig->CECVersion; + + if (netConfig->ServerVersion >= CecServerVersion::Version2_1_0) + config.bPowerOnScreensaver = netConfig->PowerOnScreensaver ? 1 : 0; + + config.callbacks = &g_cecCallbacks; + } + + + ICECAdapter * m_libCec; CecCallbackMethods ^ m_callbacks; - }; + }; }