From 9b9658482e2acbe4f27c72ba99abdb0106612b58 Mon Sep 17 00:00:00 2001 From: Yuvaramachandran Gurusamy <123441336+yuvaramachandran-gurusamy@users.noreply.github.com> Date: Wed, 23 Jul 2025 01:02:10 +0530 Subject: [PATCH 01/14] RDKEMW-6279: Revert of HdmiCecSink comrpc changes (#129) (#199) This reverts commit f4a230f1270113d9f1ca50abce58633d15c5b99b. Signed-off-by: yuvaramachandran_gurusamy --- .github/workflows/L1-tests.yml | 4 +- HdmiCecSink/CMakeLists.txt | 21 +- HdmiCecSink/HdmiCecSink.conf.in | 7 - HdmiCecSink/HdmiCecSink.config | 10 - HdmiCecSink/HdmiCecSink.cpp | 3535 +++++++++++++++- HdmiCecSink/HdmiCecSink.h | 886 +++- HdmiCecSink/HdmiCecSinkImplementation.cpp | 3581 ----------------- HdmiCecSink/HdmiCecSinkImplementation.h | 755 ---- HdmiCecSource/HdmiCecSourceImplementation.cpp | 6 +- HdmiCecSource/HdmiCecSourceImplementation.h | 4 +- Tests/L1Tests/CMakeLists.txt | 3 +- Tests/L1Tests/tests/test_HdmiCecSource.cpp | 2 +- 12 files changed, 4156 insertions(+), 4658 deletions(-) delete mode 100644 HdmiCecSink/HdmiCecSinkImplementation.cpp delete mode 100644 HdmiCecSink/HdmiCecSinkImplementation.h diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 209ff45f..6121092a 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -440,7 +440,7 @@ jobs: -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON - -DPLUGIN_HDMICECSINK=OFF + -DPLUGIN_HDMICECSINK=ON -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF && @@ -518,7 +518,7 @@ jobs: -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON - -DPLUGIN_HDMICECSINK=OFF + -DPLUGIN_HDMICECSINK=ON -DRDK_SERVICES_L1_TEST=ON -DUSE_THUNDER_R4=ON -DHIDE_NON_EXTERNAL_SYMBOLS=OFF diff --git a/HdmiCecSink/CMakeLists.txt b/HdmiCecSink/CMakeLists.txt index 11e12e6f..b244641e 100644 --- a/HdmiCecSink/CMakeLists.txt +++ b/HdmiCecSink/CMakeLists.txt @@ -16,7 +16,6 @@ # limitations under the License. set(PLUGIN_NAME HdmiCecSink) set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) -set(PLUGIN_IMPLEMENTATION ${MODULE_NAME}Implementation) set(PLUGIN_HDMICECSINK_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiCecSink plugin") @@ -27,18 +26,10 @@ add_library(${MODULE_NAME} SHARED HdmiCecSink.cpp Module.cpp) -add_library(${PLUGIN_IMPLEMENTATION} SHARED - HdmiCecSinkImplementation.cpp - Module.cpp) - set_target_properties(${MODULE_NAME} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) -set_target_properties(${PLUGIN_IMPLEMENTATION} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) - target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) find_package(DS) @@ -50,23 +41,13 @@ target_include_directories(${MODULE_NAME} PRIVATE ${CEC_INCLUDE_DIRS}) target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) set_source_files_properties(HdmiCecSink.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - -target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${IARMBUS_INCLUDE_DIRS} ../helpers) -target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${CEC_INCLUDE_DIRS}) -target_include_directories(${PLUGIN_IMPLEMENTATION} PRIVATE ${DS_INCLUDE_DIRS}) -set_source_files_properties(HdmiCecSinkImplementation.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - target_link_libraries(${MODULE_NAME} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${CEC_LIBRARIES} ${DS_LIBRARIES} ) -target_link_libraries(${PLUGIN_IMPLEMENTATION} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${CEC_LIBRARIES} ${DS_LIBRARIES} ) if (NOT RDK_SERVICES_L1_TEST) - target_compile_options(${PLUGIN_IMPLEMENTATION} PRIVATE -Wno-error=deprecated) + target_compile_options(${MODULE_NAME} PRIVATE -Wno-error=deprecated) endif () install(TARGETS ${MODULE_NAME} DESTINATION lib/${STORAGE_DIRECTORY}/plugins) -install(TARGETS ${PLUGIN_IMPLEMENTATION} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) - write_config(${PLUGIN_NAME}) diff --git a/HdmiCecSink/HdmiCecSink.conf.in b/HdmiCecSink/HdmiCecSink.conf.in index 646c4430..de8e1cdf 100644 --- a/HdmiCecSink/HdmiCecSink.conf.in +++ b/HdmiCecSink/HdmiCecSink.conf.in @@ -2,10 +2,3 @@ precondition = ["Platform"] callsign = "org.rdk.HdmiCecSink" autostart = "false" startuporder = "@PLUGIN_HDMICECSINK_STARTUPORDER@" - -configuration = JSON() -rootobject = JSON() - -rootobject.add("mode", "@PLUGIN_HDMICECSINK_MODE@") -rootobject.add("locator", "lib@PLUGIN_IMPLEMENTATION@.so") -configuration.add("root", rootobject) \ No newline at end of file diff --git a/HdmiCecSink/HdmiCecSink.config b/HdmiCecSink/HdmiCecSink.config index 7257c9e8..13ed0788 100644 --- a/HdmiCecSink/HdmiCecSink.config +++ b/HdmiCecSink/HdmiCecSink.config @@ -5,13 +5,3 @@ set (callsign "org.rdk.HdmiCecSink") if(PLUGIN_HDMICECSINK_STARTUPORDER) set (startuporder ${PLUGIN_HDMICECSINK_STARTUPORDER}) endif() - - -map() - key(root) - map() - kv(mode ${PLUGIN_HDMICECSOURCE_MODE}) - kv(locator lib${PLUGIN_IMPLEMENTATION}.so) - end() -end() -ans(configuration) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index a7e08588..b5150cf8 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -19,14 +19,159 @@ #include "HdmiCecSink.h" +#include "ccec/Connection.hpp" +#include "ccec/CECFrame.hpp" +#include "ccec/MessageEncoder.hpp" +#include "host.hpp" +#include "UtilsgetRFCConfig.h" + +#include "dsMgr.h" +#include "dsRpc.h" +#include "dsDisplay.h" +#include "videoOutputPort.hpp" +#include "manager.hpp" +#include "websocket/URL.h" + #include "UtilsIarm.h" #include "UtilsJsonRpc.h" #include "UtilssyncPersistFile.h" #include "UtilsSearchRDKProfile.h" +#define HDMICECSINK_METHOD_SET_ENABLED "setEnabled" +#define HDMICECSINK_METHOD_GET_ENABLED "getEnabled" +#define HDMICECSINK_METHOD_OTP_SET_ENABLED "setOTPEnabled" +#define HDMICECSINK_METHOD_OTP_GET_ENABLED "getOTPEnabled" +#define HDMICECSINK_METHOD_SET_OSD_NAME "setOSDName" +#define HDMICECSINK_METHOD_GET_OSD_NAME "getOSDName" +#define HDMICECSINK_METHOD_SET_VENDOR_ID "setVendorId" +#define HDMICECSINK_METHOD_GET_VENDOR_ID "getVendorId" +#define HDMICECSINK_METHOD_PRINT_DEVICE_LIST "printDeviceList" +#define HDMICECSINK_METHOD_SET_ACTIVE_PATH "setActivePath" +#define HDMICECSINK_METHOD_SET_ROUTING_CHANGE "setRoutingChange" +#define HDMICECSINK_METHOD_GET_DEVICE_LIST "getDeviceList" +#define HDMICECSINK_METHOD_GET_ACTIVE_SOURCE "getActiveSource" +#define HDMICECSINK_METHOD_SET_ACTIVE_SOURCE "setActiveSource" +#define HDMICECSINK_METHOD_GET_ACTIVE_ROUTE "getActiveRoute" +#define HDMICECSINK_METHOD_SET_MENU_LANGUAGE "setMenuLanguage" +#define HDMICECSINK_METHOD_REQUEST_ACTIVE_SOURCE "requestActiveSource" +#define HDMICECSINK_METHOD_SETUP_ARC "setupARCRouting" +#define HDMICECSINK_METHOD_REQUEST_SHORT_AUDIO_DESCRIPTOR "requestShortAudioDescriptor" +#define HDMICECSINK_METHOD_SEND_STANDBY_MESSAGE "sendStandbyMessage" +#define HDMICECSINK_METHOD_SEND_AUDIO_DEVICE_POWER_ON "sendAudioDevicePowerOnMessage" +#define HDMICECSINK_METHOD_SEND_KEY_PRESS "sendKeyPressEvent" +#define HDMICECSINK_METHOD_SEND_USER_CONTROL_PRESSED "sendUserControlPressed" +#define HDMICECSINK_METHOD_SEND_USER_CONTROL_RELEASED "sendUserControlReleased" +#define HDMICECSINK_METHOD_SEND_GIVE_AUDIO_STATUS "sendGetAudioStatusMessage" +#define HDMICECSINK_METHOD_GET_AUDIO_DEVICE_CONNECTED_STATUS "getAudioDeviceConnectedStatus" +#define HDMICECSINK_METHOD_REQUEST_AUDIO_DEVICE_POWER_STATUS "requestAudioDevicePowerStatus" +#define HDMICECSINK_METHOD_SET_LATENCY_INFO "setLatencyInfo" + +#define TEST_ADD 0 +#define HDMICECSINK_REQUEST_MAX_RETRY 3 +#define HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS 2000 +#define HDMICECSINK_PING_INTERVAL_MS 10000 +#define HDMICECSINK_WAIT_FOR_HDMI_IN_MS 1000 +#define HDMICECSINK_REQUEST_INTERVAL_TIME_MS 500 +#define HDMICECSINK_NUMBER_TV_ADDR 2 +#define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) +#define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 +#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 + + +#define SAD_FMT_CODE_AC3 2 +#define SAD_FMT_CODE_ENHANCED_AC3 10 + +#define SYSTEM_AUDIO_MODE_ON 0x01 +#define SYSTEM_AUDIO_MODE_OFF 0x00 +#define AUDIO_DEVICE_POWERSTATE_OFF 1 + +#define DEFAULT_VIDEO_LATENCY 100 +#define DEFAULT_LATENCY_FLAGS 3 +#define DEFAULT_AUDIO_OUTPUT_DELAY 100 + +//Device Type is TV - Bit 7 is set to 1 +#define ALL_DEVICE_TYPES 128 + +//RC Profile of TV is 3 - Typical TV Remote +#define RC_PROFILE_TV 10 + +//Device Features supported by TV - ARC Tx +#define DEVICE_FEATURES_TV 4 #define TR181_HDMICECSINK_CEC_VERSION "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion" +enum { + DEVICE_POWER_STATE_ON = 0, + DEVICE_POWER_STATE_OFF = 1 +}; + + +enum { + HDMICECSINK_EVENT_ACTIVE_SOURCE_CHANGE = 1, + HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY, + HDMICECSINK_EVENT_TEXT_VIEW_ON_MSG, + HDMICECSINK_EVENT_IMAGE_VIEW_ON_MSG, + HDMICECSINK_EVENT_DEVICE_ADDED, + HDMICECSINK_EVENT_DEVICE_REMOVED, + HDMICECSINK_EVENT_DEVICE_INFO_UPDATED, + HDMICECSINK_EVENT_INACTIVE_SOURCE, + HDMICECSINK_EVENT_ARC_INITIATION_EVENT, + HDMICECSINK_EVENT_ARC_TERMINATION_EVENT, + HDMICECSINK_EVENT_SHORT_AUDIODESCRIPTOR_EVENT, + HDMICECSINK_EVENT_STANDBY_MSG_EVENT, + HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE, + HDMICECSINK_EVENT_REPORT_AUDIO_STATUS, + HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS, + HDMICECSINK_EVENT_CEC_ENABLED, + HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS, + HDMICECSINK_EVENT_FEATURE_ABORT_EVENT, +}; + +static const char *eventString[] = { + "None", + "onActiveSourceChange", + "onWakeupFromStandby", + "onTextViewOnMsg", + "onImageViewOnMsg", + "onDeviceAdded", + "onDeviceRemoved", + "onDeviceInfoUpdated", + "onInActiveSource", + "arcInitiationEvent", + "arcTerminationEvent", + "shortAudiodesciptorEvent", + "standbyMessageReceived", + "setSystemAudioModeEvent", + "reportAudioStatusEvent", + "reportAudioDeviceConnectedStatus", + "reportCecEnabledEvent", + "reportAudioDevicePowerStatus", + "reportFeatureAbortEvent" +}; + + +#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" +#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" +#define CEC_SETTING_ENABLED "cecEnabled" +#define CEC_SETTING_OSD_NAME "cecOSDName" +#define CEC_SETTING_VENDOR_ID "cecVendorId" + +static std::vector defaultVendorId = {0x00,0x19,0xFB}; +static VendorID appVendorId = {defaultVendorId.at(0),defaultVendorId.at(1),defaultVendorId.at(2)}; +static VendorID lgVendorId = {0x00,0xE0,0x91}; +static PhysicalAddress physical_addr = {0x0F,0x0F,0x0F,0x0F}; +static LogicalAddress logicalAddress = 0xF; +static Language defaultLanguage = "eng"; +static OSDName osdName = "TV Box"; +static int32_t powerState = DEVICE_POWER_STATE_OFF; +static std::vector formatid = {0,0}; +static std::vector audioFormatCode = { SAD_FMT_CODE_ENHANCED_AC3,SAD_FMT_CODE_AC3 }; +static uint8_t numberofdescriptor = 2; +static int32_t HdmiArcPortID = -1; +static float cecVersion = 1.4; +static AllDeviceTypes allDevicetype = ALL_DEVICE_TYPES; +static std::vector rcProfile = {RC_PROFILE_TV}; +static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; #define API_VERSION_NUMBER_MAJOR 1 #define API_VERSION_NUMBER_MINOR 3 @@ -34,7 +179,7 @@ namespace WPEFramework { - namespace { + namespace { static Plugin::Metadata metadata( // Version (Major, Minor, Patch) @@ -50,119 +195,3365 @@ namespace WPEFramework namespace Plugin { - SERVICE_REGISTRATION(HdmiCecSink, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + SERVICE_REGISTRATION(HdmiCecSink, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + + HdmiCecSink* HdmiCecSink::_instance = nullptr; + static int libcecInitStatus = 0; + +//=========================================== HdmiCecSinkFrameListener ========================================= + void HdmiCecSinkFrameListener::notify(const CECFrame &in) const { + const uint8_t *buf = NULL; + char strBuffer[512] = {0}; + size_t len = 0; + + in.getBuffer(&buf, &len); + for (unsigned int i = 0; i < len; i++) { + snprintf(strBuffer + (i*3) , sizeof(strBuffer) - (i*3), "%02X ",(uint8_t) *(buf + i)); + } + LOGINFO(" >>>>> Received CEC Frame: :%s \n",strBuffer); + + MessageDecoder(processor).decode(in); + } + +//=========================================== HdmiCecSinkProcessor ========================================= + void HdmiCecSinkProcessor::process (const ActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->updateActiveSource(header.from.toInt(), msg); + } + void HdmiCecSinkProcessor::process (const InActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: InActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + HdmiCecSink::_instance->updateInActiveSource(header.from.toInt(), msg); + } + + void HdmiCecSinkProcessor::process (const ImageViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ImageViewOn from %s\n", header.from.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->updateImageViewOn(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const TextViewOn &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: TextViewOn\n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->updateTextViewOn(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const RequestActiveSource &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RequestActiveSource\n"); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + HdmiCecSink::_instance->setActiveSource(true); + } + void HdmiCecSinkProcessor::process (const Standby &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); + HdmiCecSink::_instance->SendStandbyMsgEvent(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const GetCECVersion &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetCECVersion sending CECVersion response \n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + if(cecVersion == 2.0) { + conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_2_0))); + } + else{ + conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); + } + } + catch(...) + { + LOGWARN("Exception while sending CECVersion "); + } + } + void HdmiCecSinkProcessor::process (const CECVersion &msg, const Header &header) + { + bool updateStatus; + printHeader(header); + LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); + + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isVersionUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.version); + if(!updateStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const SetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const GiveOSDName &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + conn.sendToAsync(header.from, MessageEncoder().encode(SetOSDName(osdName))); + } + catch(...) + { + LOGWARN("Exception while sending SetOSDName"); + } + } + void HdmiCecSinkProcessor::process (const GivePhysicalAddress &msg, const Header &header) + { + LOGINFO("Command: GivePhysicalAddress\n"); + if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) + { + try + { + LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); + conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt())), 500); + } + catch(...) + { + LOGWARN("Exception while sending ReportPhysicalAddress "); + } + } + } + void HdmiCecSinkProcessor::process (const GiveDeviceVendorID &msg, const Header &header) + { + printHeader(header); + if(header.to == LogicalAddress(LogicalAddress::BROADCAST)){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",appVendorId.toString().c_str()); + conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); + } + catch(...) + { + LOGWARN("Exception while sending DeviceVendorID"); + } + + } + void HdmiCecSinkProcessor::process (const SetOSDString &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const SetOSDName &msg, const Header &header) + { + printHeader(header); + bool updateStatus ; + LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isOSDNameUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.osdName); + if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_OSD_NAME) { + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; + } + if(!updateStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const RoutingChange &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingChange From : %s To: %s \n",msg.from.toString().c_str(),msg.to.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const RoutingInformation &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const SetStreamPath &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); + } + void HdmiCecSinkProcessor::process (const GetMenuLanguage &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GetMenuLanguage\n"); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->sendMenuLanguage(); + } + void HdmiCecSinkProcessor::process (const ReportPhysicalAddress &msg, const Header &header) + { + printHeader(header); + bool updateDeviceTypeStatus; + bool updatePAStatus; + LOGINFO("Command: ReportPhysicalAddress\n"); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + if(!HdmiCecSink::_instance) + return; + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateDeviceTypeStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isDeviceTypeUpdated; + updatePAStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isPAUpdated; + LOGINFO("updateDeviceTypeStatus %d updatePAStatus %d \n",updateDeviceTypeStatus,updatePAStatus); + if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString() != msg.physicalAddress.toString() && updatePAStatus){ + updatePAStatus= false; + LOGINFO("There is a change in physical address from current PA %s to newly reported PA %s\n",HdmiCecSink::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString().c_str(),msg.physicalAddress.toString().c_str()); + } + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.physicalAddress); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.deviceType); + if(HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_PHISICAL_ADDRESS) { + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; + } + HdmiCecSink::_instance->updateDeviceChain(header.from, msg.physicalAddress); + if (!updateDeviceTypeStatus || !updatePAStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const DeviceVendorID &msg, const Header &header) + { + bool updateStatus ; + printHeader(header); + LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); + if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ + LOGINFO("Ignore Direct messages, accepts only broadcast messages"); + return; + } + + HdmiCecSink::_instance->addDevice(header.from.toInt()); + updateStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_isVendorIDUpdated; + LOGINFO("updateStatus %d\n",updateStatus); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.vendorId); + if (!updateStatus) + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + void HdmiCecSinkProcessor::process (const GiveDevicePowerStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + try + { + conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); + } + catch(...) + { + LOGWARN("Exception while sending ReportPowerStatus"); + } + } + void HdmiCecSinkProcessor::process (const ReportPowerStatus &msg, const Header &header) + { + uint32_t oldPowerStatus,newPowerStatus; + printHeader(header); + LOGINFO("Command: ReportPowerStatus Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + oldPowerStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); + HdmiCecSink::_instance->addDevice(header.from.toInt()); + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(msg.status); + newPowerStatus = HdmiCecSink::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); + LOGINFO(" oldPowerStatus %d newpower status %d \n",oldPowerStatus,newPowerStatus); + if ((oldPowerStatus != newPowerStatus) ) + { + HdmiCecSink::_instance->sendDeviceUpdateInfo(header.from.toInt()); + } + + if((header.from.toInt() == LogicalAddress::AUDIO_SYSTEM) && (HdmiCecSink::_instance->m_audioDevicePowerStatusRequested)) { + HdmiCecSink::_instance->reportAudioDevicePowerStatusInfo(header.from.toInt(), newPowerStatus); + } + + } + void HdmiCecSinkProcessor::process (const FeatureAbort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: FeatureAbort opcode=%s, Reason = %s\n", msg.feature.toString().c_str(), msg.reason.toString().c_str()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + + if(header.from.toInt() < LogicalAddress::UNREGISTERED && + msg.reason.toInt() == AbortReason::UNRECOGNIZED_OPCODE) + { + switch(msg.feature.opCode()) + { + case GET_CEC_VERSION : + { + /* If we get a Feature abort for CEC Version then default to 1.4b */ + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(Version(Version::V_1_4)); + } + break; + case GIVE_DEVICE_VENDOR_ID : + { + /* If we get a Feature abort for CEC Version then default to 1.4b */ + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(VendorID((uint8_t *)"FA", 2)); + } + break; + + case GIVE_OSD_NAME : + { + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(OSDName("")); + } + break; + + case GIVE_DEVICE_POWER_STATUS : + { + HdmiCecSink::_instance->deviceList[header.from.toInt()].update(PowerStatus(PowerStatus::POWER_STATUS_FEATURE_ABORT)); + } + break; + } + + HdmiCecSink::_instance->deviceList[header.from.toInt()].m_featureAborts.push_back(msg); + } + + LogicalAddress logicaladdress = header.from.toInt(); + OpCode featureOpcode = msg.feature; + AbortReason abortReason = msg.reason; + + HdmiCecSink::_instance->reportFeatureAbortEvent(logicaladdress,featureOpcode,abortReason); + + if(msg.feature.opCode() == REQUEST_SHORT_AUDIO_DESCRIPTOR) + { + JsonArray audiodescriptor; + audiodescriptor.Add(0); + HdmiCecSink::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); + } + + } + void HdmiCecSinkProcessor::process (const Abort &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Abort\n"); + if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) + { + AbortReason reason = AbortReason::UNRECOGNIZED_OPCODE; + LogicalAddress logicaladdress =header.from.toInt(); + OpCode feature = msg.opCode(); + HdmiCecSink::_instance->sendFeatureAbort(logicaladdress, feature,reason); + } + else + { + LOGINFO("Command: Abort broadcast msg so ignore\n"); + } + } + void HdmiCecSinkProcessor::process (const Polling &msg, const Header &header) { + printHeader(header); + LOGINFO("Command: Polling\n"); + } + + void HdmiCecSinkProcessor::process (const InitiateArc &msg, const Header &header) + { + printHeader(header); + if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ + LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); + return; + } + PhysicalAddress physical_addr_invalid = {0x0F,0x0F,0x0F,0x0F}; + PhysicalAddress physical_addr_arc_port = {0x0F,0x0F,0x0F,0x0F}; + + LOGINFO("Command: INITIATE_ARC \n"); + if(!HdmiCecSink::_instance || HdmiArcPortID == -1) + return; + + if (HdmiArcPortID == 0 ) + physical_addr_arc_port = {0x01,0x00,0x00,0x00}; + if (HdmiArcPortID == 1 ) + physical_addr_arc_port = {0x02,0x00,0x00,0x00}; + if (HdmiArcPortID == 2 ) + physical_addr_arc_port = {0x03,0x00,0x00,0x00}; + + if( (HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_arc_port.toString()) || (HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_invalid.toString()) ) { + LOGINFO("Command: INITIATE_ARC InitiateArc success %s \n",HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); + HdmiCecSink::_instance->Process_InitiateArc(); + } else { + LOGINFO("Command: INITIATE_ARC InitiateArc ignore %s \n",HdmiCecSink::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); + } + } + void HdmiCecSinkProcessor::process (const TerminateArc &msg, const Header &header) + { + printHeader(header); + if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ + LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); + return; + } + if(!HdmiCecSink::_instance) + return; + HdmiCecSink::_instance->Process_TerminateArc(); + } + void HdmiCecSinkProcessor::process (const ReportShortAudioDescriptor &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportShortAudioDescriptor %s : %d \n",GetOpName(msg.opCode()),numberofdescriptor); + HdmiCecSink::_instance->Process_ShortAudioDescriptor_msg(msg); + } + + void HdmiCecSinkProcessor::process (const SetSystemAudioMode &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: SetSystemAudioMode %s audio status %d audio status is %s \n",GetOpName(msg.opCode()),msg.status.toInt(),msg.status.toString().c_str()); + HdmiCecSink::_instance->Process_SetSystemAudioMode_msg(msg); + } + void HdmiCecSinkProcessor::process (const ReportAudioStatus &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + if(header.to.toInt() == LogicalAddress::BROADCAST){ + LOGINFO("Ignore Broadcast messages, accepts only direct messages"); + return; + } + HdmiCecSink::_instance->Process_ReportAudioStatus_msg(msg); + } + void HdmiCecSinkProcessor::process (const GiveFeatures &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: GiveFeatures \n"); + try + { + if(cecVersion == 2.0) { + conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST),MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures))); + } + } + catch(...) + { + LOGWARN("Exception while sending ReportFeatures"); + } + } + void HdmiCecSinkProcessor::process (const RequestCurrentLatency &msg, const Header &header) + { + printHeader(header); + LOGINFO("Command: Request Current Latency :%s, physical address: %s",GetOpName(msg.opCode()),msg.physicaladdress.toString().c_str()); + + if(msg.physicaladdress.toString() == physical_addr.toString()) { + HdmiCecSink::_instance->setLatencyInfo(); + } + else { + LOGINFO("Physical Address does not match with TV's physical address"); + return; + } + } +//=========================================== HdmiCecSink ========================================= + + HdmiCecSink::HdmiCecSink() + : PluginHost::JSONRPC() + , _pwrMgrNotification(*this) + , _registeredEventHandlers(false) + { + LOGWARN("Initlaizing HdmiCecSink"); + } + HdmiCecSink::~HdmiCecSink() + { + } const std::string HdmiCecSink::Initialize(PluginHost::IShell *service) { - profileType = searchRdkProfile(); + InitializePowerManager(service); + profileType = searchRdkProfile(); + + if (profileType == STB || profileType == NOT_FOUND) + { + LOGINFO("Invalid profile type for TV \n"); + return (std::string("Not supported")); + } + + HdmiCecSink::_instance = this; + smConnection=NULL; + cecEnableStatus = false; + HdmiCecSink::_instance->m_numberOfDevices = 0; + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + m_currentActiveSource = -1; + m_isHdmiInConnected = false; + hdmiCecAudioDeviceConnected = false; + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + m_audioDevicePowerStatusRequested = false; + m_pollNextState = POLL_THREAD_STATE_NONE; + m_pollThreadState = POLL_THREAD_STATE_NONE; + m_video_latency = DEFAULT_VIDEO_LATENCY; + m_latency_flags = DEFAULT_LATENCY_FLAGS ; + m_audio_output_delay = DEFAULT_AUDIO_OUTPUT_DELAY; + + Register(HDMICECSINK_METHOD_SET_ENABLED, &HdmiCecSink::setEnabledWrapper, this); + Register(HDMICECSINK_METHOD_GET_ENABLED, &HdmiCecSink::getEnabledWrapper, this); + Register(HDMICECSINK_METHOD_SET_OSD_NAME, &HdmiCecSink::setOSDNameWrapper, this); + Register(HDMICECSINK_METHOD_GET_OSD_NAME, &HdmiCecSink::getOSDNameWrapper, this); + Register(HDMICECSINK_METHOD_SET_VENDOR_ID, &HdmiCecSink::setVendorIdWrapper, this); + Register(HDMICECSINK_METHOD_GET_VENDOR_ID, &HdmiCecSink::getVendorIdWrapper, this); + Register(HDMICECSINK_METHOD_PRINT_DEVICE_LIST, &HdmiCecSink::printDeviceListWrapper, this); + Register(HDMICECSINK_METHOD_SET_ACTIVE_PATH, &HdmiCecSink::setActivePathWrapper, this); + Register(HDMICECSINK_METHOD_SET_ROUTING_CHANGE, &HdmiCecSink::setRoutingChangeWrapper, this); + Register(HDMICECSINK_METHOD_GET_DEVICE_LIST, &HdmiCecSink::getDeviceListWrapper, this); + Register(HDMICECSINK_METHOD_GET_ACTIVE_SOURCE, &HdmiCecSink::getActiveSourceWrapper, this); + Register(HDMICECSINK_METHOD_SET_ACTIVE_SOURCE, &HdmiCecSink::setActiveSourceWrapper, this); + Register(HDMICECSINK_METHOD_GET_ACTIVE_ROUTE, &HdmiCecSink::getActiveRouteWrapper, this); + Register(HDMICECSINK_METHOD_REQUEST_ACTIVE_SOURCE, &HdmiCecSink::requestActiveSourceWrapper, this); + Register(HDMICECSINK_METHOD_SETUP_ARC, &HdmiCecSink::setArcEnableDisableWrapper, this); + Register(HDMICECSINK_METHOD_SET_MENU_LANGUAGE, &HdmiCecSink::setMenuLanguageWrapper, this); + Register(HDMICECSINK_METHOD_REQUEST_SHORT_AUDIO_DESCRIPTOR, &HdmiCecSink::requestShortAudioDescriptorWrapper, this); + Register(HDMICECSINK_METHOD_SEND_STANDBY_MESSAGE, &HdmiCecSink::sendStandbyMessageWrapper, this); + Register(HDMICECSINK_METHOD_SEND_AUDIO_DEVICE_POWER_ON, &HdmiCecSink::sendAudioDevicePowerOnMsgWrapper, this); + Register(HDMICECSINK_METHOD_SEND_KEY_PRESS,&HdmiCecSink::sendRemoteKeyPressWrapper,this); + Register(HDMICECSINK_METHOD_SEND_USER_CONTROL_PRESSED,&HdmiCecSink::sendUserControlPressedWrapper,this); + Register(HDMICECSINK_METHOD_SEND_USER_CONTROL_RELEASED,&HdmiCecSink::sendUserControlReleasedWrapper,this); + Register(HDMICECSINK_METHOD_SEND_GIVE_AUDIO_STATUS,&HdmiCecSink::sendGiveAudioStatusWrapper,this); + Register(HDMICECSINK_METHOD_GET_AUDIO_DEVICE_CONNECTED_STATUS,&HdmiCecSink::getAudioDeviceConnectedStatusWrapper,this); + Register(HDMICECSINK_METHOD_REQUEST_AUDIO_DEVICE_POWER_STATUS,&HdmiCecSink::requestAudioDevicePowerStatusWrapper,this); + Register(HDMICECSINK_METHOD_SET_LATENCY_INFO, &HdmiCecSink::setLatencyInfoWrapper, this); + logicalAddressDeviceType = "None"; + logicalAddress = 0xFF; + // load persistence setting + loadSettings(); + + int err; + dsHdmiInGetNumberOfInputsParam_t hdmiInput; + InitializeIARM(); + m_sendKeyEventThreadExit = false; + m_sendKeyEventThread = std::thread(threadSendKeyEvent); + + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + m_semSignaltoArcRoutingThread.acquire(); + m_arcRoutingThread = std::thread(threadArcRouting); + + m_audioStatusDetectionTimer.connect( std::bind( &HdmiCecSink::audioStatusTimerFunction, this ) ); + m_audioStatusDetectionTimer.setSingleShot(true); + m_arcStartStopTimer.connect( std::bind( &HdmiCecSink::arcStartStopTimerFunction, this ) ); + m_arcStartStopTimer.setSingleShot(true); + // get power state: + Core::hresult res = Core::ERROR_GENERAL; + PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; + + ASSERT (_powerManagerPlugin); + if (_powerManagerPlugin) { + res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); + if (Core::ERROR_NONE == res) { + powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) ? DEVICE_POWER_STATE_ON : DEVICE_POWER_STATE_OFF; + LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n", pwrStateCur, powerState); + } + } + + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs, + (void *)&hdmiInput, + sizeof(hdmiInput)); - if (profileType == STB || profileType == NOT_FOUND) + if (err == IARM_RESULT_SUCCESS && hdmiInput.result == dsERR_NONE) { - LOGINFO("Invalid profile type for TV \n"); - return (std::string("Not supported")); + LOGINFO("Number of Inputs [%d] \n", hdmiInput.numHdmiInputs ); + m_numofHdmiInput = hdmiInput.numHdmiInputs; + }else{ + LOGINFO("Not able to get Numebr of inputs so defaulting to 3 \n"); + m_numofHdmiInput = 3; + } + + LOGINFO("initalize inputs \n"); + + for (int i = 0; i < m_numofHdmiInput; i++){ + HdmiPortMap hdmiPort((uint8_t)i); + LOGINFO(" Add to vector [%d] \n", i); + hdmiInputs.push_back(hdmiPort); + } + + LOGINFO("Check the HDMI State \n"); + + CheckHdmiInState(); + if (cecSettingEnabled) + { + try + { + CECEnable(); + } + catch(...) + { + LOGWARN("Exception while enabling CEC settings .\r\n"); + } + } + getCecVersion(); + LOGINFO(" HdmiCecSink plugin Initialize completed \n"); + return (std::string()); + + } + + void HdmiCecSink::Deinitialize(PluginHost::IShell* /* service */) + { + if(_powerManagerPlugin) + { + _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); + _powerManagerPlugin.Reset(); + } + _registeredEventHandlers = false; + + profileType = searchRdkProfile(); + + if (profileType == STB || profileType == NOT_FOUND) + { + LOGINFO("Invalid profile type for TV \n"); + return ; + } + + CECDisable(); + m_currentArcRoutingState = ARC_STATE_ARC_EXIT; + + m_semSignaltoArcRoutingThread.release(); + + try + { + if (m_arcRoutingThread.joinable()) + m_arcRoutingThread.join(); + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + { + m_sendKeyEventThreadExit = true; + std::unique_lock lk(m_sendKeyEventMutex); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + } + + try + { + if (m_sendKeyEventThread.joinable()) + m_sendKeyEventThread.join(); + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + HdmiCecSink::_instance = nullptr; + DeinitializeIARM(); + LOGWARN(" HdmiCecSink Deinitialize() Done"); + } + + const void HdmiCecSink::InitializeIARM() + { + if (Utils::IARM::init()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); } + } + + void HdmiCecSink::DeinitializeIARM() + { + if (Utils::IARM::isConnected()) + { + IARM_Result_t res; + IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); + } + } + + void HdmiCecSink::InitializePowerManager(PluginHost::IShell *service) + { + _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) + .withIShell(service) + .withRetryIntervalMS(200) + .withRetryCount(25) + .createInterface(); + registerEventHandlers(); + } + void HdmiCecSink::registerEventHandlers() + { + ASSERT (_powerManagerPlugin); - string msg = ""; + if(!_registeredEventHandlers && _powerManagerPlugin) { + _registeredEventHandlers = true; + _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); + } + } - ASSERT(nullptr != service); - ASSERT(nullptr == _service); - ASSERT(nullptr == _hdmiCecSink); - ASSERT(0 == _connectionId); + void HdmiCecSink::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) + { + if(!HdmiCecSink::_instance) + return; + if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) + { + IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; + bool isHdmiConnected = eventData->data.hdmi_in_connect.isPortConnected; + dsHdmiInPort_t portId = eventData->data.hdmi_in_connect.port; + LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event port: %d data:%d \r\n",portId, isHdmiConnected); + HdmiCecSink::_instance->onHdmiHotPlug(portId,isHdmiConnected); + } + } - _service = service; - _service->AddRef(); - _service->Register(&_notification); - _hdmiCecSink = _service->Root(_connectionId, 5000, _T("HdmiCecSinkImplementation")); + void HdmiCecSink::onPowerModeChanged(const PowerState currentState, const PowerState newState) + { + if(!HdmiCecSink::_instance) + return; - if(nullptr != _hdmiCecSink) + LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", + currentState, newState); + LOGWARN(" m_logicalAddressAllocated 0x%x CEC enable status %d \n",_instance->m_logicalAddressAllocated,_instance->cecEnableStatus); + if(newState == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) { - _hdmiCecSink->Configure(service); - _hdmiCecSink->Register(&_notification); - Exchange::JHdmiCecSink::Register(*this, _hdmiCecSink); - LOGINFO("HdmiCecSink plugin is available. Successfully activated HdmiCecSink Plugin"); + powerState = DEVICE_POWER_STATE_ON; } else { - msg = "HdmiCecSink plugin is not available"; - LOGINFO("HdmiCecSink plugin is not available. Failed to activate HdmiCecSink Plugin"); + powerState = DEVICE_POWER_STATE_OFF; + if((_instance->m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_INITIATION) || (_instance->m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) + { + LOGINFO("%s: Stop ARC \n",__FUNCTION__); + _instance->stopArc(); } - if (0 != msg.length()) + } + if (_instance->cecEnableStatus) + { + if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED ) + { + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); + + if ( powerState != DEVICE_POWER_STATE_ON ) + { + /* reset the current active source when TV on going to standby */ + HdmiCecSink::_instance->m_currentActiveSource = -1; + } + /* Initiate a ping straight away */ + HdmiCecSink::_instance->m_pollNextState = POLL_THREAD_STATE_PING; + HdmiCecSink::_instance->m_ThreadExitCV.notify_one(); + } + } + else { - Deinitialize(service); + LOGWARN("CEC not Enabled\n"); } + } - // On success return empty, to indicate there is no error text. - return msg; - } + void HdmiCecSink::sendStandbyMessage() + { + if(!HdmiCecSink::_instance) + return; + if(!(HdmiCecSink::_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } - void HdmiCecSink::Deinitialize(PluginHost::IShell* /* service */) + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby()), 1000); + } + + void HdmiCecSink::onHdmiHotPlug(int portId , int connectStatus) + { + LOGINFO("onHdmiHotPlug Status : %d ", connectStatus); + if(!connectStatus) + { + LOGINFO(" removeDevice port: %d Logical address :%d \r\n",portId,hdmiInputs[portId].m_logicalAddr.toInt() ); + _instance->removeDevice(hdmiInputs[portId].m_logicalAddr.toInt()); + } + CheckHdmiInState(); + + if(cecEnableStatus) { + LOGINFO("cecEnableStatus : %d Trigger CEC Ping !!! \n", cecEnableStatus); + m_pollNextState = POLL_THREAD_STATE_PING; + m_ThreadExitCV.notify_one(); + } + if( HdmiArcPortID >= 0 ) { + updateArcState(); + } + return; + } + void HdmiCecSink::updateArcState() { - - profileType = searchRdkProfile(); + if ( m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED ) + { + if (!(hdmiInputs[HdmiArcPortID].m_isConnected)) + { + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + else + { + LOGINFO("updateArcState :not updating ARC state current arc state %d ",m_currentArcRoutingState); + } + } + } + void HdmiCecSink::arcStartStopTimerFunction() + { + JsonObject params; + + if (m_arcstarting) + { + LOGINFO("arcStartStopTimerFunction ARC start timer expired"); + LOGINFO("notify_device setting that Initiate ARC failed to get the ARC_STATE_ARC_INITIATED state\n"); + params["status"] = string("failure"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_INITIATION_EVENT], params); + } + else + { + LOGINFO("arcStartStopTimerFunction ARC stop timer expired"); + LOGINFO("notify_device setting that Terminate ARC failed to get the ARC_STATE_ARC_TERMINATED state\n"); + params["status"] = string("failure"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_TERMINATION_EVENT], params); + + + } + /* bring the state machine to the clean state for a new start */ + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + void HdmiCecSink::Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor) + { + JsonObject params; + + LOGINFO("Notify the DS "); + params["ShortAudioDescriptor"]= JsonValue(audiodescriptor); + sendNotify(eventString[HDMICECSINK_EVENT_SHORT_AUDIODESCRIPTOR_EVENT], params); + } + + void HdmiCecSink::Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg) + { + uint8_t numberofdescriptor = msg.numberofdescriptor; + uint32_t descriptor =0; + JsonArray audiodescriptor; + + if (numberofdescriptor) + { + for( uint8_t i=0; i < numberofdescriptor; i++) + { + descriptor = msg.shortAudioDescriptor[i].getAudiodescriptor(); + + LOGINFO("descriptor%d 0x%x\n",i,descriptor); + audiodescriptor.Add(descriptor); + + } + } + else + { + audiodescriptor.Add(descriptor); + } + HdmiCecSink::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); + } - if (profileType == STB || profileType == NOT_FOUND) + void HdmiCecSink::updateCurrentLatency(int videoLatency, bool lowLatencyMode,int audioOutputCompensated, int audioOutputDelay = 0) { - LOGINFO("Invalid profile type for TV \n"); - return ; + uint8_t latencyFlags = 0; + latencyFlags = ((lowLatencyMode & 0x1) << 2) | (audioOutputCompensated & 0x3); + LOGINFO("Video Latency : %d , Low Latency Mode : %d ,Audio Output Compensated value : %d , Audio Output Delay : %d , Latency Flags: %d ", videoLatency, lowLatencyMode, audioOutputCompensated, audioOutputDelay, latencyFlags); + m_video_latency = (videoLatency/2) + 1; + m_latency_flags = latencyFlags; + m_audio_output_delay = (audioOutputDelay/2) + 1; + setLatencyInfo(); } - bool enabled = false; - bool ret = false; - HdmiCecSink::_hdmiCecSink->GetEnabled(enabled,ret); + void HdmiCecSink::setLatencyInfo() + { + if(!HdmiCecSink::_instance) + return; - if(ret && enabled) - { - Exchange::IHdmiCecSink::HdmiCecSinkSuccess success; - HdmiCecSink::_hdmiCecSink->SetEnabled(false,success); - } + if(!(_instance->smConnection)) + return; - if(nullptr != _hdmiCecSink) - { - _hdmiCecSink->Unregister(&_notification); - Exchange::JHdmiCecSink::Unregister(*this); - _hdmiCecSink->Release(); - _hdmiCecSink = nullptr; + LOGINFO("Send Report Current Latency message \n"); + _instance->smConnection->sendTo(LogicalAddress::BROADCAST,MessageEncoder().encode(ReportCurrentLatency(physical_addr,m_video_latency,m_latency_flags,m_audio_output_delay))); - RPC::IRemoteConnection* connection = _service->RemoteConnection(_connectionId); - if (connection != nullptr) - { - try{ - connection->Terminate(); - } - catch(const std::exception& e) - { - std::string errorMessage = "Failed to terminate connection: "; - errorMessage += e.what(); - LOGWARN("%s",errorMessage.c_str()); + } + + void HdmiCecSink::Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status + //SetSystemAudioMode message may come from AVR/Soundbar while CEC disable is in-progress + if ( cecSettingEnabled != true ) + { + LOGINFO("Process SetSystemAudioMode from Audio device: Cec is disabled-> EnableCEC first"); + return; + } + + if ( (msg.status.toInt() == SYSTEM_AUDIO_MODE_OFF) && (m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) + { + /* ie system audio mode off -> amplifier goign to standby but still ARC is in initiated state,stop ARC and + bring the ARC state machine to terminated state*/ + LOGINFO("system audio mode off message but arc is not in terminated state so stopping ARC"); + stopArc(); + + } + + params["audioMode"] = msg.status.toString().c_str(); + if (msg.status.toInt() == SYSTEM_AUDIO_MODE_ON) { + LOGINFO("panel power state is %s", powerState ? "Off" : "On"); + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notifying system audio mode ON event"); + sendNotify(eventString[HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE], params); + } else { + LOGINFO("Not notifying system audio mode ON event"); + } + } else { + LOGINFO("Notifying system audio Mode OFF event"); + sendNotify(eventString[HDMICECSINK_EVENT_SYSTEM_AUDIO_MODE], params); + } + } + void HdmiCecSink::Process_ReportAudioStatus_msg(const ReportAudioStatus msg) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + if (m_audioStatusTimerStarted) + { + m_audioStatusReceived = true; + m_isAudioStatusInfoUpdated = true; + m_audioStatusTimerStarted = false; + if (m_audioStatusDetectionTimer.isActive()) + { + LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); + m_audioStatusDetectionTimer.stop(); + } + LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } + LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); + params["muteStatus"] = msg.status.getAudioMuteStatus(); + params["volumeLevel"] = msg.status.getAudioVolume(); + sendNotify(eventString[HDMICECSINK_EVENT_REPORT_AUDIO_STATUS], params); + + } + void HdmiCecSink::sendKeyPressEvent(const int logicalAddress, int keyCode) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" sendKeyPressEvent logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); + switch(keyCode) + { + case VOLUME_UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); + break; + case VOLUME_DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); + break; + case MUTE: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); + break; + case UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); + break; + case DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); + break; + case LEFT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); + break; + case RIGHT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); + break; + case SELECT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); + break; + case HOME: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); + break; + case BACK: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); + break; + case NUMBER_0: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); + break; + case NUMBER_1: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); + break; + case NUMBER_2: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); + break; + case NUMBER_3: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); + break; + case NUMBER_4: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); + break; + case NUMBER_5: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); + break; + case NUMBER_6: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); + break; + case NUMBER_7: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); + break; + case NUMBER_8: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); + break; + case NUMBER_9: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); + break; + + } + } + + void HdmiCecSink::sendUserControlPressed(const int logicalAddress, int keyCode) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" sendUserControlPressed logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); + switch(keyCode) + { + case VOLUME_UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); + break; + case VOLUME_DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); + break; + case MUTE: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); + break; + case UP: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); + break; + case DOWN: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); + break; + case LEFT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); + break; + case RIGHT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); + break; + case SELECT: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); + break; + case HOME: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); + break; + case BACK: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); + break; + case NUMBER_0: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); + break; + case NUMBER_1: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); + break; + case NUMBER_2: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); + break; + case NUMBER_3: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); + break; + case NUMBER_4: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); + break; + case NUMBER_5: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); + break; + case NUMBER_6: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); + break; + case NUMBER_7: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); + break; + case NUMBER_8: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); + break; + case NUMBER_9: + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); + break; + + } } - connection->Release(); - } - } + void HdmiCecSink::sendKeyReleaseEvent(const int logicalAddress) + { + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + + } + + void HdmiCecSink::sendUserControlReleased(const int logicalAddress) + { + if(!(_instance->smConnection)) + return; + LOGINFO(" User Control Released \n"); + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); + } + + void HdmiCecSink::sendDeviceUpdateInfo(const int logicalAddress) + { + JsonObject params; + params["logicalAddress"] = JsonValue(logicalAddress); + sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_INFO_UPDATED], params); + } + void HdmiCecSink::systemAudioModeRequest() + { + if ( cecEnableStatus != true ) + { + LOGINFO("systemAudioModeRequest: Cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send systemAudioModeRequest "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(SystemAudioModeRequest(physical_addr)), 1000); - _connectionId = 0; - _service->Unregister(&_notification); - _service->Release(); - _service = nullptr; - LOGINFO("HdmiCecSink plugin is deactivated. Successfully deactivated HdmiCecSink Plugin"); } + void HdmiCecSink::sendGiveAudioStatusMsg() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send GiveAudioStatus "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); - string HdmiCecSink::Information() const + } + void HdmiCecSink::reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus) { - return("This HdmiCecSink PLugin Facilitates the HDMI CEC Sink Control"); + JsonObject params; + params["powerStatus"] = JsonValue(powerStatus); + LOGINFO("Panle power state is %s", powerState ? "Off" : "On"); + if (powerStatus != AUDIO_DEVICE_POWERSTATE_OFF) { + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS], params); + } else { + LOGINFO("Not notifying audio device power state to DS"); + } + } else { + LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_POWER_STATUS], params); + } } - void HdmiCecSink::Deactivated(RPC::IRemoteConnection* connection) + void HdmiCecSink::SendStandbyMsgEvent(const int logicalAddress) { - if (connection->Id() == _connectionId) + JsonObject params; + if(!HdmiCecSink::_instance) + return; + params["logicalAddress"] = JsonValue(logicalAddress); + sendNotify(eventString[HDMICECSINK_EVENT_STANDBY_MSG_EVENT], params); + } + uint32_t HdmiCecSink::setEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + + setEnabled(enabled); + returnResponse(true); + } + + uint32_t HdmiCecSink::getEnabledWrapper(const JsonObject& parameters, JsonObject& response) + { + response["enabled"] = getEnabled(); + returnResponse(true); + } + + uint32_t HdmiCecSink::getAudioDeviceConnectedStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + response["connected"] = getAudioDeviceConnectedStatus(); + returnResponse(true); + } + + uint32_t HdmiCecSink::requestAudioDevicePowerStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + requestAudioDevicePowerStatus(); + returnResponse(true); + } + + uint32_t HdmiCecSink::getActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) + { + char routeString[1024] = {'\0'}; + int length = 0; + std::stringstream temp; + + if ( HdmiCecSink::_instance->m_currentActiveSource != -1 ) + { + int n = HdmiCecSink::_instance->m_currentActiveSource; + response["available"] = true; + response["logicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt(); + response["physicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_physicalAddr.toString().c_str(); + response["deviceType"] = HdmiCecSink::_instance->deviceList[n].m_deviceType.toString().c_str(); + response["cecVersion"] = HdmiCecSink::_instance->deviceList[n].m_cecVersion.toString().c_str(); + response["osdName"] = HdmiCecSink::_instance->deviceList[n].m_osdName.toString().c_str(); + response["vendorID"] = HdmiCecSink::_instance->deviceList[n].m_vendorID.toString().c_str(); + response["powerStatus"] = HdmiCecSink::_instance->deviceList[n].m_powerStatus.toString().c_str(); + + if ( HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) != 0 ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) - 1)); + } + else if ( HdmiCecSink::_instance->deviceList[n].m_physicalAddr.getByteValue(0) == 0 ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s", "TV"); + } + + temp << (char *)routeString; + response["port"] = temp.str(); + + } + else + { + response["available"] = false; + } + + returnResponse(true); + } + + uint32_t HdmiCecSink::getDeviceListWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + response["numberofdevices"] = HdmiCecSink::_instance->m_numberOfDevices; + LOGINFO("getDeviceListWrapper m_numberOfDevices :%d \n", HdmiCecSink::_instance->m_numberOfDevices); + JsonArray deviceList; + + for (int n = 0; n <= LogicalAddress::UNREGISTERED; n++) + { + + if ( n != HdmiCecSink::_instance->m_logicalAddressAllocated && + HdmiCecSink::_instance->deviceList[n].m_isDevicePresent ) + { + JsonObject device; + + device["logicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt(); + device["physicalAddress"] = HdmiCecSink::_instance->deviceList[n].m_physicalAddr.toString().c_str(); + device["deviceType"] = HdmiCecSink::_instance->deviceList[n].m_deviceType.toString().c_str(); + device["cecVersion"] = HdmiCecSink::_instance->deviceList[n].m_cecVersion.toString().c_str(); + device["osdName"] = HdmiCecSink::_instance->deviceList[n].m_osdName.toString().c_str(); + device["vendorID"] = HdmiCecSink::_instance->deviceList[n].m_vendorID.toString().c_str(); + device["powerStatus"] = HdmiCecSink::_instance->deviceList[n].m_powerStatus.toString().c_str(); + int hdmiPortNumber = -1; + LOGINFO("getDeviceListWrapper m_numofHdmiInput:%d looking for Logical Address :%d \n", m_numofHdmiInput, HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt()); + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO("getDeviceListWrapper connected : %d, portid:%d LA: %d \n", hdmiInputs[i].m_isConnected, hdmiInputs[i].m_portID, hdmiInputs[i].m_logicalAddr.toInt()); + if(hdmiInputs[i].m_isConnected && hdmiInputs[i].m_logicalAddr.toInt() == HdmiCecSink::_instance->deviceList[n].m_logicalAddress.toInt()) + { + hdmiPortNumber = hdmiInputs[i].m_portID; + LOGINFO("got portid :%d break \n", hdmiPortNumber); + break; + } + } + device["portNumber"] = hdmiPortNumber; + deviceList.Add(device); + } + } + + response["deviceList"] = deviceList; + + returnResponse(true); + } + + + uint32_t HdmiCecSink::setOSDNameWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + if (parameters.HasLabel("name")) + { + std::string osd = parameters["name"].String(); + LOGINFO("setOSDNameWrapper osdName: %s",osd.c_str()); + osdName = osd.c_str(); + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OSD_NAME, JsonValue(osd.c_str())); + } + else { - ASSERT(_service != nullptr); - Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE)); + returnResponse(false); } + returnResponse(true); + } + + uint32_t HdmiCecSink::getOSDNameWrapper(const JsonObject& parameters, JsonObject& response) + { + response["name"] = osdName.toString(); + LOGINFO("getOSDNameWrapper osdName : %s \n",osdName.toString().c_str()); + returnResponse(true); } + uint32_t HdmiCecSink::printDeviceListWrapper(const JsonObject& parameters, JsonObject& response) + { + printDeviceList(); + response["printed"] = true; + returnResponse(true); + } + + uint32_t HdmiCecSink::setActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) + { + setActiveSource(false); + returnResponse(true); + } + + uint32_t HdmiCecSink::setActivePathWrapper(const JsonObject& parameters, JsonObject& response) + { + if (parameters.HasLabel("activePath")) + { + std::string id = parameters["activePath"].String(); + PhysicalAddress phy_addr = PhysicalAddress(id); + + LOGINFO("Addr = %s, length = %zu", id.c_str(), id.length()); + + setStreamPath(phy_addr); + returnResponse(true); + } + else + { + returnResponse(false); + } + } + + uint32_t HdmiCecSink::getActiveRouteWrapper(const JsonObject& parameters, JsonObject& response) + { + std::vector route; + char routeString[1024] = {'\0'}; + int length = 0; + JsonArray pathList; + std::stringstream temp; + + if (HdmiCecSink::_instance->m_currentActiveSource != -1 && + HdmiCecSink::_instance->m_currentActiveSource != HdmiCecSink::_instance->m_logicalAddressAllocated ) + { + HdmiCecSink::_instance->getActiveRoute(LogicalAddress(HdmiCecSink::_instance->m_currentActiveSource), route); + + if (route.size()) + { + response["available"] = true; + response["length"] = route.size(); + + for (unsigned int i=0; i < route.size(); i++) + { + if ( route[i] != LogicalAddress::UNREGISTERED ) + { + JsonObject device; + + device["logicalAddress"] = HdmiCecSink::_instance->deviceList[route[i]].m_logicalAddress.toInt(); + device["physicalAddress"] = HdmiCecSink::_instance->deviceList[route[i]].m_physicalAddr.toString().c_str(); + device["deviceType"] = HdmiCecSink::_instance->deviceList[route[i]].m_deviceType.toString().c_str(); + device["osdName"] = HdmiCecSink::_instance->deviceList[route[i]].m_osdName.toString().c_str(); + device["vendorID"] = HdmiCecSink::_instance->deviceList[route[i]].m_vendorID.toString().c_str(); + + pathList.Add(device); + + snprintf(&routeString[length], sizeof(routeString) - length, "%s", _instance->deviceList[route[i]].m_logicalAddress.toString().c_str()); + length += _instance->deviceList[route[i]].m_logicalAddress.toString().length(); + snprintf(&routeString[length], sizeof(routeString) - length, "(%s", _instance->deviceList[route[i]].m_osdName.toString().c_str()); + length += _instance->deviceList[route[i]].m_osdName.toString().length(); + snprintf(&routeString[length], sizeof(routeString) - length, "%s", ")-->"); + length += strlen(")-->"); + if( i + 1 == route.size() ) + { + snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSink::_instance->deviceList[route[i]].m_physicalAddr.getByteValue(0) - 1)); + } + } + } + + response["pathList"] = pathList; + temp << (char *)routeString; + response["ActiveRoute"] = temp.str(); + LOGINFO("ActiveRoute = [%s]", routeString); + } + + } + else if ( HdmiCecSink::_instance->m_currentActiveSource == HdmiCecSink::_instance->m_logicalAddressAllocated ) + { + response["available"] = true; + response["ActiveRoute"] = "TV"; + } + else + { + response["available"] = false; + } + + returnResponse(true); + } + + uint32_t HdmiCecSink::requestActiveSourceWrapper(const JsonObject& parameters, JsonObject& response) + { + requestActiveSource(); + returnResponse(true); + } + + uint32_t HdmiCecSink::setRoutingChangeWrapper(const JsonObject& parameters, JsonObject& response) + { + std::string oldPortID; + std::string newPortID; + + returnIfParamNotFound(parameters, "oldPort"); + returnIfParamNotFound(parameters, "newPort"); + + oldPortID = parameters["oldPort"].String(); + newPortID = parameters["newPort"].String(); + + + if ((oldPortID.find("HDMI",0) != std::string::npos || + oldPortID.find("TV",0) != std::string::npos ) && + ( newPortID.find("HDMI", 0) != std::string::npos || + newPortID.find("TV", 0) != std::string::npos )) + { + setRoutingChange(oldPortID, newPortID); + returnResponse(true); + } + else + { + returnResponse(false); + } + } + + + uint32_t HdmiCecSink::setMenuLanguageWrapper(const JsonObject& parameters, JsonObject& response) + { + std::string lang; + + returnIfParamNotFound(parameters, "language"); + + lang = parameters["language"].String(); + + setCurrentLanguage(Language(lang.data())); + sendMenuLanguage(); + returnResponse(true); + } + + + uint32_t HdmiCecSink::setVendorIdWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFOMETHOD(); + + if (parameters.HasLabel("vendorid")) + { + std::string id = parameters["vendorid"].String(); + unsigned int vendorID = 0x00; + try + { + vendorID = stoi(id,NULL,16); + } + catch (...) + { + LOGWARN("Exception in setVendorIdWrapper set default value\n"); + vendorID = 0x0019FB; + } + appVendorId = {(uint8_t)(vendorID >> 16 & 0xff),(uint8_t)(vendorID>> 8 & 0xff),(uint8_t) (vendorID & 0xff)}; + LOGINFO("appVendorId : %s vendorID :%x \n",appVendorId.toString().c_str(), vendorID ); + + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_VENDOR_ID, JsonValue(vendorID)); + } + else + { + returnResponse(false); + } + returnResponse(true); + } + uint32_t HdmiCecSink::setArcEnableDisableWrapper(const JsonObject& parameters, JsonObject& response) + { + + bool enabled = false; + + if (parameters.HasLabel("enabled")) + { + getBoolParameter("enabled", enabled); + } + else + { + returnResponse(false); + } + if(enabled) + { + startArc(); + } + else + { + stopArc(); + + } + + returnResponse(true); + } + uint32_t HdmiCecSink::getVendorIdWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("getVendorIdWrapper appVendorId : %s \n",appVendorId.toString().c_str()); + response["vendorid"] = appVendorId.toString() ; + returnResponse(true); + } + + uint32_t HdmiCecSink::requestShortAudioDescriptorWrapper(const JsonObject& parameters, JsonObject& response) + { + requestShortaudioDescriptor(); + returnResponse(true); + } + uint32_t HdmiCecSink::sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response) + { + sendStandbyMessage(); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendAudioDevicePowerOnMsgWrapper(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("%s invoked. \n",__FUNCTION__); + systemAudioModeRequest(); + returnResponse(true); + } + uint32_t HdmiCecSink::sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response) + { + returnIfParamNotFound(parameters, "logicalAddress"); + returnIfParamNotFound(parameters, "keyCode"); + string logicalAddress = parameters["logicalAddress"].String(); + string keyCode = parameters["keyCode"].String(); + SendKeyInfo keyInfo; + keyInfo.logicalAddr = stoi(logicalAddress); + keyInfo.keyCode = stoi(keyCode); + keyInfo.UserControl = "sendKeyPressEvent"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("Post send key press event to queue size:%zu \n",m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendUserControlPressedWrapper(const JsonObject& parameters, JsonObject& response) + { + returnIfParamNotFound(parameters, "logicalAddress"); + returnIfParamNotFound(parameters, "keyCode"); + string logicalAddress = parameters["logicalAddress"].String(); + string keyCode = parameters["keyCode"].String(); + SendKeyInfo keyInfo; + keyInfo.logicalAddr = stoi(logicalAddress); + keyInfo.keyCode = stoi(keyCode); + keyInfo.UserControl = "sendUserControlPressed"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("User control pressed, queue size:%zu \n",m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendUserControlReleasedWrapper(const JsonObject& parameters, JsonObject& response) + { + returnIfParamNotFound(parameters, "logicalAddress"); + string logicalAddress = parameters["logicalAddress"].String(); + SendKeyInfo keyInfo; + keyInfo.logicalAddr = stoi(logicalAddress); + keyInfo.keyCode = 0; + keyInfo.UserControl = "sendUserControlReleased"; + std::unique_lock lk(m_sendKeyEventMutex); + m_SendKeyQueue.push(keyInfo); + m_sendKeyEventThreadRun = true; + m_sendKeyCV.notify_one(); + LOGINFO("User Control Released, queue size:%zu \n",m_SendKeyQueue.size()); + returnResponse(true); + } + + uint32_t HdmiCecSink::sendGiveAudioStatusWrapper(const JsonObject& parameters, JsonObject& response) + { + sendGiveAudioStatusMsg(); + returnResponse(true); + } + uint32_t HdmiCecSink::setLatencyInfoWrapper(const JsonObject& parameters, JsonObject& response) + { + int video_latency,audio_output_compensated,audio_output_delay; + bool low_latency_mode; + + returnIfParamNotFound(parameters, "videoLatency"); + returnIfParamNotFound(parameters, "lowLatencyMode"); + returnIfParamNotFound(parameters, "audioOutputCompensated"); + returnIfParamNotFound(parameters, "audioOutputDelay"); + video_latency = stoi(parameters["videoLatency"].String()); + low_latency_mode = stoi(parameters["lowLatencyMode"].String()); + audio_output_compensated = stoi(parameters["audioOutputCompensated"].String()); + audio_output_delay = stoi(parameters["audioOutputDelay"].String()); + + updateCurrentLatency(video_latency, low_latency_mode,audio_output_compensated, audio_output_delay); + returnResponse(true); + } + bool HdmiCecSink::loadSettings() + { + Core::File file; + file = CEC_SETTING_ENABLED_FILE; + + if( file.Open()) + { + JsonObject parameters; + parameters.IElement::FromFile(file); + bool isConfigAdded = false; + + if( parameters.HasLabel(CEC_SETTING_ENABLED)) + { + getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); + LOGINFO("CEC_SETTING_ENABLED present value:%d",cecSettingEnabled); + } + else + { + parameters[CEC_SETTING_ENABLED] = true; + cecSettingEnabled = true; + isConfigAdded = true; + LOGINFO("CEC_SETTING_ENABLED not present set dafult true:\n "); + } + + if( parameters.HasLabel(CEC_SETTING_OTP_ENABLED)) + { + getBoolParameter(CEC_SETTING_OTP_ENABLED, cecOTPSettingEnabled); + LOGINFO("CEC_SETTING_OTP_ENABLED present value :%d",cecOTPSettingEnabled); + } + else + { + parameters[CEC_SETTING_OTP_ENABLED] = true; + cecOTPSettingEnabled = true; + isConfigAdded = true; + LOGINFO("CEC_SETTING_OTP_ENABLED not present set dafult true:\n "); + } + if( parameters.HasLabel(CEC_SETTING_OSD_NAME)) + { + std::string osd_name; + getStringParameter(CEC_SETTING_OSD_NAME, osd_name); + osdName = osd_name.c_str(); + LOGINFO("CEC_SETTING_OSD_NAME present osd_name :%s",osdName.toString().c_str()); + } + else + { + parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); + LOGINFO("CEC_SETTING_OSD_NMAE not present set dafult value :%s\n ",osdName.toString().c_str()); + isConfigAdded = true; + } + unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); + if( parameters.HasLabel(CEC_SETTING_VENDOR_ID)) + { + getNumberParameter(CEC_SETTING_VENDOR_ID, vendorId); + LOGINFO("CEC_SETTING_VENDOR_ID present :%x ",vendorId); + } + else + { + LOGINFO("CEC_SETTING_VENDOR_ID not present set dafult value :%x \n ",vendorId); + parameters[CEC_SETTING_VENDOR_ID] = vendorId; + isConfigAdded = true; + } + + appVendorId = {(uint8_t)(vendorId >> 16 & 0xff),(uint8_t)(vendorId >> 8 & 0xff),(uint8_t) (vendorId & 0xff)}; + LOGINFO("appVendorId : %s vendorId :%x \n",appVendorId.toString().c_str(), vendorId ); + + if(isConfigAdded) + { + LOGINFO("isConfigAdded true so update file:\n "); + file.Destroy(); + file.Create(); + parameters.IElement::ToFile(file); + + } + + file.Close(); + } + else + { + LOGINFO("CEC_SETTING_ENABLED_FILE file not present create with default settings "); + file.Open(false); + if (!file.IsOpen()) + file.Create(); + + JsonObject parameters; + unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); + parameters[CEC_SETTING_ENABLED] = true; + parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); + parameters[CEC_SETTING_VENDOR_ID] = vendorId; + + cecSettingEnabled = true; + cecOTPSettingEnabled = true; + parameters.IElement::ToFile(file); + + file.Close(); + + } + + return cecSettingEnabled; + } + + void HdmiCecSink::setEnabled(bool enabled) + { + LOGINFO("Entered setEnabled: %d cecSettingEnabled :%d ",enabled, cecSettingEnabled); + + if (cecSettingEnabled != enabled) + { + Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); + cecSettingEnabled = enabled; + } + if(true == enabled) + { + CECEnable(); + } + else + { + CECDisable(); + } + return; + } + + void HdmiCecSink::updateImageViewOn(const int logicalAddress) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); + } + + sendNotify(eventString[HDMICECSINK_EVENT_IMAGE_VIEW_ON_MSG], params); + } + + void HdmiCecSink::updateTextViewOn(const int logicalAddress) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); + } + + sendNotify(eventString[HDMICECSINK_EVENT_TEXT_VIEW_ON_MSG], params); + } + + + void HdmiCecSink::updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr) + { + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && + logicalAddress.toInt() != _instance->m_logicalAddressAllocated) + { + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO(" addr = %d, portID = %d", phy_addr.getByteValue(0), hdmiInputs[i].m_portID); + if (phy_addr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].addChild(logicalAddress, phy_addr); + } + } + } + } + + void HdmiCecSink::getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route) + { + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || + logicalAddress.toInt() == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && + logicalAddress.toInt() != _instance->m_logicalAddressAllocated && + _instance->deviceList[logicalAddress.toInt()].m_isActiveSource ) + { + route.clear(); + for (int i=0; i < m_numofHdmiInput; i++) + { + LOGINFO("physicalAddress = [%d], portID = %d", _instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0), hdmiInputs[i].m_portID); + if (_instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].getRoute(_instance->deviceList[logicalAddress.toInt()].m_physicalAddr, route); + } + } + } + else { + LOGERR("Not in correct state to Find Route"); + } + } + + + void HdmiCecSink::CheckHdmiInState() + { + int err; + bool isAnyPortConnected = false; + + dsHdmiInGetStatusParam_t params; + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + IARM_BUS_DSMGR_API_dsHdmiInGetStatus, + (void *)¶ms, + sizeof(params)); + + if(err == IARM_RESULT_SUCCESS && params.result == dsERR_NONE ) + { + for( int i = 0; i < m_numofHdmiInput; i++ ) + { + LOGINFO("Is HDMI In Port [%d] connected [%d] \n",i, params.status.isPortConnected[i]); + if ( params.status.isPortConnected[i] ) + { + isAnyPortConnected = true; + } + + LOGINFO("update Port Status [%d] \n", i); + hdmiInputs[i].update(params.status.isPortConnected[i]); + } + } + + if ( isAnyPortConnected ) { + m_isHdmiInConnected = true; + } else { + m_isHdmiInConnected = false; + } + } + + void HdmiCecSink::requestActiveSource() + { + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, + MessageEncoder().encode(RequestActiveSource()), 500); + } + + void HdmiCecSink::setActiveSource(bool isResponse) + { + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (isResponse && (_instance->m_currentActiveSource != _instance->m_logicalAddressAllocated) ) + { + LOGWARN("TV is not current Active Source"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, + MessageEncoder().encode(ActiveSource(_instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr)), 500); + _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; + } + + void HdmiCecSink::setCurrentLanguage(const Language &lang) + { + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = lang; + } + + void HdmiCecSink::sendMenuLanguage() + { + Language lang = ""; + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + lang = _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage; + + _instance->smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(SetMenuLanguage(lang)), 100); + } + + void HdmiCecSink::updateInActiveSource(const int logical_address, const InActiveSource &source ) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if( logical_address != _instance->m_logicalAddressAllocated ) + { + _instance->deviceList[logical_address].m_isActiveSource = false; + + if ( _instance->m_currentActiveSource == logical_address ) + { + _instance->m_currentActiveSource = -1; + } + + params["logicalAddress"] = JsonValue(logical_address); + params["phsicalAddress"] = source.physicalAddress.toString().c_str(); + sendNotify(eventString[HDMICECSINK_EVENT_INACTIVE_SOURCE], params); + } + } + + void HdmiCecSink::updateActiveSource(const int logical_address, const ActiveSource &source ) + { + JsonObject params; + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if( logical_address != _instance->m_logicalAddressAllocated ) + { + if ( _instance->m_currentActiveSource != -1 ) + { + _instance->deviceList[_instance->m_currentActiveSource].m_isActiveSource = false; + } + + _instance->deviceList[logical_address].m_isActiveSource = true; + _instance->deviceList[logical_address].update(source.physicalAddress); + _instance->m_currentActiveSource = logical_address; + + if (_instance->deviceList[logical_address].m_isDevicePresent && + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) + { + /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ + sendNotify(eventString[HDMICECSINK_EVENT_WAKEUP_FROM_STANDBY], params); + } + + params["logicalAddress"] = JsonValue(logical_address); + params["physicalAddress"] = _instance->deviceList[logical_address].m_physicalAddr.toString().c_str(); + sendNotify(eventString[HDMICECSINK_EVENT_ACTIVE_SOURCE_CHANGE], params); + } + } + + void HdmiCecSink::requestShortaudioDescriptor() + { + if ( cecEnableStatus != true ) + { + LOGINFO("requestShortaudioDescriptor: cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + LOGINFO(" Send requestShortAudioDescriptor Message "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestShortAudioDescriptor(formatid,audioFormatCode,numberofdescriptor)), 1000); + + } + + void HdmiCecSink::requestAudioDevicePowerStatus() + { + if ( cecEnableStatus != true ) + { + LOGWARN("cec is disabled-> EnableCEC first"); + return; + } + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + LOGINFO(" Send GiveDevicePowerStatus Message to Audio system in the network \n"); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM, MessageEncoder().encode(GiveDevicePowerStatus()), 500); + + m_audioDevicePowerStatusRequested = true; + } + + void HdmiCecSink::sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason) + { + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Sending FeatureAbort to %s for opcode %s with reason %s ",logicalAddress.toString().c_str(),feature.toString().c_str(),reason.toString().c_str()); + _instance->smConnection->sendTo(logicalAddress, MessageEncoder().encode(FeatureAbort(feature,reason)), 500); + } + + void HdmiCecSink::reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode featureOpcode, const AbortReason abortReason) + { + LOGINFO(" Notifying the UI FeatureAbort from the %s for the opcode %s with the reason %s ",logicalAddress.toString().c_str(),featureOpcode.toString().c_str(),abortReason.toString().c_str()); + JsonObject params; + params["LogicalAddress"] = logicalAddress.toInt(); + params["opcode"] = featureOpcode.opCode(); + params["FeatureAbortReason"] = abortReason.toInt(); + sendNotify(eventString[HDMICECSINK_EVENT_FEATURE_ABORT_EVENT], params); + } + + void HdmiCecSink::pingDevices(std::vector &connected , std::vector &disconnected) + { + int i; + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { + if ( i != _instance->m_logicalAddressAllocated ) + { + //LOGWARN("PING for 0x%x \r\n",i); + try { + _instance->smConnection->ping(LogicalAddress(_instance->m_logicalAddressAllocated), LogicalAddress(i), Throw_e()); + } + catch(CECNoAckException &e) + { + if ( _instance->deviceList[i].m_isDevicePresent ) { + disconnected.push_back(i); + } + //LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); + usleep(50000); + continue; + } + catch(Exception &e) + { + LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); + usleep(50000); + continue; + } + + /* If we get ACK, then the device is present in the network*/ + if ( !_instance->deviceList[i].m_isDevicePresent ) + { + connected.push_back(i); + //LOGWARN("Ping success, added device: 0x%x \r\n", i); + } + usleep(50000); + } + } + } + + int HdmiCecSink::requestType( const int logicalAddress ) { + int requestType = CECDeviceParams::REQUEST_NONE; + + if ( !_instance->deviceList[logicalAddress].m_isPAUpdated || !_instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) { + requestType = CECDeviceParams::REQUEST_PHISICAL_ADDRESS; + }else if ( !_instance->deviceList[logicalAddress].m_isOSDNameUpdated ) { + requestType = CECDeviceParams::REQUEST_OSD_NAME; + }else if ( !_instance->deviceList[logicalAddress].m_isVersionUpdated ) { + requestType = CECDeviceParams::REQUEST_CEC_VERSION; + }else if ( !_instance->deviceList[logicalAddress].m_isVendorIDUpdated ) { + requestType = CECDeviceParams::REQUEST_DEVICE_VENDOR_ID; + }else if ( !_instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) { + requestType = CECDeviceParams::REQUEST_POWER_STATUS; + } + + return requestType; + } + + void HdmiCecSink::printDeviceList() { + int i; + + if(!HdmiCecSink::_instance) + return; + + for(i=0; i< 16; i++) + { + if (HdmiCecSink::_instance->deviceList[i].m_isDevicePresent) { + LOGWARN("------ Device ID = %d--------", i); + HdmiCecSink::_instance->deviceList[i].printVariable(); + LOGWARN("-----------------------------"); + } + } + } + + void HdmiCecSink::setStreamPath( const PhysicalAddress &physical_addr) { + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(SetStreamPath(physical_addr)), 500); + } + + void HdmiCecSink::setRoutingChange(const std::string &from, const std::string &to) { + PhysicalAddress oldPhyAddr = {0xF,0xF,0xF,0xF}; + PhysicalAddress newPhyAddr = {0xF,0xF,0xF,0xF}; + int oldPortID = -1; + int newPortID = -1; + + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + if( from.find("TV",0) != std::string::npos ) + { + oldPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; + _instance->m_currentActiveSource = -1; + } + else + { + oldPortID = stoi(from.substr(4,1),NULL,16); + if ( oldPortID < _instance->m_numofHdmiInput ) + { + oldPhyAddr = _instance->hdmiInputs[oldPortID].m_physicalAddr; + } + else + { + LOGERR("Invalid HDMI Old Port ID"); + return; + } + } + + if( to.find("TV",0) != std::string::npos ) + { + newPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; + /*set active source as TV */ + _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; + } + else + { + newPortID = stoi(to.substr(4,1),NULL,16); + + if ( newPortID < _instance->m_numofHdmiInput ) + { + newPhyAddr = _instance->hdmiInputs[newPortID].m_physicalAddr; + } + else + { + LOGERR("Invalid HDMI New Port ID"); + return; + } + } + + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(RoutingChange(oldPhyAddr, newPhyAddr)), 500); + } + + void HdmiCecSink::addDevice(const int logicalAddress) { + JsonObject params; + + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if ( !HdmiCecSink::_instance->deviceList[logicalAddress].m_isDevicePresent ) + { + HdmiCecSink::_instance->deviceList[logicalAddress].m_isDevicePresent = true; + HdmiCecSink::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); + HdmiCecSink::_instance->m_numberOfDevices++; + HdmiCecSink::_instance->m_pollNextState = POLL_THREAD_STATE_INFO; + + if(logicalAddress == 0x5) + { + LOGINFO(" logicalAddress =%d , Audio device detected, Notify Device Settings", logicalAddress ); + params["status"] = string("success"); + params["audioDeviceConnected"] = string("true"); + hdmiCecAudioDeviceConnected = true; + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); + } + + sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_ADDED], JsonObject()); + } + } + + void HdmiCecSink::removeDevice(const int logicalAddress) { + JsonObject params; + + if(!HdmiCecSink::_instance) + return; + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ + LOGERR("Logical Address NOT Allocated"); + return; + } + + if (_instance->deviceList[logicalAddress].m_isDevicePresent) + { + _instance->m_numberOfDevices--; + + for (int i=0; i < m_numofHdmiInput; i++) + { + if (_instance->deviceList[logicalAddress].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { + hdmiInputs[i].removeChild(_instance->deviceList[logicalAddress].m_physicalAddr); + hdmiInputs[i].update(LogicalAddress(LogicalAddress::UNREGISTERED)); + } + } + + if(logicalAddress == 0x5) + { + LOGINFO(" logicalAddress =%d , Audio device removed, Notify Device Settings", logicalAddress ); + params["status"] = string("success"); + params["audioDeviceConnected"] = string("false"); + hdmiCecAudioDeviceConnected = false; + if (m_audioStatusDetectionTimer.isActive()){ + m_audioStatusDetectionTimer.stop(); + } + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + sendNotify(eventString[HDMICECSINK_EVENT_AUDIO_DEVICE_CONNECTED_STATUS], params); + } + + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + _instance->deviceList[logicalAddress].clear(); + sendNotify(eventString[HDMICECSINK_EVENT_DEVICE_REMOVED], JsonObject()); + } + } + + void HdmiCecSink::request(const int logicalAddress) { + int requestType; + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ){ + LOGERR("Logical Address NOT Allocated Or its not valid"); + return; + } + + requestType = _instance->requestType(logicalAddress); + _instance->deviceList[logicalAddress].m_isRequested = requestType; + + switch (requestType) + { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GivePhysicalAddress()), 200); + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GetCECVersion()), 100); + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDeviceVendorID()), 100); + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveOSDName()), 500); + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDevicePowerStatus()), 100); + } + break; + default: + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + break; + } + + _instance->deviceList[logicalAddress].m_requestTime = std::chrono::system_clock::now(); + LOGINFO("request type %d", _instance->deviceList[logicalAddress].m_isRequested); + } + + int HdmiCecSink::requestStatus(const int logicalAddress) { + std::chrono::duration elapsed; + bool isElapsed = false; + + if(!HdmiCecSink::_instance) + return -1; + + + if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ) { + LOGERR("Logical Address NOT Allocated Or its not valid"); + return -1; + } + + switch ( _instance->deviceList[logicalAddress].m_isRequested ) { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + if( _instance->deviceList[logicalAddress].m_isPAUpdated && + _instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + if( _instance->deviceList[logicalAddress].m_isVersionUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + if( _instance->deviceList[logicalAddress].m_isVendorIDUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + if( _instance->deviceList[logicalAddress].m_isOSDNameUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + if( _instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) + { + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + } + break; + default: + break; + } + + if ( _instance->deviceList[logicalAddress].m_isRequested != CECDeviceParams::REQUEST_NONE ) + { + elapsed = std::chrono::system_clock::now() - _instance->deviceList[logicalAddress].m_requestTime; + + if ( elapsed.count() > HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS ) + { + LOGINFO("request elapsed "); + isElapsed = true; + } + } + + if (isElapsed) + { + /* For some request it should be retry, like report physical address etc for other we can have default values */ + switch( _instance->deviceList[logicalAddress].m_isRequested ) + { + case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : + { + LOGINFO("Retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + /* Update with Invalid Physical Address */ + if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) + { + LOGINFO("Max retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + _instance->deviceList[logicalAddress].update(PhysicalAddress(0xF,0xF,0xF,0xF)); + _instance->deviceList[logicalAddress].update(DeviceType(DeviceType::RESERVED)); + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + } + } + break; + + case CECDeviceParams::REQUEST_CEC_VERSION : + { + /*Defaulting to 1.4*/ + _instance->deviceList[logicalAddress].update(Version(Version::V_1_4)); + } + break; + + case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : + { + _instance->deviceList[logicalAddress].update(VendorID(0,0,0)); + } + break; + + case CECDeviceParams::REQUEST_OSD_NAME : + { + if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) + { + LOGINFO("Max retry for REQUEST_OSD_NAME = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); + _instance->deviceList[logicalAddress].update(OSDName("")); + _instance->deviceList[logicalAddress].m_isRequestRetry = 0; + } + } + break; + + case CECDeviceParams::REQUEST_POWER_STATUS : + { + _instance->deviceList[logicalAddress].update(PowerStatus(PowerStatus::POWER_STATUS_NOT_KNOWN)); + } + break; + default: + break; + } + + + _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; + } + + if( _instance->deviceList[logicalAddress].m_isRequested == CECDeviceParams::REQUEST_NONE) + { + LOGINFO("Request Done"); + return CECDeviceParams::REQUEST_DONE; + } + + //LOGINFO("Request NOT Done"); + return CECDeviceParams::REQUEST_NOT_DONE; + } + + void HdmiCecSink::threadRun() + { + std::vector connected; + std::vector disconnected; + int logicalAddressRequested = LogicalAddress::UNREGISTERED + TEST_ADD; + bool isExit = false; + + if(!HdmiCecSink::_instance) + return; + + if(!(_instance->smConnection)) + return; + LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); + _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; + + while(1) + { + + if (_instance->m_pollThreadExit || isExit ){ + LOGWARN("Thread Exits _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); + break; + } + + if ( _instance->m_pollNextState != POLL_THREAD_STATE_NONE ) + { + _instance->m_pollThreadState = _instance->m_pollNextState; + _instance->m_pollNextState = POLL_THREAD_STATE_NONE; + } + + switch (_instance->m_pollThreadState) { + + case POLL_THREAD_STATE_POLL : + { + //LOGINFO("POLL_THREAD_STATE_POLL"); + _instance->allocateLogicalAddress(DeviceType::TV); + if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED) + { + try{ + + logicalAddress = LogicalAddress(_instance->m_logicalAddressAllocated); + LibCCEC::getInstance().addLogicalAddress(logicalAddress); + _instance->smConnection->setSource(logicalAddress); + _instance->m_numberOfDevices = 0; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType = DeviceType::TV; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_isDevicePresent = true; + _instance->deviceList[_instance->m_logicalAddressAllocated].update(physical_addr); + _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_1_4; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_vendorID = appVendorId; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); + _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = defaultLanguage; + _instance->deviceList[_instance->m_logicalAddressAllocated].m_osdName = osdName.toString().c_str(); + if(cecVersion == 2.0) { + _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_2_0; + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), + MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures)), 500); + } + _instance->smConnection->addFrameListener(_instance->msgFrameListener); + _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), + MessageEncoder().encode(ReportPhysicalAddress(physical_addr, _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType)), 100); + + _instance->m_sleepTime = 0; + _instance->m_pollThreadState = POLL_THREAD_STATE_PING; + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught while allocated logical address. %s", e.what()); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + catch(IOException &e){ + LOGWARN("IOException caught while allocated logical address. %s", e.what()); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + catch(...){ + LOGWARN("Exception caught while allocated logical address."); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + } + else + { + LOGINFO("Not able allocate Logical Address for TV"); + _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; + } + } + break; + + case POLL_THREAD_STATE_PING : + { + //LOGINFO("POLL_THREAD_STATE_PING"); + _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; + connected.clear(); + disconnected.clear(); + _instance->pingDevices(connected, disconnected); + + if ( disconnected.size() ){ + for( unsigned int i=0; i< disconnected.size(); i++ ) + { + LOGWARN("Disconnected Devices [%zu]", disconnected.size()); + _instance->removeDevice(disconnected[i]); + } + } + + if (connected.size()) { + LOGWARN("Connected Devices [%zu]", connected.size()); + for( unsigned int i=0; i< connected.size(); i++ ) + { + _instance->addDevice(connected[i]); + /* If new device is connected, then try to aquire the information */ + _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + else + { + for(int i=0;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + !_instance->deviceList[i].isAllUpdated() ) + { + _instance->m_pollNextState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + /* Check for any update required */ + _instance->m_pollThreadState = POLL_THREAD_STATE_UPDATE; + _instance->m_sleepTime = 0; + } + } + break; + + case POLL_THREAD_STATE_INFO : + { + //LOGINFO("POLL_THREAD_STATE_INFO"); + + if ( logicalAddressRequested == LogicalAddress::UNREGISTERED + TEST_ADD ) + { + int i = 0; + for(;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + !_instance->deviceList[i].isAllUpdated() ) + { + //LOGINFO("POLL_THREAD_STATE_INFO -> request for %d", i); + logicalAddressRequested = i; + _instance->request(logicalAddressRequested); + _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; + break; + } + } + + if ( i == LogicalAddress::UNREGISTERED) + { + /*So there is no update required, try to ping after some seconds*/ + _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; + _instance->m_sleepTime = 0; + //LOGINFO("POLL_THREAD_STATE_INFO -> state change to Ping", i); + } + } + else + { + /*So there is request sent for logical address, so wait and check the status */ + if ( _instance->requestStatus(logicalAddressRequested) == CECDeviceParams::REQUEST_DONE ) + { + logicalAddressRequested = LogicalAddress::UNREGISTERED; + } + else + { + _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; + } + } + } + break; + + /* updating the power status and if required we can add other information later*/ + case POLL_THREAD_STATE_UPDATE : + { + //LOGINFO("POLL_THREAD_STATE_UPDATE"); + + for(int i=0;im_logicalAddressAllocated && + _instance->deviceList[i].m_isDevicePresent && + _instance->deviceList[i].m_isPowerStatusUpdated ) + { + std::chrono::duration elapsed = std::chrono::system_clock::now() - _instance->deviceList[i].m_lastPowerUpdateTime; + + if ( elapsed.count() > HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS ) + { + _instance->deviceList[i].m_isPowerStatusUpdated = false; + _instance->m_pollNextState = POLL_THREAD_STATE_INFO; + _instance->m_sleepTime = 0; + } + } + } + + _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; + _instance->m_sleepTime = 0; + } + break; + + case POLL_THREAD_STATE_IDLE : + { + //LOGINFO("POLL_THREAD_STATE_IDLE"); + _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; + _instance->m_pollThreadState = POLL_THREAD_STATE_PING; + } + break; + + case POLL_THREAD_STATE_WAIT : + { + /* Wait for Hdmi is connected, in case it disconnected */ + //LOGINFO("19Aug2020-[01] -> POLL_THREAD_STATE_WAIT"); + _instance->m_sleepTime = HDMICECSINK_WAIT_FOR_HDMI_IN_MS; + + if ( _instance->m_isHdmiInConnected == true ) + { + _instance->m_pollThreadState = POLL_THREAD_STATE_POLL; + } + } + break; + + case POLL_THREAD_STATE_EXIT : + { + isExit = true; + _instance->m_sleepTime = 0; + } + break; + } + + std::unique_lock lk(_instance->m_pollExitMutex); + if ( _instance->m_ThreadExitCV.wait_for(lk, std::chrono::milliseconds(_instance->m_sleepTime)) == std::cv_status::timeout ) + continue; + else + LOGINFO("Thread is going to Exit m_pollThreadExit %d\n", _instance->m_pollThreadExit ); + + } + } + + void HdmiCecSink::allocateLAforTV() + { + bool gotLogicalAddress = false; + int addr = LogicalAddress::TV; + int i, j; + if (!(_instance->smConnection)) + return; + + for (i = 0; i< HDMICECSINK_NUMBER_TV_ADDR; i++) + { + /* poll for TV logical address - retry 5 times*/ + for (j = 0; j < 5; j++) + { + try { + smConnection->poll(LogicalAddress(addr), Throw_e()); + } + catch(CECNoAckException &e ) + { + LOGWARN("Poll caught %s \r\n",e.what()); + gotLogicalAddress = true; + break; + } + catch(Exception &e) + { + LOGWARN("Poll caught %s \r\n",e.what()); + usleep(250000); + } + } + if (gotLogicalAddress) + { + break; + } + addr = LogicalAddress::SPECIFIC_USE; + } + + if ( gotLogicalAddress ) + { + m_logicalAddressAllocated = addr; + } + else + { + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + } + + LOGWARN("Logical Address for TV 0x%x \r\n",m_logicalAddressAllocated); + } + + void HdmiCecSink::allocateLogicalAddress(int deviceType) + { + if( deviceType == DeviceType::TV ) + { + allocateLAforTV(); + } + } + + void HdmiCecSink::CECEnable(void) + { + std::lock_guard lock(m_enableMutex); + JsonObject params; + LOGINFO("Entered CECEnable"); + if (cecEnableStatus) + { + LOGWARN("CEC Already Enabled"); + return; + } + + if(0 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().init("HdmiCecSink"); + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught in LibCCEC::init %s", e.what()); + } + catch(IOException &e){ + LOGWARN("IOException caught in LibCCEC::init %s", e.what()); + } + catch(...){ + LOGWARN("Exception caught in LibCCEC::init"); + } + } + libcecInitStatus++; + + //Acquire CEC Addresses + getPhysicalAddress(); + + smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); + smConnection->open(); + allocateLogicalAddress(DeviceType::TV); + LOGINFO("logical address allocalted: %x \n",m_logicalAddressAllocated); + if ( m_logicalAddressAllocated != LogicalAddress::UNREGISTERED && smConnection) + { + logicalAddress = LogicalAddress(m_logicalAddressAllocated); + LOGINFO(" add logical address %x \n",m_logicalAddressAllocated); + LibCCEC::getInstance().addLogicalAddress(logicalAddress); + smConnection->setSource(logicalAddress); + } + msgProcessor = new HdmiCecSinkProcessor(*smConnection); + msgFrameListener = new HdmiCecSinkFrameListener(*msgProcessor); + if(smConnection) + { + LOGWARN("Start Thread %p", smConnection ); + m_pollThreadState = POLL_THREAD_STATE_POLL; + m_pollNextState = POLL_THREAD_STATE_NONE; + m_pollThreadExit = false; + m_pollThread = std::thread(threadRun); + } + cecEnableStatus = true; + + params["cecEnable"] = string("true"); + sendNotify(eventString[HDMICECSINK_EVENT_CEC_ENABLED], params); + + return; + } + + void HdmiCecSink::CECDisable(void) + { + std::lock_guard lock(m_enableMutex); + JsonObject params; + LOGINFO("Entered CECDisable "); + if(!cecEnableStatus) + { + LOGWARN("CEC Already Disabled "); + return; + } + + if(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) + { + stopArc(); + while(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) + { + usleep(500000); + } + } + + LOGINFO(" CECDisable ARC stopped "); + cecEnableStatus = false; + if (smConnection != NULL) + { + LOGWARN("Stop Thread %p", smConnection ); + m_pollThreadExit = true; + m_ThreadExitCV.notify_one(); + + try + { + if (m_pollThread.joinable()) + { + LOGWARN("Join Thread %p", smConnection ); + m_pollThread.join(); + } + } + catch(const std::system_error& e) + { + LOGERR("system_error exception in thread join %s", e.what()); + } + catch(const std::exception& e) + { + LOGERR("exception in thread join %s", e.what()); + } + + m_pollThreadState = POLL_THREAD_STATE_NONE; + m_pollNextState = POLL_THREAD_STATE_NONE; + + LOGWARN("Deleted Thread %p", smConnection ); + + smConnection->close(); + delete smConnection; + smConnection = NULL; + } + + m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; + m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + if (m_audioStatusDetectionTimer.isActive()){ + m_audioStatusDetectionTimer.stop(); + } + m_isAudioStatusInfoUpdated = false; + m_audioStatusReceived = false; + m_audioStatusTimerStarted = false; + LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + + + for(int i=0; i< 16; i++) + { + if (_instance->deviceList[i].m_isDevicePresent) + { + _instance->deviceList[i].clear(); + } + } + + if(1 == libcecInitStatus) + { + try + { + LibCCEC::getInstance().term(); + } + catch(InvalidStateException &e){ + LOGWARN("InvalidStateException caught in LibCCEC::term %s", e.what()); + } + catch(IOException &e){ + LOGWARN("IOException caught in LibCCEC::term %s", e.what()); + } + catch(...){ + LOGWARN("Exception caught in LibCCEC::term"); + } + } + + libcecInitStatus--; + LOGWARN("CEC Disabled %d",libcecInitStatus); + + params["cecEnable"] = string("false"); + sendNotify(eventString[HDMICECSINK_EVENT_CEC_ENABLED], params); + + return; + } + + + void HdmiCecSink::getPhysicalAddress() + { + LOGINFO("Entered getPhysicalAddress "); + + uint32_t physAddress = 0x0F0F0F0F; + + try { + LibCCEC::getInstance().getPhysicalAddress(&physAddress); + physical_addr = {(uint8_t)((physAddress >> 24) & 0xFF),(uint8_t)((physAddress >> 16) & 0xFF),(uint8_t) ((physAddress >> 8) & 0xFF),(uint8_t)((physAddress) & 0xFF)}; + LOGINFO("getPhysicalAddress: physicalAddress: %s ", physical_addr.toString().c_str()); + } + catch (const std::exception& e) + { + LOGWARN("exception caught from getPhysicalAddress"); + } + return; + } + + bool HdmiCecSink::getEnabled() + { + + + LOGINFO("getEnabled :%d ",cecEnableStatus); + if(true == cecEnableStatus) + return true; + else + return false; + } + + bool HdmiCecSink::getAudioDeviceConnectedStatus() + { + LOGINFO("getAudioDeviceConnectedStatus :%d ", hdmiCecAudioDeviceConnected); + if(true == hdmiCecAudioDeviceConnected) + return true; + else + return false; + } + //Arc Routing related functions + void HdmiCecSink::startArc() + { + if ( cecEnableStatus != true ) + { + LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); + return; + } + if(!HdmiCecSink::_instance) + return; + + LOGINFO("Current ARC State : %d\n", m_currentArcRoutingState); + + _instance->requestArcInitiation(); + + // start initiate ARC timer 3 sec + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + m_arcstarting = true; + m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); + + } + void HdmiCecSink::requestArcInitiation() + { + { + std::lock_guard lock(m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_INITIATION; + } + LOGINFO("requestArcInitiation release sem"); + _instance->m_semSignaltoArcRoutingThread.release(); + + } + void HdmiCecSink::stopArc() + { + if ( cecEnableStatus != true ) + { + LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); + return; + } + if(!HdmiCecSink::_instance) + return; + if(m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_TERMINATION || m_currentArcRoutingState == ARC_STATE_ARC_TERMINATED) + { + LOGINFO("ARC is either Termination in progress or already Terminated"); + return; + } + + _instance->requestArcTermination(); + /* start a timer for 3 sec to get the desired ARC_STATE_ARC_TERMINATED */ + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + /* m_arcstarting = true means starting the ARC start timer ,false means ARC stopping timer*/ + m_arcstarting = false; + m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); + + + } + void HdmiCecSink::requestArcTermination() + { + { + std::lock_guard lock(m_arcRoutingStateMutex); + m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_TERMINATION; + } + LOGINFO("requestArcTermination release sem"); + _instance->m_semSignaltoArcRoutingThread.release(); + + } + + void HdmiCecSink::Process_InitiateArc() + { + JsonObject params; + + LOGINFO("Command: INITIATE_ARC \n"); + + if(!HdmiCecSink::_instance) + return; + + //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status + //Initiate ARC message may come from AVR/Soundbar while CEC disable is in-progress + if ( cecSettingEnabled != true ) + { + LOGINFO("Process InitiateArc from Audio device: Cec is disabled-> EnableCEC first"); + return; + } + + LOGINFO("Got : INITIATE_ARC and current Arcstate is %d\n",_instance->m_currentArcRoutingState); + + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + if (powerState == DEVICE_POWER_STATE_ON ) { + LOGINFO("Notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); + { + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + _instance->m_currentArcRoutingState = ARC_STATE_ARC_INITIATED; + } + _instance->m_semSignaltoArcRoutingThread.release(); + LOGINFO("Got : ARC_INITIATED and notify Device setting"); + params["status"] = string("success"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_INITIATION_EVENT], params); + } else { + LOGINFO("Not notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); + } + + } + void HdmiCecSink::Process_TerminateArc() + { + JsonObject params; + + LOGINFO("Command: TERMINATE_ARC current arc state %d \n",HdmiCecSink::_instance->m_currentArcRoutingState); + if (m_arcStartStopTimer.isActive()) + { + m_arcStartStopTimer.stop(); + } + { + std::lock_guard lock(m_arcRoutingStateMutex); + HdmiCecSink::_instance->m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; + } + _instance->m_semSignaltoArcRoutingThread.release(); + + // trigger callback to Device setting informing to TERMINATE_ARC + LOGINFO("Got : ARC_TERMINATED and notify Device setting"); + params["status"] = string("success"); + sendNotify(eventString[HDMICECSINK_EVENT_ARC_TERMINATION_EVENT], params); + } + + void HdmiCecSink::threadSendKeyEvent() + { + if(!HdmiCecSink::_instance) + return; + + SendKeyInfo keyInfo = {-1,-1}; + + while(!_instance->m_sendKeyEventThreadExit) + { + keyInfo.logicalAddr = -1; + keyInfo.keyCode = -1; + { + // Wait for a message to be added to the queue + std::unique_lock lk(_instance->m_sendKeyEventMutex); + _instance->m_sendKeyCV.wait(lk, []{return (_instance->m_sendKeyEventThreadRun == true);}); + } + + if (_instance->m_sendKeyEventThreadExit == true) + { + LOGINFO(" threadSendKeyEvent Exiting"); + _instance->m_sendKeyEventThreadRun = false; + break; + } + + if (_instance->m_SendKeyQueue.empty()) { + _instance->m_sendKeyEventThreadRun = false; + continue; + } + + keyInfo = _instance->m_SendKeyQueue.front(); + _instance->m_SendKeyQueue.pop(); + + if(keyInfo.UserControl == "sendUserControlPressed" ) + { + LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); + _instance->sendUserControlPressed(keyInfo.logicalAddr,keyInfo.keyCode); + } + else if(keyInfo.UserControl == "sendUserControlReleased") + { + LOGINFO("sendUserControlReleased : logical addr:0x%x queue size :%zu \n",keyInfo.logicalAddr,_instance->m_SendKeyQueue.size()); + _instance->sendUserControlReleased(keyInfo.logicalAddr); + } + else + { + LOGINFO("sendKeyPressEvent : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); + _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); + _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); + } + + if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) + { + if(keyInfo.keyCode == MUTE) + { + _instance->sendGiveAudioStatusMsg(); + } + else + { + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); + if (!_instance->m_isAudioStatusInfoUpdated) + { + if ( !(_instance->m_audioStatusDetectionTimer.isActive())) + { + LOGINFO("Audio status info not updated. Starting the Timer!"); + _instance->m_audioStatusTimerStarted = true; + _instance->m_audioStatusDetectionTimer.start((HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS)); + } + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", _instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); + } + else + { + if (!_instance->m_audioStatusReceived){ + _instance->sendGiveAudioStatusMsg(); + } + } + } + } + + }//while(!_instance->m_sendKeyEventThreadExit) + }//threadSendKeyEvent + + void HdmiCecSink::audioStatusTimerFunction() + { + m_audioStatusTimerStarted = false; + m_isAudioStatusInfoUpdated = true; + LOGINFO("Timer Expired. Requesting the AudioStatus since not received.\n"); + sendGiveAudioStatusMsg(); + LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); + } + + void HdmiCecSink::threadArcRouting() + { + bool isExit = false; + uint32_t currentArcRoutingState; + + if(!HdmiCecSink::_instance) + return; + + LOGINFO("Running threadArcRouting"); + _instance->getHdmiArcPortID(); + + while(1) + { + + _instance->m_semSignaltoArcRoutingThread.acquire(); + + + + { + LOGINFO(" threadArcRouting Got semaphore"); + std::lock_guard lock(_instance->m_arcRoutingStateMutex); + + currentArcRoutingState = _instance->m_currentArcRoutingState; + + LOGINFO(" threadArcRouting Got Sem arc state %d",currentArcRoutingState); + } + + switch (currentArcRoutingState) + { + + case ARC_STATE_REQUEST_ARC_INITIATION : + { + + _instance->systemAudioModeRequest(); + _instance->Send_Request_Arc_Initiation_Message(); + + } + break; + case ARC_STATE_ARC_INITIATED : + { + _instance->Send_Report_Arc_Initiated_Message(); + } + break; + case ARC_STATE_REQUEST_ARC_TERMINATION : + { + + _instance->Send_Request_Arc_Termination_Message(); + + } + break; + case ARC_STATE_ARC_TERMINATED : + { + _instance->Send_Report_Arc_Terminated_Message(); + } + break; + case ARC_STATE_ARC_EXIT : + { + isExit = true; + } + break; + } + + if (isExit == true) + { + LOGINFO(" threadArcRouting EXITing"); + break; + } + }//while(1) + }//threadArcRouting + + void HdmiCecSink::Send_Request_Arc_Initiation_Message() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + LOGINFO(" Send_Request_Arc_Initiation_Message "); + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcInitiation()), 1000); + + } + void HdmiCecSink::Send_Report_Arc_Initiated_Message() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcInitiation()), 1000); + + } + void HdmiCecSink::Send_Request_Arc_Termination_Message() + { + + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcTermination()), 1000); + } + + void HdmiCecSink::Send_Report_Arc_Terminated_Message() + { + if(!HdmiCecSink::_instance) + return; + if(!(_instance->smConnection)) + return; + _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcTermination()), 1000); + + } + + void HdmiCecSink::getHdmiArcPortID() + { + int err; + dsGetHDMIARCPortIdParam_t param; + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, + (void *)¶m, + sizeof(param)); + if (IARM_RESULT_SUCCESS == err) + { + LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); + HdmiArcPortID = param.portId; + } + } + + void HdmiCecSink::getCecVersion() + { + RFC_ParamData_t param = {0}; + WDMP_STATUS status = getRFCParameter((char*)"thunderapi", TR181_HDMICECSINK_CEC_VERSION, ¶m); + if(WDMP_SUCCESS == status && param.type == WDMP_STRING) { + LOGINFO("CEC Version from RFC = [%s] \n", param.value); + cecVersion = atof(param.value); + } + else { + LOGINFO("Error while fetching CEC Version from RFC "); + } + } + } // namespace Plugin } // namespace WPEFrameworklk diff --git a/HdmiCecSink/HdmiCecSink.h b/HdmiCecSink/HdmiCecSink.h index e0f61176..418fb134 100644 --- a/HdmiCecSink/HdmiCecSink.h +++ b/HdmiCecSink/HdmiCecSink.h @@ -20,27 +20,456 @@ #pragma once #include -#include -#include +#include "ccec/FrameListener.hpp" +#include "ccec/Connection.hpp" -#include +#include "libIARM.h" +#include "ccec/Assert.hpp" +#include "ccec/Messages.hpp" +#include "ccec/MessageDecoder.hpp" +#include "ccec/MessageProcessor.hpp" #undef Assert // this define from Connection.hpp conflicts with WPEFramework #include "Module.h" +#include "tptimer.h" +#include +#include +#include +#include -#include "UtilsBIT.h" -#include "UtilsThreadRAII.h" - -#include -#include -#include +#include "UtilsLogging.h" +#include +#include "PowerManagerInterface.h" using namespace WPEFramework; +using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; +using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; + namespace WPEFramework { namespace Plugin { + class HdmiCecSinkFrameListener : public FrameListener + { + public: + HdmiCecSinkFrameListener(MessageProcessor &processor) : processor(processor) {} + void notify(const CECFrame &in) const; + ~HdmiCecSinkFrameListener() {} + private: + MessageProcessor &processor; + }; + + class HdmiCecSinkProcessor : public MessageProcessor + { + public: + HdmiCecSinkProcessor(Connection &conn) : conn(conn) {} + void process (const ActiveSource &msg, const Header &header); + void process (const InActiveSource &msg, const Header &header); + void process (const ImageViewOn &msg, const Header &header); + void process (const TextViewOn &msg, const Header &header); + void process (const RequestActiveSource &msg, const Header &header); + void process (const Standby &msg, const Header &header); + void process (const GetCECVersion &msg, const Header &header); + void process (const CECVersion &msg, const Header &header); + void process (const SetMenuLanguage &msg, const Header &header); + void process (const GiveOSDName &msg, const Header &header); + void process (const GivePhysicalAddress &msg, const Header &header); + void process (const GiveDeviceVendorID &msg, const Header &header); + void process (const SetOSDString &msg, const Header &header); + void process (const SetOSDName &msg, const Header &header); + void process (const RoutingChange &msg, const Header &header); + void process (const RoutingInformation &msg, const Header &header); + void process (const SetStreamPath &msg, const Header &header); + void process (const GetMenuLanguage &msg, const Header &header); + void process (const ReportPhysicalAddress &msg, const Header &header); + void process (const DeviceVendorID &msg, const Header &header); + void process (const GiveDevicePowerStatus &msg, const Header &header); + void process (const ReportPowerStatus &msg, const Header &header); + void process (const FeatureAbort &msg, const Header &header); + void process (const Abort &msg, const Header &header); + void process (const Polling &msg, const Header &header); + void process (const InitiateArc &msg, const Header &header); + void process (const TerminateArc &msg, const Header &header); + void process (const ReportShortAudioDescriptor &msg, const Header &header); + void process (const SetSystemAudioMode &msg, const Header &header); + void process (const ReportAudioStatus &msg, const Header &header); + void process (const GiveFeatures &msg, const Header &header); + void process (const RequestCurrentLatency &msg, const Header &header); + private: + Connection conn; + void printHeader(const Header &header) + { + printf("Header : From : %s \n", header.from.toString().c_str()); + printf("Header : to : %s \n", header.to.toString().c_str()); + } + + }; + + class CECDeviceParams { + public: + + enum { + REQUEST_NONE = 0, + REQUEST_PHISICAL_ADDRESS = 1, + REQUEST_CEC_VERSION, + REQUEST_DEVICE_VENDOR_ID, + REQUEST_POWER_STATUS, + REQUEST_OSD_NAME, + }; + + enum { + REQUEST_DONE = 0, + REQUEST_NOT_DONE, + REQUEST_TIME_ELAPSED, + }; + + DeviceType m_deviceType; + LogicalAddress m_logicalAddress; + PhysicalAddress m_physicalAddr; + Version m_cecVersion; + VendorID m_vendorID; + OSDName m_osdName; + PowerStatus m_powerStatus; + bool m_isDevicePresent; + bool m_isDeviceDisconnected; + Language m_currentLanguage; + bool m_isActiveSource; + bool m_isDeviceTypeUpdated; + bool m_isPAUpdated; + bool m_isVersionUpdated; + bool m_isOSDNameUpdated; + bool m_isVendorIDUpdated; + bool m_isPowerStatusUpdated; + int m_isRequested; + int m_isRequestRetry; + std::chrono::system_clock::time_point m_requestTime; + std::vector m_featureAborts; + std::chrono::system_clock::time_point m_lastPowerUpdateTime; + + CECDeviceParams() + : m_deviceType(0), m_logicalAddress(0),m_physicalAddr(0x0f,0x0f,0x0f,0x0f),m_cecVersion(0),m_vendorID(0,0,0),m_osdName(""),m_powerStatus(0),m_currentLanguage("") + { + m_isDevicePresent = false; + m_isActiveSource = false; + m_isPAUpdated = false; + m_isVersionUpdated = false; + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + m_isPowerStatusUpdated = false; + m_isDeviceDisconnected = false; + m_isDeviceTypeUpdated = false; + m_isRequestRetry = 0; + } + + void clear( ) + { + m_deviceType = 0; + m_logicalAddress = 0; + m_physicalAddr = PhysicalAddress(0x0f,0x0f,0x0f,0x0f); + m_cecVersion = 0; + m_vendorID = VendorID(0,0,0); + m_osdName = ""; + m_powerStatus = 0; + m_currentLanguage = ""; + m_isDevicePresent = false; + m_isActiveSource = false; + m_isPAUpdated = false; + m_isVersionUpdated = false; + m_isOSDNameUpdated = false; + m_isVendorIDUpdated = false; + m_isPowerStatusUpdated = false; + m_isDeviceDisconnected = false; + m_isDeviceTypeUpdated = false; + } + + void printVariable() + { + LOGWARN("Device LogicalAddress %s", m_logicalAddress.toString().c_str()); + LOGWARN("Device Type %s", m_deviceType.toString().c_str()); + LOGWARN("Device Present %d", m_isDevicePresent); + LOGWARN("Active Source %d", m_isActiveSource); + LOGWARN("PA Updated %d", m_isPAUpdated); + LOGWARN("Version Updated %d", m_isVersionUpdated); + LOGWARN("OSDName Updated %d", m_isOSDNameUpdated); + LOGWARN("PowerStatus Updated %d", m_isPowerStatusUpdated); + LOGWARN("VendorID Updated %d", m_isPowerStatusUpdated); + LOGWARN("CEC Version : %s", m_cecVersion.toString().c_str()); + LOGWARN("Vendor ID : %s", m_vendorID.toString().c_str()); + LOGWARN("PhisicalAddress : %s", m_physicalAddr.toString().c_str()); + LOGWARN("OSDName : %s", m_osdName.toString().c_str()); + LOGWARN("Power Status : %s", m_powerStatus.toString().c_str()); + LOGWARN("Language : %s", m_currentLanguage.toString().c_str()); + } + + bool isAllUpdated() { + if( !m_isPAUpdated + || !m_isVersionUpdated + || !m_isOSDNameUpdated + || !m_isVendorIDUpdated + || !m_isPowerStatusUpdated + || !m_isDeviceTypeUpdated ){ + return false; + } + return true; + } + + void update( const DeviceType &deviceType ) { + m_deviceType = deviceType; + m_isDeviceTypeUpdated = true; + } + + void update( const PhysicalAddress &physical_addr ) { + m_physicalAddr = physical_addr; + m_isPAUpdated = true; + } + + void update ( const VendorID &vendorId) { + m_vendorID = vendorId; + m_isVendorIDUpdated = true; + } + + void update ( const Version &version ) { + m_cecVersion = version; + m_isVersionUpdated = true; + } + + void update ( const OSDName &osdName ) { + m_osdName = osdName; + m_isOSDNameUpdated = true; + } + + void update ( const PowerStatus &status ) { + m_powerStatus = status; + m_isPowerStatusUpdated = true; + m_lastPowerUpdateTime = std::chrono::system_clock::now(); + } + }; + + class DeviceNode { + public: + uint8_t m_childsLogicalAddr[LogicalAddress::UNREGISTERED]; + + DeviceNode() { + int i; + for (i = 0; i < LogicalAddress::UNREGISTERED; i++ ) + { + m_childsLogicalAddr[i] = LogicalAddress::UNREGISTERED; + } + } + + } ; + typedef struct sendKeyInfo + { + int logicalAddr; + int keyCode; + string UserControl; + }SendKeyInfo; + + class HdmiPortMap { + public: + uint8_t m_portID; + bool m_isConnected; + LogicalAddress m_logicalAddr; + PhysicalAddress m_physicalAddr; + DeviceNode m_deviceChain[3]; + + HdmiPortMap(uint8_t portID) : m_portID(portID), + m_logicalAddr(LogicalAddress::UNREGISTERED), + m_physicalAddr(portID+1,0,0,0) + { + m_isConnected = false; + } + + void update(bool isConnected) + { + m_isConnected = isConnected; + } + + void update( const LogicalAddress &addr ) + { + m_logicalAddr = addr; + } + + void addChild( const LogicalAddress &logical_addr, const PhysicalAddress &physical_addr ) + { + LOGINFO(" logicalAddr = %d, phisicalAddr = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); + + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED && + m_logicalAddr.toInt() != logical_addr.toInt() ) + { + LOGINFO(" update own logicalAddr = %d, new devcie logicalAddress = %d", m_logicalAddr.toInt(), logical_addr.toInt() ); + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = logical_addr.toInt(); + } + else if ( physical_addr.getByteValue(2) != 0 ) + { + m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = logical_addr.toInt(); + } + else if ( physical_addr.getByteValue(1) != 0 ) + { + m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = logical_addr.toInt(); + } + } + } + else if ( physical_addr == m_physicalAddr ) + { + update(logical_addr); + LOGINFO(" update own logicalAddr = %d", m_logicalAddr.toInt()); + } + } + + void removeChild( PhysicalAddress &physical_addr ) + { + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) + { + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = LogicalAddress::UNREGISTERED; + } + else if ( physical_addr.getByteValue(2) != 0 ) + { + m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = LogicalAddress::UNREGISTERED; + } + else if ( physical_addr.getByteValue(1) != 0 ) + { + m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = LogicalAddress::UNREGISTERED; + } + } + } + } + + void getRoute( PhysicalAddress &physical_addr, std::vector & route ) + { + LOGINFO(" logicalAddr = %d, phsical = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); + + if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) + { + LOGINFO(" search for logicalAddr = %d", m_logicalAddr.toInt()); + /* check matching with this port's physical address */ + if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && + physical_addr.getByteValue(1) != 0 ) + { + if ( physical_addr.getByteValue(3) != 0 ) + { + route.push_back(m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1]); + } + + if ( physical_addr.getByteValue(2) != 0 ) + { + route.push_back(m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1]); + } + + if ( physical_addr.getByteValue(1) != 0 ) + { + route.push_back(m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1]); + } + + route.push_back(m_logicalAddr.toInt()); + } + else + { + route.push_back(m_logicalAddr.toInt()); + LOGINFO("logicalAddr = %d, physical = %s", m_logicalAddr.toInt(), m_physicalAddr.toString().c_str()); + } + } + } + }; + + class binary_semaphore { + + public: + + explicit binary_semaphore(int init_count = count_max) + + : count_(init_count) {} + + + + // P-operation / acquire + + void wait() + + { + + std::unique_lock lk(m_); + + cv_.wait(lk, [=]{ return 0 < count_; }); + + --count_; + + } + + bool try_wait() + + { + + std::lock_guard lk(m_); + + if (0 < count_) { + + --count_; + + return true; + + } else { + + return false; + + } + + } + + // V-operation / release + + void signal() + + { + + std::lock_guard lk(m_); + + if (count_ < count_max) { + + ++count_; + + cv_.notify_one(); + + } + + } + + + + // Lockable requirements + + void acquire() { wait(); } + + bool try_lock() { return try_wait(); } + + void release() { signal(); } + + + +private: + + static const int count_max = 1; + + int count_; + + std::mutex m_; + + std::condition_variable cv_; + +}; // This is a server for a JSONRPC communication channel. // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. @@ -55,211 +484,262 @@ namespace WPEFramework { // will receive a JSONRPC message as a notification, in case this method is called. class HdmiCecSink : public PluginHost::IPlugin, public PluginHost::JSONRPC { + enum { + POLL_THREAD_STATE_NONE, + POLL_THREAD_STATE_IDLE, + POLL_THREAD_STATE_POLL, + POLL_THREAD_STATE_PING, + POLL_THREAD_STATE_INFO, + POLL_THREAD_STATE_WAIT, + POLL_THREAD_STATE_CLEAN, + POLL_THREAD_STATE_UPDATE, + POLL_THREAD_STATE_EXIT, + }; + enum { + ARC_STATE_REQUEST_ARC_INITIATION, + ARC_STATE_ARC_INITIATED, + ARC_STATE_REQUEST_ARC_TERMINATION, + ARC_STATE_ARC_TERMINATED, + ARC_STATE_ARC_EXIT + }; + enum { + VOLUME_UP = 0x41, + VOLUME_DOWN = 0x42, + MUTE = 0x43, + UP = 0x01, + DOWN = 0x02, + LEFT = 0x03, + RIGHT = 0x04, + SELECT = 0x00, + HOME = 0x09, + BACK = 0x0D, + NUMBER_0 = 0x20, + NUMBER_1 = 0x21, + NUMBER_2 = 0x22, + NUMBER_3 = 0x23, + NUMBER_4 = 0x24, + NUMBER_5 = 0x25, + NUMBER_6 = 0x26, + NUMBER_7 = 0x27, + NUMBER_8 = 0x28, + NUMBER_9 = 0x29 + }; + public: + HdmiCecSink(); + virtual ~HdmiCecSink(); + virtual const string Initialize(PluginHost::IShell* shell) override; + virtual void Deinitialize(PluginHost::IShell* service) override; + virtual string Information() const override { return {}; } + static HdmiCecSink* _instance; + CECDeviceParams deviceList[16]; + std::vector hdmiInputs; + int m_currentActiveSource; + void updateInActiveSource(const int logical_address, const InActiveSource &source ); + void updateActiveSource(const int logical_address, const ActiveSource &source ); + void updateTextViewOn(const int logicalAddress); + void updateImageViewOn(const int logicalAddress); + void updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr); + void getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route); + void removeDevice(const int logicalAddress); + void addDevice(const int logicalAddress); + void printDeviceList(); + void setStreamPath( const PhysicalAddress &physical_addr); + void setRoutingChange(const std::string &from, const std::string &to); + void sendStandbyMessage(); + void setCurrentLanguage(const Language &lang); + void sendMenuLanguage(); + void setActiveSource(bool isResponse); + void requestActiveSource(); + void startArc(); + void stopArc(); + void Process_InitiateArc(); + void Process_TerminateArc(); + void updateArcState(); + void requestShortaudioDescriptor(); + void Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor); + void Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg); + void Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg); + void sendDeviceUpdateInfo(const int logicalAddress); + void sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); + void reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); + void systemAudioModeRequest(); + void SendStandbyMsgEvent(const int logicalAddress); + void requestAudioDevicePowerStatus(); + void reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus); + void updateCurrentLatency(int videoLatency, bool lowLatencyMode, int audioOutputCompensated, int audioOutputDelay); + void setLatencyInfo(); + void Process_ReportAudioStatus_msg(const ReportAudioStatus msg); + void sendKeyPressEvent(const int logicalAddress, int keyCode); + void sendKeyReleaseEvent(const int logicalAddress); + void sendUserControlPressed(const int logicalAddress, int keyCode); + void sendUserControlReleased(const int logicalAddress); + void onPowerModeChanged(const PowerState currentState, const PowerState newState); + void registerEventHandlers(); + void sendGiveAudioStatusMsg(); + void getHdmiArcPortID(); + int m_numberOfDevices; /* Number of connected devices othethan own device */ + bool m_audioDevicePowerStatusRequested; + + BEGIN_INTERFACE_MAP(HdmiCecSink) + INTERFACE_ENTRY(PluginHost::IPlugin) + INTERFACE_ENTRY(PluginHost::IDispatcher) + END_INTERFACE_MAP + + private: + class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { private: - class Notification : public RPC::IRemoteConnection::INotification, - public Exchange::IHdmiCecSink::INotification - { - private: - Notification() = delete; - Notification(const Notification&) = delete; - Notification& operator=(const Notification&) = delete; - - public: - explicit Notification(HdmiCecSink* parent) - : _parent(*parent) - { - ASSERT(parent != nullptr); - } - - virtual ~Notification() - { - } - - BEGIN_INTERFACE_MAP(Notification) - INTERFACE_ENTRY(Exchange::IHdmiCecSink::INotification) - INTERFACE_ENTRY(RPC::IRemoteConnection::INotification) - END_INTERFACE_MAP - - void Activated(RPC::IRemoteConnection*) override - { - } - - void Deactivated(RPC::IRemoteConnection *connection) override - { - _parent.Deactivated(connection); - } - - void ArcInitiationEvent(const string success) override - { - LOGINFO("ArcInitiationEvent"); - LOGINFO("success: %s", success.c_str()); - Exchange::JHdmiCecSink::Event::ArcInitiationEvent(_parent, success); - } - - void ArcTerminationEvent(const string success) override - { - LOGINFO("ArcTerminationEvent"); - LOGINFO("success: %s", success.c_str()); - Exchange::JHdmiCecSink::Event::ArcTerminationEvent(_parent, success); - } - - void OnActiveSourceChange(const int logicalAddress, const string physicalAddress) override - { - LOGINFO("OnActiveSourceChange"); - LOGINFO("logicalAddress: %d, physicalAddress: %s", logicalAddress, physicalAddress.c_str()); - Exchange::JHdmiCecSink::Event::OnActiveSourceChange(_parent, logicalAddress, physicalAddress); - } - - void OnDeviceAdded(const int logicalAddress) override - { - LOGINFO("OnDeviceAdded"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnDeviceAdded(_parent, logicalAddress); - } - - void OnDeviceInfoUpdated(const int logicalAddress) override - { - LOGINFO("OnDeviceInfoUpdated"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnDeviceInfoUpdated(_parent, logicalAddress); - } - - void OnDeviceRemoved(const int logicalAddress) override - { - LOGINFO("OnDeviceRemoved"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnDeviceRemoved(_parent, logicalAddress); - } - - void OnImageViewOnMsg(const int logicalAddress) override - { - LOGINFO("OnImageViewOnMsg"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnImageViewOnMsg(_parent, logicalAddress); - } - - void OnInActiveSource(const int logicalAddress, const string physicalAddress) override - { - LOGINFO("OnInActiveSource"); - LOGINFO("logicalAddress: %d, physicalAddress: %s", logicalAddress, physicalAddress.c_str()); - Exchange::JHdmiCecSink::Event::OnInActiveSource(_parent, logicalAddress, physicalAddress); - } - - void OnTextViewOnMsg(const int logicalAddress) override - { - LOGINFO("OnTextViewOnMsg"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnTextViewOnMsg(_parent, logicalAddress); - } - - void OnWakeupFromStandby(const int logicalAddress) override - { - LOGINFO("OnWakeupFromStandby"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::OnWakeupFromStandby(_parent, logicalAddress); - } - - void ReportAudioDeviceConnectedStatus(const string status, const string audioDeviceConnected) override - { - LOGINFO("ReportAudioDeviceConnectedStatus"); - LOGINFO("status: %s, audioDeviceConnected: %s", status.c_str(), audioDeviceConnected.c_str()); - Exchange::JHdmiCecSink::Event::ReportAudioDeviceConnectedStatus(_parent, status, audioDeviceConnected); - } - - void ReportAudioStatusEvent(const int muteStatus, const int volumeLevel) override - { - LOGINFO("ReportAudioStatusEvent"); - LOGINFO("muteStatus: %d, volumeLevel: %d", muteStatus, volumeLevel); - Exchange::JHdmiCecSink::Event::ReportAudioStatusEvent(_parent, muteStatus, volumeLevel); - } - - void ReportFeatureAbortEvent(const int logicalAddress, const int opcode, const int FeatureAbortReason) override - { - LOGINFO("ReportFeatureAbortEvent"); - LOGINFO("logicalAddress: %d, opcode: %d, FeatureAbortReason: %d", logicalAddress, opcode, FeatureAbortReason); - Exchange::JHdmiCecSink::Event::ReportFeatureAbortEvent(_parent, logicalAddress, opcode, FeatureAbortReason); - } - - void ReportCecEnabledEvent(const string cecEnable) override - { - LOGINFO("ReportCecEnabledEvent"); - LOGINFO("cecEnable: %s", cecEnable.c_str()); - Exchange::JHdmiCecSink::Event::ReportCecEnabledEvent(_parent, cecEnable); - } - - void SetSystemAudioModeEvent(const string audioMode) override - { - LOGINFO("SetSystemAudioModeEvent"); - LOGINFO("audioMode: %s", audioMode.c_str()); - Exchange::JHdmiCecSink::Event::SetSystemAudioModeEvent(_parent, audioMode); - } - - void ShortAudiodescriptorEvent(const string& jsonresponse) override - { - LOGINFO("ShortAudiodescriptorEvent"); - Exchange::JHdmiCecSink::Event::ShortAudiodescriptorEvent(_parent, jsonresponse); - } - - void StandbyMessageReceived(const int logicalAddress) override - { - LOGINFO("StandbyMessageReceived"); - LOGINFO("logicalAddress: %d", logicalAddress); - Exchange::JHdmiCecSink::Event::StandbyMessageReceived(_parent, logicalAddress); - } - - void ReportAudioDevicePowerStatus(const int powerStatus) override - { - LOGINFO("ReportAudioDevicePowerStatus"); - LOGINFO("powerStatus: %d", powerStatus); - Exchange::JHdmiCecSink::Event::ReportAudioDevicePowerStatus(_parent, powerStatus); - } - - private: - HdmiCecSink &_parent; - - }; + PowerManagerNotification(const PowerManagerNotification&) = delete; + PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; public: - // We do not allow this plugin to be copied !! - HdmiCecSink(const HdmiCecSink&) = delete; - HdmiCecSink& operator=(const HdmiCecSink&) = delete; - - HdmiCecSink() - : PluginHost::IPlugin() - , PluginHost::JSONRPC() - , _service(nullptr) - , _notification(this) - , _hdmiCecSink(nullptr) - , _connectionId(0) + explicit PowerManagerNotification(HdmiCecSink& parent) + : _parent(parent) { - } - virtual ~HdmiCecSink() - { + ~PowerManagerNotification() override = default; + public: + void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override + { + _parent.onPowerModeChanged(currentState, newState); } - BEGIN_INTERFACE_MAP(HdmiCecSink) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - INTERFACE_AGGREGATE(Exchange::IHdmiCecSink, _hdmiCecSink) + template + T* baseInterface() + { + static_assert(std::is_base_of(), "base type mismatch"); + return static_cast(this); + } + + BEGIN_INTERFACE_MAP(PowerManagerNotification) + INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) END_INTERFACE_MAP - // IPlugin methods - // ------------------------------------------------------------------------------------------------------- - const string Initialize(PluginHost::IShell* service) override; - void Deinitialize(PluginHost::IShell* service) override; - string Information() const override; - //Begin methods - - private: - void Deactivated(RPC::IRemoteConnection* connection); - private: - PluginHost::IShell* _service{}; - Core::Sink _notification; - Exchange::IHdmiCecSink* _hdmiCecSink; - uint32_t _connectionId; + HdmiCecSink& _parent; + }; + // We do not allow this plugin to be copied !! + HdmiCecSink(const HdmiCecSink&) = delete; + HdmiCecSink& operator=(const HdmiCecSink&) = delete; + + //Begin methods + uint32_t setEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getEnabledWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setOSDNameWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getOSDNameWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setVendorIdWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getVendorIdWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t printDeviceListWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setActivePathWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setRoutingChangeWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getDeviceListWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getActiveRouteWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t requestActiveSourceWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setArcEnableDisableWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setMenuLanguageWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t requestShortAudioDescriptorWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendStandbyMessageWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendAudioDevicePowerOnMsgWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendRemoteKeyPressWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendUserControlPressedWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendUserControlReleasedWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t sendGiveAudioStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t getAudioDeviceConnectedStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t requestAudioDevicePowerStatusWrapper(const JsonObject& parameters, JsonObject& response); + uint32_t setLatencyInfoWrapper(const JsonObject& parameters, JsonObject& response); + void InitializePowerManager(PluginHost::IShell *service); + //End methods + std::string logicalAddressDeviceType; + bool cecSettingEnabled; + bool cecOTPSettingEnabled; + bool cecEnableStatus; + bool hdmiCecAudioDeviceConnected; + bool m_isHdmiInConnected; + int m_numofHdmiInput; + uint8_t m_deviceType; + int m_logicalAddressAllocated; + std::thread m_pollThread; + uint32_t m_pollThreadState; + uint32_t m_pollNextState; + bool m_pollThreadExit; + uint32_t m_sleepTime; + std::mutex m_pollExitMutex; + std::mutex m_enableMutex; + /* Send Key event related */ + bool m_sendKeyEventThreadExit; + bool m_sendKeyEventThreadRun; + bool m_isAudioStatusInfoUpdated; + bool m_audioStatusReceived; + bool m_audioStatusTimerStarted; + std::thread m_sendKeyEventThread; + std::mutex m_sendKeyEventMutex; + std::queue m_SendKeyQueue; + std::condition_variable m_sendKeyCV; + std::condition_variable m_ThreadExitCV; + + /* DALS - Latency Values */ + uint8_t m_video_latency; + uint8_t m_latency_flags; + uint8_t m_audio_output_delay; + + /* ARC related */ + std::thread m_arcRoutingThread; + uint32_t m_currentArcRoutingState; + std::mutex m_arcRoutingStateMutex; + binary_semaphore m_semSignaltoArcRoutingThread; + bool m_arcstarting; + TpTimer m_arcStartStopTimer; + TpTimer m_audioStatusDetectionTimer; + + Connection *smConnection; + std::vector m_connectedDevices; + HdmiCecSinkProcessor *msgProcessor; + HdmiCecSinkFrameListener *msgFrameListener; + PowerManagerInterfaceRef _powerManagerPlugin; + Core::Sink _pwrMgrNotification; + bool _registeredEventHandlers; + const void InitializeIARM(); + void DeinitializeIARM(); + void allocateLogicalAddress(int deviceType); + void allocateLAforTV(); + void pingDevices(std::vector &connected , std::vector &disconnected); + void CheckHdmiInState(); + void request(const int logicalAddress); + int requestType(const int logicalAddress); + int requestStatus(const int logicalAddress); + static void threadRun(); + void cecMonitoringThread(); + static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); + void onHdmiHotPlug(int portId, int connectStatus); + bool loadSettings(); + void persistSettings(bool enableStatus); + void persistOTPSettings(bool enableStatus); + void persistOSDName(const char *name); + void persistVendorId(unsigned int vendorID); + void setEnabled(bool enabled); + bool getEnabled(); + bool getAudioDeviceConnectedStatus(); + void CECEnable(void); + void CECDisable(void); + void getPhysicalAddress(); + void getLogicalAddress(); + void cecAddressesChanged(int changeStatus); + + // Arc functions + + static void threadSendKeyEvent(); + static void threadArcRouting(); + void requestArcInitiation(); + void requestArcTermination(); + void Send_Request_Arc_Initiation_Message(); + void Send_Report_Arc_Initiated_Message(); + void Send_Request_Arc_Termination_Message(); + void Send_Report_Arc_Terminated_Message(); + void arcStartStopTimerFunction(); + void audioStatusTimerFunction(); + void getCecVersion(); }; } // namespace Plugin } // namespace WPEFramework diff --git a/HdmiCecSink/HdmiCecSinkImplementation.cpp b/HdmiCecSink/HdmiCecSinkImplementation.cpp deleted file mode 100644 index 7363bb76..00000000 --- a/HdmiCecSink/HdmiCecSinkImplementation.cpp +++ /dev/null @@ -1,3581 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include "HdmiCecSinkImplementation.h" - -#include "ccec/Connection.hpp" -#include "ccec/CECFrame.hpp" -#include "ccec/MessageEncoder.hpp" -#include "host.hpp" -#include "UtilsgetRFCConfig.h" - -#include "dsMgr.h" -#include "dsRpc.h" -#include "dsDisplay.h" -#include "videoOutputPort.hpp" -#include "manager.hpp" -#include "websocket/URL.h" - -#include "UtilsIarm.h" -#include "UtilsJsonRpc.h" -#include "UtilssyncPersistFile.h" -#include "UtilsSearchRDKProfile.h" - -#define TEST_ADD 0 -#define HDMICECSINK_REQUEST_MAX_RETRY 3 -#define HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS 2000 -#define HDMICECSINK_PING_INTERVAL_MS 10000 -#define HDMICECSINK_WAIT_FOR_HDMI_IN_MS 1000 -#define HDMICECSINK_REQUEST_INTERVAL_TIME_MS 500 -#define HDMICECSINK_NUMBER_TV_ADDR 2 -#define HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS (60 * 1000) -#define HDMISINK_ARC_START_STOP_MAX_WAIT_MS 4000 -#define HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS 500 - - -#define SAD_FMT_CODE_AC3 2 -#define SAD_FMT_CODE_ENHANCED_AC3 10 - -#define SYSTEM_AUDIO_MODE_ON 0x01 -#define SYSTEM_AUDIO_MODE_OFF 0x00 -#define AUDIO_DEVICE_POWERSTATE_OFF 1 - -#define DEFAULT_VIDEO_LATENCY 100 -#define DEFAULT_LATENCY_FLAGS 3 -#define DEFAULT_AUDIO_OUTPUT_DELAY 100 - -//Device Type is TV - Bit 7 is set to 1 -#define ALL_DEVICE_TYPES 128 - -//RC Profile of TV is 3 - Typical TV Remote -#define RC_PROFILE_TV 10 - -//Device Features supported by TV - ARC Tx -#define DEVICE_FEATURES_TV 4 - -#define TR181_HDMICECSINK_CEC_VERSION "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.HdmiCecSink.CECVersion" - - -#define CEC_SETTING_ENABLED_FILE "/opt/persistent/ds/cecData_2.json" -#define CEC_SETTING_OTP_ENABLED "cecOTPEnabled" -#define CEC_SETTING_ENABLED "cecEnabled" -#define CEC_SETTING_OSD_NAME "cecOSDName" -#define CEC_SETTING_VENDOR_ID "cecVendorId" - -enum { - DEVICE_POWER_STATE_ON = 0, - DEVICE_POWER_STATE_OFF = 1 -}; - -static std::vector defaultVendorId = {0x00,0x19,0xFB}; -static VendorID appVendorId = {defaultVendorId.at(0),defaultVendorId.at(1),defaultVendorId.at(2)}; -static VendorID lgVendorId = {0x00,0xE0,0x91}; -static PhysicalAddress physical_addr = {0x0F,0x0F,0x0F,0x0F}; -static LogicalAddress logicalAddress = 0xF; -static Language defaultLanguage = "eng"; -static OSDName osdName = "TV Box"; -static int32_t powerState = DEVICE_POWER_STATE_OFF; -static std::vector formatid = {0,0}; -static std::vector audioFormatCode = { SAD_FMT_CODE_ENHANCED_AC3,SAD_FMT_CODE_AC3 }; -static uint8_t numberofdescriptor = 2; -static int32_t HdmiArcPortID = -1; -static float cecVersion = 1.4; -static AllDeviceTypes allDevicetype = ALL_DEVICE_TYPES; -static std::vector rcProfile = {RC_PROFILE_TV}; -static std::vector deviceFeatures = {DEVICE_FEATURES_TV}; - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 3 -#define API_VERSION_NUMBER_PATCH 7 - -using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; - -namespace WPEFramework -{ - - namespace Plugin - { - SERVICE_REGISTRATION(HdmiCecSinkImplementation, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - HdmiCecSinkImplementation* HdmiCecSinkImplementation::_instance = nullptr; - static int libcecInitStatus = 0; - -//=========================================== HdmiCecSinkFrameListener ========================================= - void HdmiCecSinkFrameListener::notify(const CECFrame &in) const { - const uint8_t *buf = NULL; - char strBuffer[512] = {0}; - size_t len = 0; - - in.getBuffer(&buf, &len); - for (unsigned int i = 0; i < len; i++) { - snprintf(strBuffer + (i*3) , sizeof(strBuffer) - (i*3), "%02X ",(uint8_t) *(buf + i)); - } - LOGINFO(" >>>>> Received CEC Frame: :%s \n",strBuffer); - - MessageDecoder(processor).decode(in); - } - -//=========================================== HdmiCecSinkProcessor ========================================= - void HdmiCecSinkProcessor::process (const ActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->updateActiveSource(header.from.toInt(), msg); - } - void HdmiCecSinkProcessor::process (const InActiveSource &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: InActiveSource %s : %s : %s \n",GetOpName(msg.opCode()),msg.physicalAddress.name().c_str(),msg.physicalAddress.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - HdmiCecSinkImplementation::_instance->updateInActiveSource(header.from.toInt(), msg); - } - - void HdmiCecSinkProcessor::process (const ImageViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ImageViewOn from %s\n", header.from.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->updateImageViewOn(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const TextViewOn &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: TextViewOn\n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->updateTextViewOn(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const RequestActiveSourceMessage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RequestActiveSource\n"); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - HdmiCecSinkImplementation::_instance->setActiveSource(true); - } - void HdmiCecSinkProcessor::process (const Standby &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Standby from %s\n", header.from.toString().c_str()); - HdmiCecSinkImplementation::_instance->SendStandbyMsgEvent(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const GetCECVersion &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetCECVersion sending CECVersion response \n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - if(cecVersion == 2.0) { - conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_2_0))); - } - else{ - conn.sendToAsync(header.from, MessageEncoder().encode(CECVersion(Version::V_1_4))); - } - } - catch(...) - { - LOGWARN("Exception while sending CECVersion "); - } - } - void HdmiCecSinkProcessor::process (const CECVersion &msg, const Header &header) - { - bool updateStatus; - printHeader(header); - LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); - - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isVersionUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.version); - if(!updateStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const SetMenuLanguageMessage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const GiveOSDName &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveOSDName sending SetOSDName : %s\n",osdName.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - conn.sendToAsync(header.from, MessageEncoder().encode(SetOSDName(osdName))); - } - catch(...) - { - LOGWARN("Exception while sending SetOSDName"); - } - } - void HdmiCecSinkProcessor::process (const GivePhysicalAddress &msg, const Header &header) - { - LOGINFO("Command: GivePhysicalAddress\n"); - if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) - { - try - { - LOGINFO(" sending ReportPhysicalAddress response physical_addr :%s logicalAddress :%x \n",physical_addr.toString().c_str(), logicalAddress.toInt()); - conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(physical_addr,logicalAddress.toInt())), 500); - } - catch(...) - { - LOGWARN("Exception while sending ReportPhysicalAddress "); - } - } - } - void HdmiCecSinkProcessor::process (const GiveDeviceVendorID &msg, const Header &header) - { - printHeader(header); - if(header.to == LogicalAddress(LogicalAddress::BROADCAST)){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n",appVendorId.toString().c_str()); - conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(appVendorId))); - } - catch(...) - { - LOGWARN("Exception while sending DeviceVendorID"); - } - - } - void HdmiCecSinkProcessor::process (const SetOSDString &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetOSDString OSDString : %s\n",msg.osdString.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const SetOSDName &msg, const Header &header) - { - printHeader(header); - bool updateStatus ; - LOGINFO("Command: SetOSDName OSDName : %s\n",msg.osdName.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isOSDNameUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.osdName); - if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_OSD_NAME) { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; - } - if(!updateStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const RoutingChange &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingChange From : %s To: %s \n",msg.from.toString().c_str(),msg.to.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const RoutingInformation &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: RoutingInformation Routing Information to Sink : %s\n",msg.toSink.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const SetStreamPath &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetStreamPath Set Stream Path to Sink : %s\n",msg.toSink.toString().c_str()); - } - void HdmiCecSinkProcessor::process (const GetMenuLanguage &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GetMenuLanguage\n"); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->sendMenuLanguage(); - } - void HdmiCecSinkProcessor::process (const ReportPhysicalAddress &msg, const Header &header) - { - printHeader(header); - bool updateDeviceTypeStatus; - bool updatePAStatus; - LOGINFO("Command: ReportPhysicalAddress\n"); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - return; - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateDeviceTypeStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isDeviceTypeUpdated; - updatePAStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isPAUpdated; - LOGINFO("updateDeviceTypeStatus %d updatePAStatus %d \n",updateDeviceTypeStatus,updatePAStatus); - if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString() != msg.physicalAddress.toString() && updatePAStatus){ - updatePAStatus= false; - LOGINFO("There is a change in physical address from current PA %s to newly reported PA %s\n",HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_physicalAddr.toString().c_str(),msg.physicalAddress.toString().c_str()); - } - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.physicalAddress); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.deviceType); - if(HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry > 0 && - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequested == CECDeviceParams::REQUEST_PHISICAL_ADDRESS) { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isRequestRetry = 0; - } - HdmiCecSinkImplementation::_instance->updateDeviceChain(header.from, msg.physicalAddress); - if (!updateDeviceTypeStatus || !updatePAStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const DeviceVendorID &msg, const Header &header) - { - bool updateStatus ; - printHeader(header); - LOGINFO("Command: DeviceVendorID VendorID : %s\n",msg.vendorId.toString().c_str()); - if(!(header.to == LogicalAddress(LogicalAddress::BROADCAST))){ - LOGINFO("Ignore Direct messages, accepts only broadcast messages"); - return; - } - - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - updateStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_isVendorIDUpdated; - LOGINFO("updateStatus %d\n",updateStatus); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.vendorId); - if (!updateStatus) - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - void HdmiCecSinkProcessor::process (const GiveDevicePowerStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveDevicePowerStatus sending powerState :%d \n",powerState); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - try - { - conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState)))); - } - catch(...) - { - LOGWARN("Exception while sending ReportPowerStatus"); - } - } - void HdmiCecSinkProcessor::process (const ReportPowerStatus &msg, const Header &header) - { - uint32_t oldPowerStatus,newPowerStatus; - printHeader(header); - LOGINFO("Command: ReportPowerStatus Power Status from:%s status : %s \n",header.from.toString().c_str(),msg.status.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - oldPowerStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); - HdmiCecSinkImplementation::_instance->addDevice(header.from.toInt()); - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(msg.status); - newPowerStatus = HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_powerStatus.toInt(); - LOGINFO(" oldPowerStatus %d newpower status %d \n",oldPowerStatus,newPowerStatus); - if ((oldPowerStatus != newPowerStatus) ) - { - HdmiCecSinkImplementation::_instance->sendDeviceUpdateInfo(header.from.toInt()); - } - - if((header.from.toInt() == LogicalAddress::AUDIO_SYSTEM) && (HdmiCecSinkImplementation::_instance->m_audioDevicePowerStatusRequested)) { - HdmiCecSinkImplementation::_instance->reportAudioDevicePowerStatusInfo(header.from.toInt(), newPowerStatus); - } - - } - void HdmiCecSinkProcessor::process (const FeatureAbort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: FeatureAbort opcode=%s, Reason = %s\n", msg.feature.toString().c_str(), msg.reason.toString().c_str()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - - if(header.from.toInt() < LogicalAddress::UNREGISTERED && - msg.reason.toInt() == AbortReason::UNRECOGNIZED_OPCODE) - { - switch(msg.feature.opCode()) - { - case GET_CEC_VERSION : - { - /* If we get a Feature abort for CEC Version then default to 1.4b */ - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(Version(Version::V_1_4)); - } - break; - case GIVE_DEVICE_VENDOR_ID : - { - /* If we get a Feature abort for CEC Version then default to 1.4b */ - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(VendorID((uint8_t *)"FA", 2)); - } - break; - - case GIVE_OSD_NAME : - { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(OSDName("")); - } - break; - - case GIVE_DEVICE_POWER_STATUS : - { - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].update(PowerStatus(PowerStatus::POWER_STATUS_FEATURE_ABORT)); - } - break; - } - - HdmiCecSinkImplementation::_instance->deviceList[header.from.toInt()].m_featureAborts.push_back(msg); - } - - LogicalAddress logicaladdress = header.from.toInt(); - OpCode featureOpcode = msg.feature; - AbortReason abortReason = msg.reason; - - HdmiCecSinkImplementation::_instance->reportFeatureAbortEvent(logicaladdress,featureOpcode,abortReason); - - if(msg.feature.opCode() == REQUEST_SHORT_AUDIO_DESCRIPTOR) - { - JsonArray audiodescriptor; - audiodescriptor.Add(0); - HdmiCecSinkImplementation::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); - } - - } - void HdmiCecSinkProcessor::process (const Abort &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Abort\n"); - if (!(header.to == LogicalAddress(LogicalAddress::BROADCAST))) - { - AbortReason reason = AbortReason::UNRECOGNIZED_OPCODE; - LogicalAddress logicaladdress =header.from.toInt(); - OpCode feature = msg.opCode(); - HdmiCecSinkImplementation::_instance->sendFeatureAbort(logicaladdress, feature,reason); - } - else - { - LOGINFO("Command: Abort broadcast msg so ignore\n"); - } - } - void HdmiCecSinkProcessor::process (const Polling &msg, const Header &header) { - printHeader(header); - LOGINFO("Command: Polling\n"); - } - - void HdmiCecSinkProcessor::process (const InitiateArc &msg, const Header &header) - { - printHeader(header); - if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ - LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); - return; - } - PhysicalAddress physical_addr_invalid = {0x0F,0x0F,0x0F,0x0F}; - PhysicalAddress physical_addr_arc_port = {0x0F,0x0F,0x0F,0x0F}; - - LOGINFO("Command: INITIATE_ARC \n"); - if(!HdmiCecSinkImplementation::_instance || HdmiArcPortID == -1) - return; - - if (HdmiArcPortID == 0 ) - physical_addr_arc_port = {0x01,0x00,0x00,0x00}; - if (HdmiArcPortID == 1 ) - physical_addr_arc_port = {0x02,0x00,0x00,0x00}; - if (HdmiArcPortID == 2 ) - physical_addr_arc_port = {0x03,0x00,0x00,0x00}; - - if( (HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_arc_port.toString()) || (HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString() == physical_addr_invalid.toString()) ) { - LOGINFO("Command: INITIATE_ARC InitiateArc success %s \n",HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); - HdmiCecSinkImplementation::_instance->Process_InitiateArc(); - } else { - LOGINFO("Command: INITIATE_ARC InitiateArc ignore %s \n",HdmiCecSinkImplementation::_instance->deviceList[0x5].m_physicalAddr.toString().c_str()); - } - } - void HdmiCecSinkProcessor::process (const TerminateArc &msg, const Header &header) - { - printHeader(header); - if((!(header.from.toInt() == 0x5)) || (header.to.toInt() == LogicalAddress::BROADCAST)){ - LOGINFO("Ignoring the message coming from addresses other than 0X5 or a braodcast message"); - return; - } - if(!HdmiCecSinkImplementation::_instance) - return; - HdmiCecSinkImplementation::_instance->Process_TerminateArc(); - } - void HdmiCecSinkProcessor::process (const ReportShortAudioDescriptor &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportShortAudioDescriptor %s : %d \n",GetOpName(msg.opCode()),numberofdescriptor); - HdmiCecSinkImplementation::_instance->Process_ShortAudioDescriptor_msg(msg); - } - - void HdmiCecSinkProcessor::process (const SetSystemAudioMode &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: SetSystemAudioMode %s audio status %d audio status is %s \n",GetOpName(msg.opCode()),msg.status.toInt(),msg.status.toString().c_str()); - HdmiCecSinkImplementation::_instance->Process_SetSystemAudioMode_msg(msg); - } - void HdmiCecSinkProcessor::process (const ReportAudioStatus &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); - if(header.to.toInt() == LogicalAddress::BROADCAST){ - LOGINFO("Ignore Broadcast messages, accepts only direct messages"); - return; - } - HdmiCecSinkImplementation::_instance->Process_ReportAudioStatus_msg(msg); - } - void HdmiCecSinkProcessor::process (const GiveFeatures &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: GiveFeatures \n"); - try - { - if(cecVersion == 2.0) { - conn.sendToAsync(LogicalAddress(LogicalAddress::BROADCAST),MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures))); - } - } - catch(...) - { - LOGWARN("Exception while sending ReportFeatures"); - } - } - void HdmiCecSinkProcessor::process (const RequestCurrentLatency &msg, const Header &header) - { - printHeader(header); - LOGINFO("Command: Request Current Latency :%s, physical address: %s",GetOpName(msg.opCode()),msg.physicaladdress.toString().c_str()); - - if(msg.physicaladdress.toString() == physical_addr.toString()) { - HdmiCecSinkImplementation::_instance->setLatencyInfo(); - } - else { - LOGINFO("Physical Address does not match with TV's physical address"); - return; - } - } -//=========================================== HdmiCecSinkImplementation ========================================= - - HdmiCecSinkImplementation::HdmiCecSinkImplementation() - : _pwrMgrNotification(*this) - , _registeredEventHandlers(false) - { - LOGWARN("Initlaizing HdmiCecSinkImplementation"); - } - - HdmiCecSinkImplementation::~HdmiCecSinkImplementation() - { - if(_powerManagerPlugin) - { - _powerManagerPlugin->Unregister(_pwrMgrNotification.baseInterface()); - _powerManagerPlugin.Reset(); - } - _registeredEventHandlers = false; - - profileType = searchRdkProfile(); - - if (profileType == STB || profileType == NOT_FOUND) - { - LOGINFO("Invalid profile type for TV \n"); - return ; - } - - CECDisable(); - m_currentArcRoutingState = ARC_STATE_ARC_EXIT; - - m_semSignaltoArcRoutingThread.release(); - - try - { - if (m_arcRoutingThread.joinable()) - m_arcRoutingThread.join(); - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - { - m_sendKeyEventThreadExit = true; - std::unique_lock lk(m_sendKeyEventMutex); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - } - - try - { - if (m_sendKeyEventThread.joinable()) - m_sendKeyEventThread.join(); - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - HdmiCecSinkImplementation::_instance = nullptr; - DeinitializeIARM(); - } - - Core::hresult HdmiCecSinkImplementation::Configure(PluginHost::IShell *service) - { - InitializePowerManager(service); - profileType = searchRdkProfile(); - - HdmiCecSinkImplementation::_instance = this; - smConnection=NULL; - cecEnableStatus = false; - HdmiCecSinkImplementation::_instance->m_numberOfDevices = 0; - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - m_currentActiveSource = -1; - m_isHdmiInConnected = false; - hdmiCecAudioDeviceConnected = false; - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - m_audioDevicePowerStatusRequested = false; - m_pollNextState = POLL_THREAD_STATE_NONE; - m_pollThreadState = POLL_THREAD_STATE_NONE; - m_video_latency = DEFAULT_VIDEO_LATENCY; - m_latency_flags = DEFAULT_LATENCY_FLAGS ; - m_audio_output_delay = DEFAULT_AUDIO_OUTPUT_DELAY; - - logicalAddressDeviceType = "None"; - logicalAddress = 0xFF; - // load persistence setting - loadSettings(); - - int err; - dsHdmiInGetNumberOfInputsParam_t hdmiInput; - InitializeIARM(); - m_sendKeyEventThreadExit = false; - m_sendKeyEventThread = std::thread(threadSendKeyEvent); - - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - m_semSignaltoArcRoutingThread.acquire(); - m_arcRoutingThread = std::thread(threadArcRouting); - - m_audioStatusDetectionTimer.connect( std::bind( &HdmiCecSinkImplementation::audioStatusTimerFunction, this ) ); - m_audioStatusDetectionTimer.setSingleShot(true); - m_arcStartStopTimer.connect( std::bind( &HdmiCecSinkImplementation::arcStartStopTimerFunction, this ) ); - m_arcStartStopTimer.setSingleShot(true); - - // get power state: - uint32_t res = Core::ERROR_GENERAL; - PowerState pwrStateCur = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - PowerState pwrStatePrev = WPEFramework::Exchange::IPowerManager::POWER_STATE_UNKNOWN; - - ASSERT (_powerManagerPlugin); - if (_powerManagerPlugin) { - res = _powerManagerPlugin->GetPowerState(pwrStateCur, pwrStatePrev); - if (Core::ERROR_NONE == res) { - powerState = (pwrStateCur == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) ? DEVICE_POWER_STATE_ON : DEVICE_POWER_STATE_OFF; - LOGINFO("Current state is PowerManagerPlugin: (%d) powerState :%d \n", pwrStateCur, powerState); - } - } - - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - IARM_BUS_DSMGR_API_dsHdmiInGetNumberOfInputs, - (void *)&hdmiInput, - sizeof(hdmiInput)); - - if (err == IARM_RESULT_SUCCESS && hdmiInput.result == dsERR_NONE) - { - LOGINFO("Number of Inputs [%d] \n", hdmiInput.numHdmiInputs ); - m_numofHdmiInput = hdmiInput.numHdmiInputs; - }else{ - LOGINFO("Not able to get Numebr of inputs so defaulting to 3 \n"); - m_numofHdmiInput = 3; - } - - LOGINFO("initalize inputs \n"); - - for (int i = 0; i < m_numofHdmiInput; i++){ - HdmiPortMap hdmiPort((uint8_t)i); - LOGINFO(" Add to vector [%d] \n", i); - hdmiInputs.push_back(hdmiPort); - } - - LOGINFO("Check the HDMI State \n"); - - CheckHdmiInState(); - if (cecSettingEnabled) - { - try - { - CECEnable(); - } - catch(...) - { - LOGWARN("Exception while enabling CEC settings .\r\n"); - } - } - getCecVersion(); - LOGINFO(" HdmiCecSinkImplementation plugin Initialize completed \n"); - return Core::ERROR_NONE; - - } - - Core::hresult HdmiCecSinkImplementation::Register(Exchange::IHdmiCecSink::INotification* notification) - { - LOGINFO("Register"); - if(notification != nullptr){ - _adminLock.Lock(); - if(std::find(_hdmiCecSinkNotifications.begin(), _hdmiCecSinkNotifications.end(), notification) == _hdmiCecSinkNotifications.end()) - { - _hdmiCecSinkNotifications.push_back(notification); - notification->AddRef(); - } - else - { - LOGERR("Same notification is registered already"); - } - _adminLock.Unlock(); - } - - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::Unregister(Exchange::IHdmiCecSink::INotification* notification) - { - LOGINFO("Unregister"); - if(notification != nullptr){ - _adminLock.Lock(); - std::list::iterator index = std::find(_hdmiCecSinkNotifications.begin(), _hdmiCecSinkNotifications.end(), notification); - if(index != _hdmiCecSinkNotifications.end()) - { - (*index)->Release(); - _hdmiCecSinkNotifications.erase(index); - } - else - { - LOGERR("Notification is not registered"); - } - _adminLock.Unlock(); - } - - return Core::ERROR_NONE; - } - - - const void HdmiCecSinkImplementation::InitializeIARM() - { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - } - } - - void HdmiCecSinkImplementation::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - } - } - - void HdmiCecSinkImplementation::InitializePowerManager(PluginHost::IShell *service) - { - _powerManagerPlugin = PowerManagerInterfaceBuilder(_T("org.rdk.PowerManager")) - .withIShell(service) - .withRetryIntervalMS(200) - .withRetryCount(25) - .createInterface(); - registerEventHandlers(); - } - void HdmiCecSinkImplementation::registerEventHandlers() - { - ASSERT (_powerManagerPlugin); - - if(!_registeredEventHandlers && _powerManagerPlugin) { - _registeredEventHandlers = true; - _powerManagerPlugin->Register(_pwrMgrNotification.baseInterface()); - } - } - - void HdmiCecSinkImplementation::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - bool isHdmiConnected = eventData->data.hdmi_in_connect.isPortConnected; - dsHdmiInPort_t portId = eventData->data.hdmi_in_connect.port; - LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event port: %d data:%d \r\n",portId, isHdmiConnected); - HdmiCecSinkImplementation::_instance->onHdmiHotPlug(portId,isHdmiConnected); - } - } - - void HdmiCecSinkImplementation::onPowerModeChanged(const PowerState ¤tState, const PowerState &newState) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - LOGINFO("Event IARM_BUS_PWRMGR_EVENT_MODECHANGED: State Changed %d -- > %d\r", - currentState, newState); - LOGWARN(" m_logicalAddressAllocated 0x%x CEC enable status %d \n",_instance->m_logicalAddressAllocated,_instance->cecEnableStatus); - if(newState == WPEFramework::Exchange::IPowerManager::POWER_STATE_ON) - { - powerState = DEVICE_POWER_STATE_ON; - } - else - { - powerState = DEVICE_POWER_STATE_OFF; - if((_instance->m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_INITIATION) || (_instance->m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) - { - LOGINFO("%s: Stop ARC \n",__FUNCTION__); - _instance->stopArc(); - } - - } - if (_instance->cecEnableStatus) - { - if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED ) - { - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); - - if ( powerState != DEVICE_POWER_STATE_ON ) - { - /* reset the current active source when TV on going to standby */ - HdmiCecSinkImplementation::_instance->m_currentActiveSource = -1; - } - /* Initiate a ping straight away */ - HdmiCecSinkImplementation::_instance->m_pollNextState = POLL_THREAD_STATE_PING; - HdmiCecSinkImplementation::_instance->m_ThreadExitCV.notify_one(); - } - } - else - { - LOGWARN("CEC not Enabled\n"); - } - } - - - void HdmiCecSinkImplementation::sendStandbyMessage() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(HdmiCecSinkImplementation::_instance->smConnection)) - return; - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(Standby()), 1000); - } - - void HdmiCecSinkImplementation::onHdmiHotPlug(int portId , int connectStatus) - { - LOGINFO("onHdmiHotPlug Status : %d ", connectStatus); - if(!connectStatus) - { - LOGINFO(" removeDevice port: %d Logical address :%d \r\n",portId,hdmiInputs[portId].m_logicalAddr.toInt() ); - _instance->removeDevice(hdmiInputs[portId].m_logicalAddr.toInt()); - } - CheckHdmiInState(); - - if(cecEnableStatus) { - LOGINFO("cecEnableStatus : %d Trigger CEC Ping !!! \n", cecEnableStatus); - m_pollNextState = POLL_THREAD_STATE_PING; - m_ThreadExitCV.notify_one(); - } - if( HdmiArcPortID >= 0 ) { - updateArcState(); - } - return; - } - void HdmiCecSinkImplementation::updateArcState() - { - if ( m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED ) - { - if (!(hdmiInputs[HdmiArcPortID].m_isConnected)) - { - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - else - { - LOGINFO("updateArcState :not updating ARC state current arc state %d ",m_currentArcRoutingState); - } - } - } - void HdmiCecSinkImplementation::arcStartStopTimerFunction() - { - JsonObject params; - - if (m_arcstarting) - { - LOGINFO("arcStartStopTimerFunction ARC start timer expired"); - LOGINFO("notify_device setting that Initiate ARC failed to get the ARC_STATE_ARC_INITIATED state\n"); - params["status"] = string("failure"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcInitiationEvent("failure"); - index++; - } - } - else - { - LOGINFO("arcStartStopTimerFunction ARC stop timer expired"); - LOGINFO("notify_device setting that Terminate ARC failed to get the ARC_STATE_ARC_TERMINATED state\n"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcTerminationEvent("failure"); - index++; - } - } - /* bring the state machine to the clean state for a new start */ - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - } - void HdmiCecSinkImplementation::Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor) - { - - LOGINFO("Notify the DS "); - string shortAudioDescriptors; - - if (!audiodescriptor.ToString(shortAudioDescriptors)) { - LOGERR("Failed to stringify JsonArray"); - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ShortAudiodescriptorEvent(shortAudioDescriptors); - index++; - } - } - - void HdmiCecSinkImplementation::Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg) - { - uint8_t numberofdescriptor = msg.numberofdescriptor; - uint32_t descriptor =0; - JsonArray audiodescriptor; - - if (numberofdescriptor) - { - for( uint8_t i=0; i < numberofdescriptor; i++) - { - descriptor = msg.shortAudioDescriptor[i].getAudiodescriptor(); - - LOGINFO("descriptor%d 0x%x\n",i,descriptor); - audiodescriptor.Add(descriptor); - - } - } - else - { - audiodescriptor.Add(descriptor); - } - HdmiCecSinkImplementation::_instance->Send_ShortAudioDescriptor_Event(audiodescriptor); - } - - void HdmiCecSinkImplementation::updateCurrentLatency(int videoLatency, bool lowLatencyMode,int audioOutputCompensated, int audioOutputDelay = 0) - { - uint8_t latencyFlags = 0; - latencyFlags = ((lowLatencyMode & 0x1) << 2) | (audioOutputCompensated & 0x3); - LOGINFO("Video Latency : %d , Low Latency Mode : %d ,Audio Output Compensated value : %d , Audio Output Delay : %d , Latency Flags: %d ", videoLatency, lowLatencyMode, audioOutputCompensated, audioOutputDelay, latencyFlags); - m_video_latency = (videoLatency/2) + 1; - m_latency_flags = latencyFlags; - m_audio_output_delay = (audioOutputDelay/2) + 1; - setLatencyInfo(); - } - - void HdmiCecSinkImplementation::setLatencyInfo() - { - if(!HdmiCecSinkImplementation::_instance) - return; - - if(!(_instance->smConnection)) - return; - - LOGINFO("Send Report Current Latency message \n"); - _instance->smConnection->sendTo(LogicalAddress::BROADCAST,MessageEncoder().encode(ReportCurrentLatency(physical_addr,m_video_latency,m_latency_flags,m_audio_output_delay))); - - } - - void HdmiCecSinkImplementation::Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg) - { - if(!HdmiCecSinkImplementation::_instance) - return; - - //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status - //SetSystemAudioMode message may come from AVR/Soundbar while CEC disable is in-progress - if ( cecSettingEnabled != true ) - { - LOGINFO("Process SetSystemAudioMode from Audio device: Cec is disabled-> EnableCEC first"); - return; - } - - if ( (msg.status.toInt() == SYSTEM_AUDIO_MODE_OFF) && (m_currentArcRoutingState == ARC_STATE_ARC_INITIATED)) - { - /* ie system audio mode off -> amplifier goign to standby but still ARC is in initiated state,stop ARC and - bring the ARC state machine to terminated state*/ - LOGINFO("system audio mode off message but arc is not in terminated state so stopping ARC"); - stopArc(); - - } - - if (msg.status.toInt() == SYSTEM_AUDIO_MODE_ON) { - LOGINFO("panel power state is %s", powerState ? "Off" : "On"); - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notifying system audio mode ON event"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->SetSystemAudioModeEvent(msg.status.toString()); - index++; - } - } else { - LOGINFO("Not notifying system audio mode ON event"); - } - } else { - LOGINFO("Notifying system audio Mode OFF event"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->SetSystemAudioModeEvent(msg.status.toString()); - index++; - } - } - } - void HdmiCecSinkImplementation::Process_ReportAudioStatus_msg(const ReportAudioStatus msg) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if (m_audioStatusTimerStarted) - { - m_audioStatusReceived = true; - m_isAudioStatusInfoUpdated = true; - m_audioStatusTimerStarted = false; - if (m_audioStatusDetectionTimer.isActive()) - { - LOGINFO("AudioStatus received from the Audio Device and the timer is still active. So stopping the timer!\n"); - m_audioStatusDetectionTimer.stop(); - } - LOGINFO("AudioStatus received from the Audio Device. Updating the AudioStatus info! m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - } - LOGINFO("Command: ReportAudioStatus %s audio Mute status %d means %s and current Volume level is %d \n",GetOpName(msg.opCode()),msg.status.getAudioMuteStatus(),msg.status.toString().c_str(),msg.status.getAudioVolume()); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioStatusEvent(msg.status.getAudioMuteStatus(), msg.status.getAudioVolume()); - index++; - } - - } - void HdmiCecSinkImplementation::sendKeyPressEvent(const int logicalAddress, int keyCode) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" sendKeyPressEvent logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); - switch(keyCode) - { - case VOLUME_UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); - break; - case VOLUME_DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); - break; - case MUTE: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); - break; - case UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); - break; - case DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); - break; - case LEFT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); - break; - case RIGHT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); - break; - case SELECT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); - break; - case HOME: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); - break; - case BACK: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); - break; - case NUMBER_0: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); - break; - case NUMBER_1: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); - break; - case NUMBER_2: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); - break; - case NUMBER_3: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); - break; - case NUMBER_4: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); - break; - case NUMBER_5: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); - break; - case NUMBER_6: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); - break; - case NUMBER_7: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); - break; - case NUMBER_8: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); - break; - case NUMBER_9: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); - break; - - } - } - - void HdmiCecSinkImplementation::sendUserControlPressed(const int logicalAddress, int keyCode) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" sendUserControlPressed logicalAddress 0x%x keycode 0x%x\n",logicalAddress,keyCode); - switch(keyCode) - { - case VOLUME_UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_UP)),100); - break; - case VOLUME_DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_VOLUME_DOWN)), 100); - break; - case MUTE: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_MUTE)), 100); - break; - case UP: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_UP)), 100); - break; - case DOWN: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_DOWN)), 100); - break; - case LEFT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_LEFT)), 100); - break; - case RIGHT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_RIGHT)), 100); - break; - case SELECT: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_SELECT)), 100); - break; - case HOME: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_HOME)), 100); - break; - case BACK: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_BACK)), 100); - break; - case NUMBER_0: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_0)), 100); - break; - case NUMBER_1: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_1)), 100); - break; - case NUMBER_2: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_2)), 100); - break; - case NUMBER_3: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_3)), 100); - break; - case NUMBER_4: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_4)), 100); - break; - case NUMBER_5: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_5)), 100); - break; - case NUMBER_6: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_6)), 100); - break; - case NUMBER_7: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_7)), 100); - break; - case NUMBER_8: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_8)), 100); - break; - case NUMBER_9: - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlPressed(UICommand::UI_COMMAND_NUM_9)), 100); - break; - - } - } - - void HdmiCecSinkImplementation::sendKeyReleaseEvent(const int logicalAddress) - { - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - - } - - void HdmiCecSinkImplementation::sendUserControlReleased(const int logicalAddress) - { - if(!(_instance->smConnection)) - return; - LOGINFO(" User Control Released \n"); - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(UserControlReleased()), 100); - } - - void HdmiCecSinkImplementation::sendDeviceUpdateInfo(const int logicalAddress) - { - LOGINFO("Send Device Update Info \n"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnDeviceInfoUpdated(logicalAddress); - index++; - } - } - void HdmiCecSinkImplementation::systemAudioModeRequest() - { - if ( cecEnableStatus != true ) - { - LOGINFO("systemAudioModeRequest: Cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - { - return; - } - LOGINFO(" Send systemAudioModeRequest "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(SystemAudioModeRequest(physical_addr)), 1000); - - } - void HdmiCecSinkImplementation::sendGiveAudioStatusMsg() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - { - return; - } - LOGINFO(" Send GiveAudioStatus "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(GiveAudioStatus()), 100); - - } - void HdmiCecSinkImplementation::reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus) - { - JsonObject params; - params["powerStatus"] = JsonValue(powerStatus); - LOGINFO("Panle power state is %s", powerState ? "Off" : "On"); - if (powerStatus != AUDIO_DEVICE_POWERSTATE_OFF) { - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDevicePowerStatus(powerStatus); - index++; - } - } else { - LOGINFO("Not notifying audio device power state to DS"); - } - } else { - LOGINFO("Notify DS!!! logicalAddress = %d , Audio device power status = %d \n", logicalAddress, powerStatus); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDevicePowerStatus(powerStatus); - index++; - } - } - } - - void HdmiCecSinkImplementation::SendStandbyMsgEvent(const int logicalAddress) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->StandbyMessageReceived(logicalAddress); - index++; - } - - } - Core::hresult HdmiCecSinkImplementation::SetEnabled(const bool &enabled, HdmiCecSinkSuccess &success) - { - - setEnabled(enabled); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetEnabled(bool &enabled, bool &success) - { - enabled = getEnabled(); - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetAudioDeviceConnectedStatus(bool &connected, bool &success) - { - connected = getAudioDeviceConnectedStatus(); - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetActiveSource(bool &available, uint8_t &logicalAddress, string &physicalAddress, string &deviceType, string &cecVersion, string &osdName, string &vendorID, string &powerStatus, string &port, bool &success) - { - char routeString[1024] = {'\0'}; - int length = 0; - std::stringstream temp; - - if ( HdmiCecSinkImplementation::_instance->m_currentActiveSource != -1 ) - { - int n = HdmiCecSinkImplementation::_instance->m_currentActiveSource; - available = true; - logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt(); - physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.toString().c_str(); - deviceType = HdmiCecSinkImplementation::_instance->deviceList[n].m_deviceType.toString().c_str(); - cecVersion = HdmiCecSinkImplementation::_instance->deviceList[n].m_cecVersion.toString().c_str(); - osdName = HdmiCecSinkImplementation::_instance->deviceList[n].m_osdName.toString().c_str(); - vendorID = HdmiCecSinkImplementation::_instance->deviceList[n].m_vendorID.toString().c_str(); - powerStatus = HdmiCecSinkImplementation::_instance->deviceList[n].m_powerStatus.toString().c_str(); - - - if ( HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) != 0 ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) - 1)); - } - else if ( HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.getByteValue(0) == 0 ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s", "TV"); - } - - temp << (char *)routeString; - port = temp.str(); - - } - else - { - available = false; - } - - success = true; - return Core::ERROR_NONE; - - } - - Core::hresult HdmiCecSinkImplementation::GetDeviceList(uint32_t &numberofdevices, IHdmiCecSinkDeviceListIterator*& deviceList, bool &success) - { - - numberofdevices = HdmiCecSinkImplementation::_instance->m_numberOfDevices; - LOGINFO("getDeviceList m_numberOfDevices :%d \n", HdmiCecSinkImplementation::_instance->m_numberOfDevices); - std::vector localDevices; - Exchange::IHdmiCecSink::HdmiCecSinkDevices actual_hdmicecdevices = {0}; - - for (int n = 0; n <= LogicalAddress::UNREGISTERED; n++) - { - - if ( n != HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated && - HdmiCecSinkImplementation::_instance->deviceList[n].m_isDevicePresent ) - { - - actual_hdmicecdevices.logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt(); - actual_hdmicecdevices.physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[n].m_physicalAddr.toString().c_str(); - actual_hdmicecdevices.deviceType = HdmiCecSinkImplementation::_instance->deviceList[n].m_deviceType.toString().c_str(); - actual_hdmicecdevices.cecVersion = HdmiCecSinkImplementation::_instance->deviceList[n].m_cecVersion.toString().c_str(); - actual_hdmicecdevices.osdName = HdmiCecSinkImplementation::_instance->deviceList[n].m_osdName.toString().c_str(); - actual_hdmicecdevices.vendorID = HdmiCecSinkImplementation::_instance->deviceList[n].m_vendorID.toString().c_str(); - actual_hdmicecdevices.powerStatus = HdmiCecSinkImplementation::_instance->deviceList[n].m_powerStatus.toString().c_str(); - int hdmiPortNumber = -1; - LOGINFO("getDeviceList m_numofHdmiInput:%d looking for Logical Address :%d \n", m_numofHdmiInput, HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt()); - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO("getDeviceList connected : %d, portid:%d LA: %d \n", hdmiInputs[i].m_isConnected, hdmiInputs[i].m_portID, hdmiInputs[i].m_logicalAddr.toInt()); - if(hdmiInputs[i].m_isConnected && hdmiInputs[i].m_logicalAddr.toInt() == HdmiCecSinkImplementation::_instance->deviceList[n].m_logicalAddress.toInt()) - { - hdmiPortNumber = hdmiInputs[i].m_portID; - LOGINFO("got portid :%d break \n", hdmiPortNumber); - break; - } - } - actual_hdmicecdevices.powerStatus = hdmiPortNumber; - localDevices.push_back(actual_hdmicecdevices); - } - } - - deviceList = (Core::Service>::Create(localDevices)); - success = true; - return Core::ERROR_NONE; - } - - - Core::hresult HdmiCecSinkImplementation::SetOSDName(const string &name, HdmiCecSinkSuccess &success) - { - - LOGINFO("SetOSDName osdName: %s",name.c_str()); - osdName = name.c_str(); - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_OSD_NAME, JsonValue(name.c_str())); - - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetOSDName(string &name, bool &success) - { - name = osdName.toString(); - LOGINFO("GetOSDName osdName : %s \n",osdName.toString().c_str()); - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::PrintDeviceList(bool &printed, bool &success) - { - printDeviceList(); - printed = true; - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetActiveSource(HdmiCecSinkSuccess &success) - { - setActiveSource(false); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetActivePath(const string &activePath, HdmiCecSinkSuccess &success) - { - string activePathStr = activePath; - PhysicalAddress phy_addr = PhysicalAddress(activePathStr); - LOGINFO("Addr = %s, length = %zu", activePathStr.c_str(), activePathStr.length()); - setStreamPath(phy_addr); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetActiveRoute(bool &available, uint8_t &length, IHdmiCecSinkActivePathIterator*& pathList, string &ActiveRoute, bool &success) - { - std::vector route; - char routeString[1024] = {'\0'}; - std::vector paths; - std::stringstream temp; - - if (HdmiCecSinkImplementation::_instance->m_currentActiveSource != -1 && - HdmiCecSinkImplementation::_instance->m_currentActiveSource != HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated ) - { - HdmiCecSinkImplementation::_instance->getActiveRoute(LogicalAddress(HdmiCecSinkImplementation::_instance->m_currentActiveSource), route); - - if (route.size()) - { - available = true; - length = route.size(); - - for (unsigned int i=0; i < route.size(); i++) - { - if ( route[i] != LogicalAddress::UNREGISTERED ) - { - Exchange::IHdmiCecSink::HdmiCecSinkActivePath device; - - device.logicalAddress = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_logicalAddress.toInt(); - device.physicalAddress = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_physicalAddr.toString().c_str(); - device.deviceType = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_deviceType.toString().c_str(); - device.vendorID = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_osdName.toString().c_str(); - device.osdName = HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_vendorID.toString().c_str(); - - paths.push_back(device); - - snprintf(&routeString[length], sizeof(routeString) - length, "%s", _instance->deviceList[route[i]].m_logicalAddress.toString().c_str()); - length += _instance->deviceList[route[i]].m_logicalAddress.toString().length(); - snprintf(&routeString[length], sizeof(routeString) - length, "(%s", _instance->deviceList[route[i]].m_osdName.toString().c_str()); - length += _instance->deviceList[route[i]].m_osdName.toString().length(); - snprintf(&routeString[length], sizeof(routeString) - length, "%s", ")-->"); - length += strlen(")-->"); - if( i + 1 == route.size() ) - { - snprintf(&routeString[length], sizeof(routeString) - length, "%s%d", "HDMI",(HdmiCecSinkImplementation::_instance->deviceList[route[i]].m_physicalAddr.getByteValue(0) - 1)); - } - } - } - - pathList = (Core::Service>::Create(paths)); - temp << (char *)routeString; - ActiveRoute = temp.str(); - LOGINFO("ActiveRoute = [%s]", routeString); - } - else{ - available = false; - } - - } - else if ( HdmiCecSinkImplementation::_instance->m_currentActiveSource == HdmiCecSinkImplementation::_instance->m_logicalAddressAllocated ) - { - available = true; - ActiveRoute = "TV"; - } - else - { - available = false; - } - - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::RequestActiveSource(HdmiCecSinkSuccess &success) - { - requestActiveSource(); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetRoutingChange(const string &oldPort, const string &newPort, HdmiCecSinkSuccess &success) - { - if ((oldPort.find("HDMI",0) != std::string::npos || - oldPort.find("TV",0) != std::string::npos ) && - (newPort.find("HDMI", 0) != std::string::npos || - newPort.find("TV", 0) != std::string::npos )) - { - setRoutingChange(oldPort, newPort); - success.success = true; - } - else - { - success.success = false; - } - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SetMenuLanguage(const string &language, HdmiCecSinkSuccess &success) - { - std::string lang; - - lang = language; - - setCurrentLanguage(Language(lang.data())); - success.success = true; - - return Core::ERROR_NONE; - - } - - - Core::hresult HdmiCecSinkImplementation::SetVendorId(const string &vendorId, HdmiCecSinkSuccess &success) - { - - unsigned int vendorID = 0x00; - try - { - vendorID = stoi(vendorId,NULL,16); - } - catch (...) - { - LOGWARN("Exception in setVendorId set default value\n"); - vendorID = 0x0019FB; - } - appVendorId = {(uint8_t)(vendorID >> 16 & 0xff),(uint8_t)(vendorID>> 8 & 0xff),(uint8_t) (vendorID & 0xff)}; - LOGINFO("appVendorId : %s vendorID :%x \n",appVendorId.toString().c_str(), vendorID ); - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_VENDOR_ID, JsonValue(vendorID)); - - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SetupARCRouting(const bool &enabled, HdmiCecSinkSuccess &success) - { - if(enabled) - { - startArc(); - } - else - { - stopArc(); - } - - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::GetVendorId(string &vendorid, bool &success) - { - LOGINFO("GetVendorId appVendorId : %s \n",appVendorId.toString().c_str()); - vendorid = appVendorId.toString() ; - success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::RequestShortAudioDescriptor(HdmiCecSinkSuccess &success) - { - requestShortaudioDescriptor(); - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SendStandbyMessage(HdmiCecSinkSuccess &success) - { - sendStandbyMessage(); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendAudioDevicePowerOnMessage(HdmiCecSinkSuccess &success) - { - LOGINFO("%s invoked. \n",__FUNCTION__); - systemAudioModeRequest(); - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SendKeyPressEvent(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) - { - SendKeyInfo keyInfo; - - keyInfo.logicalAddr = logicalAddress; - keyInfo.keyCode = keyCode; - keyInfo.UserControl = "sendKeyPressEvent"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("Post send key press event to queue size:%zu \n",m_SendKeyQueue.size()); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendUserControlPressed(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) - { - - SendKeyInfo keyInfo; - keyInfo.logicalAddr = logicalAddress; - keyInfo.keyCode = keyCode; - keyInfo.UserControl = "sendUserControlPressed"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("User control pressed, queue size:%zu \n",m_SendKeyQueue.size()); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendUserControlReleased(const uint32_t &logicalAddress, HdmiCecSinkSuccess &success) - { - SendKeyInfo keyInfo; - keyInfo.logicalAddr = logicalAddress; - keyInfo.keyCode = 0; - keyInfo.UserControl = "sendUserControlReleased"; - std::unique_lock lk(m_sendKeyEventMutex); - m_SendKeyQueue.push(keyInfo); - m_sendKeyEventThreadRun = true; - m_sendKeyCV.notify_one(); - LOGINFO("User Control Released, queue size:%zu \n",m_SendKeyQueue.size()); - success.success = true; - return Core::ERROR_NONE; - } - - Core::hresult HdmiCecSinkImplementation::SendGetAudioStatusMessage(HdmiCecSinkSuccess &success) - { - sendGiveAudioStatusMsg(); - success.success = true; - return Core::ERROR_NONE; - } - Core::hresult HdmiCecSinkImplementation::SetLatencyInfo(const string &videoLatency, const string &lowLatencyMode, const string &audioOutputCompensated, const string &audioOutputDelay, HdmiCecSinkSuccess &success) - { - int video_latency,audio_output_compensated,audio_output_delay; - bool low_latency_mode; - - LOGINFO("SetLatencyInfo videoLatency : %s lowLatencyMode : %s audioOutputCompensated : %s audioOutputDelay : %s \n",videoLatency.c_str(),lowLatencyMode.c_str(),audioOutputCompensated.c_str(),audioOutputDelay.c_str()); - video_latency = stoi(videoLatency); - low_latency_mode = stoi(lowLatencyMode); - audio_output_compensated = stoi(audioOutputCompensated); - audio_output_delay = stoi(audioOutputDelay); - - updateCurrentLatency(video_latency, low_latency_mode,audio_output_compensated, audio_output_delay); - success.success = true; - return Core::ERROR_NONE; - } - bool HdmiCecSinkImplementation::loadSettings() - { - Core::File file; - file = CEC_SETTING_ENABLED_FILE; - - if( file.Open()) - { - JsonObject parameters; - parameters.IElement::FromFile(file); - bool isConfigAdded = false; - - if( parameters.HasLabel(CEC_SETTING_ENABLED)) - { - getBoolParameter(CEC_SETTING_ENABLED, cecSettingEnabled); - LOGINFO("CEC_SETTING_ENABLED present value:%d",cecSettingEnabled); - } - else - { - parameters[CEC_SETTING_ENABLED] = true; - cecSettingEnabled = true; - isConfigAdded = true; - LOGINFO("CEC_SETTING_ENABLED not present set dafult true:\n "); - } - - if( parameters.HasLabel(CEC_SETTING_OTP_ENABLED)) - { - getBoolParameter(CEC_SETTING_OTP_ENABLED, cecOTPSettingEnabled); - LOGINFO("CEC_SETTING_OTP_ENABLED present value :%d",cecOTPSettingEnabled); - } - else - { - parameters[CEC_SETTING_OTP_ENABLED] = true; - cecOTPSettingEnabled = true; - isConfigAdded = true; - LOGINFO("CEC_SETTING_OTP_ENABLED not present set dafult true:\n "); - } - if( parameters.HasLabel(CEC_SETTING_OSD_NAME)) - { - std::string osd_name; - getStringParameter(CEC_SETTING_OSD_NAME, osd_name); - osdName = osd_name.c_str(); - LOGINFO("CEC_SETTING_OSD_NAME present osd_name :%s",osdName.toString().c_str()); - } - else - { - parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); - LOGINFO("CEC_SETTING_OSD_NMAE not present set dafult value :%s\n ",osdName.toString().c_str()); - isConfigAdded = true; - } - unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); - if( parameters.HasLabel(CEC_SETTING_VENDOR_ID)) - { - getNumberParameter(CEC_SETTING_VENDOR_ID, vendorId); - LOGINFO("CEC_SETTING_VENDOR_ID present :%x ",vendorId); - } - else - { - LOGINFO("CEC_SETTING_VENDOR_ID not present set dafult value :%x \n ",vendorId); - parameters[CEC_SETTING_VENDOR_ID] = vendorId; - isConfigAdded = true; - } - - appVendorId = {(uint8_t)(vendorId >> 16 & 0xff),(uint8_t)(vendorId >> 8 & 0xff),(uint8_t) (vendorId & 0xff)}; - LOGINFO("appVendorId : %s vendorId :%x \n",appVendorId.toString().c_str(), vendorId ); - - if(isConfigAdded) - { - LOGINFO("isConfigAdded true so update file:\n "); - file.Destroy(); - file.Create(); - parameters.IElement::ToFile(file); - - } - - file.Close(); - } - else - { - LOGINFO("CEC_SETTING_ENABLED_FILE file not present create with default settings "); - file.Open(false); - if (!file.IsOpen()) - file.Create(); - - JsonObject parameters; - unsigned int vendorId = (defaultVendorId.at(0) <<16) | ( defaultVendorId.at(1) << 8 ) | defaultVendorId.at(2); - parameters[CEC_SETTING_ENABLED] = true; - parameters[CEC_SETTING_OSD_NAME] = osdName.toString(); - parameters[CEC_SETTING_VENDOR_ID] = vendorId; - - cecSettingEnabled = true; - cecOTPSettingEnabled = true; - parameters.IElement::ToFile(file); - - file.Close(); - - } - - return cecSettingEnabled; - } - - void HdmiCecSinkImplementation::setEnabled(bool enabled) - { - LOGINFO("Entered setEnabled: %d cecSettingEnabled :%d ",enabled, cecSettingEnabled); - - if (cecSettingEnabled != enabled) - { - Utils::persistJsonSettings (CEC_SETTING_ENABLED_FILE, CEC_SETTING_ENABLED, JsonValue(enabled)); - cecSettingEnabled = enabled; - } - if(true == enabled) - { - CECEnable(); - } - else - { - CECDisable(); - } - return; - } - - void HdmiCecSinkImplementation::updateImageViewOn(const int logicalAddress) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnWakeupFromStandby(logicalAddress); - index++; - } - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnInActiveSource(logicalAddress, _instance->deviceList[logicalAddress].m_physicalAddr.toString()); - index++; - } - } - - void HdmiCecSinkImplementation::updateTextViewOn(const int logicalAddress) - { - JsonObject params; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnWakeupFromStandby(logicalAddress); - index++; - } - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnTextViewOnMsg(logicalAddress); - index++; - } - } - - - void HdmiCecSinkImplementation::updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && - logicalAddress.toInt() != _instance->m_logicalAddressAllocated) - { - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO(" addr = %d, portID = %d", phy_addr.getByteValue(0), hdmiInputs[i].m_portID); - if (phy_addr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].addChild(logicalAddress, phy_addr); - } - } - } - } - - void HdmiCecSinkImplementation::getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || - logicalAddress.toInt() == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress.toInt()].m_isDevicePresent && - logicalAddress.toInt() != _instance->m_logicalAddressAllocated && - _instance->deviceList[logicalAddress.toInt()].m_isActiveSource ) - { - route.clear(); - for (int i=0; i < m_numofHdmiInput; i++) - { - LOGINFO("physicalAddress = [%d], portID = %d", _instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0), hdmiInputs[i].m_portID); - if (_instance->deviceList[logicalAddress.toInt()].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].getRoute(_instance->deviceList[logicalAddress.toInt()].m_physicalAddr, route); - } - } - } - else { - LOGERR("Not in correct state to Find Route"); - } - } - - - void HdmiCecSinkImplementation::CheckHdmiInState() - { - int err; - bool isAnyPortConnected = false; - - dsHdmiInGetStatusParam_t params; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - IARM_BUS_DSMGR_API_dsHdmiInGetStatus, - (void *)¶ms, - sizeof(params)); - - if(err == IARM_RESULT_SUCCESS && params.result == dsERR_NONE ) - { - for( int i = 0; i < m_numofHdmiInput; i++ ) - { - LOGINFO("Is HDMI In Port [%d] connected [%d] \n",i, params.status.isPortConnected[i]); - if ( params.status.isPortConnected[i] ) - { - isAnyPortConnected = true; - } - - LOGINFO("update Port Status [%d] \n", i); - hdmiInputs[i].update(params.status.isPortConnected[i]); - } - } - - if ( isAnyPortConnected ) { - m_isHdmiInConnected = true; - } else { - m_isHdmiInConnected = false; - } - } - - void HdmiCecSinkImplementation::requestActiveSource() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, - MessageEncoder().encode(RequestActiveSourceMessage()), 500); - } - - void HdmiCecSinkImplementation::setActiveSource(bool isResponse) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (isResponse && (_instance->m_currentActiveSource != _instance->m_logicalAddressAllocated) ) - { - LOGWARN("TV is not current Active Source"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, - MessageEncoder().encode(ActiveSource(_instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr)), 500); - _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; - } - - void HdmiCecSinkImplementation::setCurrentLanguage(const Language &lang) - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = lang; - } - - void HdmiCecSinkImplementation::sendMenuLanguage() - { - Language lang = ""; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - lang = _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage; - - _instance->smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(SetMenuLanguageMessage(lang)), 100); - } - - void HdmiCecSinkImplementation::updateInActiveSource(const int logical_address, const InActiveSource &source ) - { - JsonObject params; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if( logical_address != _instance->m_logicalAddressAllocated ) - { - _instance->deviceList[logical_address].m_isActiveSource = false; - - if ( _instance->m_currentActiveSource == logical_address ) - { - _instance->m_currentActiveSource = -1; - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnInActiveSource(logical_address, source.physicalAddress.toString()); - index++; - } - } - } - - void HdmiCecSinkImplementation::updateActiveSource(const int logical_address, const ActiveSource &source ) - { - JsonObject params; - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if( logical_address != _instance->m_logicalAddressAllocated ) - { - if ( _instance->m_currentActiveSource != -1 ) - { - _instance->deviceList[_instance->m_currentActiveSource].m_isActiveSource = false; - } - - _instance->deviceList[logical_address].m_isActiveSource = true; - _instance->deviceList[logical_address].update(source.physicalAddress); - _instance->m_currentActiveSource = logical_address; - - if (_instance->deviceList[logical_address].m_isDevicePresent && - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus.toInt() == PowerStatus::STANDBY) - { - /* Bringing TV out of standby is handled by application.notify UI to bring the TV out of standby */ - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnWakeupFromStandby(logical_address); - index++; - } - } - - string physicalAddress = _instance->deviceList[logical_address].m_physicalAddr.toString().c_str(); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnActiveSourceChange(logical_address, physicalAddress); - index++; - } - } - } - - void HdmiCecSinkImplementation::requestShortaudioDescriptor() - { - if ( cecEnableStatus != true ) - { - LOGINFO("requestShortaudioDescriptor: cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - LOGINFO(" Send requestShortAudioDescriptor Message "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestShortAudioDescriptorMessage(formatid,audioFormatCode,numberofdescriptor)), 1000); - - } - - void HdmiCecSinkImplementation::requestAudioDevicePowerStatus() - { - if ( cecEnableStatus != true ) - { - LOGWARN("cec is disabled-> EnableCEC first"); - return; - } - - if(!HdmiCecSinkImplementation::_instance) - return; - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - LOGINFO(" Send GiveDevicePowerStatus Message to Audio system in the network \n"); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM, MessageEncoder().encode(GiveDevicePowerStatus()), 500); - - m_audioDevicePowerStatusRequested = true; - } - - void HdmiCecSinkImplementation::sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason) - { - - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Sending FeatureAbort to %s for opcode %s with reason %s ",logicalAddress.toString().c_str(),feature.toString().c_str(),reason.toString().c_str()); - _instance->smConnection->sendTo(logicalAddress, MessageEncoder().encode(FeatureAbort(feature,reason)), 500); - } - - void HdmiCecSinkImplementation::reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode featureOpcode, const AbortReason abortReason) - { - LOGINFO(" Notifying the UI FeatureAbort from the %s for the opcode %s with the reason %s ",logicalAddress.toString().c_str(),featureOpcode.toString().c_str(),abortReason.toString().c_str()); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportFeatureAbortEvent(logicalAddress.toInt(), featureOpcode.opCode(), abortReason.toInt()); - index++; - } - } - - void HdmiCecSinkImplementation::pingDevices(std::vector &connected , std::vector &disconnected) - { - int i; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - return; - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED ){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - for(i=0; i< LogicalAddress::UNREGISTERED; i++ ) { - if ( i != _instance->m_logicalAddressAllocated ) - { - //LOGWARN("PING for 0x%x \r\n",i); - try { - _instance->smConnection->ping(LogicalAddress(_instance->m_logicalAddressAllocated), LogicalAddress(i), Throw_e()); - } - catch(CECNoAckException &e) - { - if ( _instance->deviceList[i].m_isDevicePresent ) { - disconnected.push_back(i); - } - //LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); - usleep(50000); - continue; - } - catch(Exception &e) - { - LOGWARN("Ping device: 0x%x caught %s \r\n", i, e.what()); - usleep(50000); - continue; - } - - /* If we get ACK, then the device is present in the network*/ - if ( !_instance->deviceList[i].m_isDevicePresent ) - { - connected.push_back(i); - //LOGWARN("Ping success, added device: 0x%x \r\n", i); - } - usleep(50000); - } - } - } - - int HdmiCecSinkImplementation::requestType( const int logicalAddress ) { - int requestType = CECDeviceParams::REQUEST_NONE; - - if ( !_instance->deviceList[logicalAddress].m_isPAUpdated || !_instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) { - requestType = CECDeviceParams::REQUEST_PHISICAL_ADDRESS; - }else if ( !_instance->deviceList[logicalAddress].m_isOSDNameUpdated ) { - requestType = CECDeviceParams::REQUEST_OSD_NAME; - }else if ( !_instance->deviceList[logicalAddress].m_isVersionUpdated ) { - requestType = CECDeviceParams::REQUEST_CEC_VERSION; - }else if ( !_instance->deviceList[logicalAddress].m_isVendorIDUpdated ) { - requestType = CECDeviceParams::REQUEST_DEVICE_VENDOR_ID; - }else if ( !_instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) { - requestType = CECDeviceParams::REQUEST_POWER_STATUS; - } - - return requestType; - } - - void HdmiCecSinkImplementation::printDeviceList() { - int i; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - for(i=0; i< 16; i++) - { - if (HdmiCecSinkImplementation::_instance->deviceList[i].m_isDevicePresent) { - LOGWARN("------ Device ID = %d--------", i); - HdmiCecSinkImplementation::_instance->deviceList[i].printVariable(); - LOGWARN("-----------------------------"); - } - } - } - - void HdmiCecSinkImplementation::setStreamPath( const PhysicalAddress &physical_addr) { - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(SetStreamPath(physical_addr)), 500); - } - - void HdmiCecSinkImplementation::setRoutingChange(const std::string &from, const std::string &to) { - PhysicalAddress oldPhyAddr = {0xF,0xF,0xF,0xF}; - PhysicalAddress newPhyAddr = {0xF,0xF,0xF,0xF}; - int oldPortID = -1; - int newPortID = -1; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - if( from.find("TV",0) != std::string::npos ) - { - oldPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; - _instance->m_currentActiveSource = -1; - } - else - { - oldPortID = stoi(from.substr(4,1),NULL,16); - if ( oldPortID < _instance->m_numofHdmiInput ) - { - oldPhyAddr = _instance->hdmiInputs[oldPortID].m_physicalAddr; - } - else - { - LOGERR("Invalid HDMI Old Port ID"); - return; - } - } - - if( to.find("TV",0) != std::string::npos ) - { - newPhyAddr = _instance->deviceList[_instance->m_logicalAddressAllocated].m_physicalAddr; - /*set active source as TV */ - _instance->m_currentActiveSource = _instance->m_logicalAddressAllocated; - } - else - { - newPortID = stoi(to.substr(4,1),NULL,16); - - if ( newPortID < _instance->m_numofHdmiInput ) - { - newPhyAddr = _instance->hdmiInputs[newPortID].m_physicalAddr; - } - else - { - LOGERR("Invalid HDMI New Port ID"); - return; - } - } - - if(!(_instance->smConnection)) - { - return; - } - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(RoutingChange(oldPhyAddr, newPhyAddr)), 500); - } - - void HdmiCecSinkImplementation::addDevice(const int logicalAddress) { - JsonObject params; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if ( !HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_isDevicePresent ) - { - HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_isDevicePresent = true; - HdmiCecSinkImplementation::_instance->deviceList[logicalAddress].m_logicalAddress = LogicalAddress(logicalAddress); - HdmiCecSinkImplementation::_instance->m_numberOfDevices++; - HdmiCecSinkImplementation::_instance->m_pollNextState = POLL_THREAD_STATE_INFO; - - if(logicalAddress == 0x5) - { - LOGINFO(" logicalAddress =%d , Audio device detected, Notify Device Settings", logicalAddress ); - hdmiCecAudioDeviceConnected = true; - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDeviceConnectedStatus("success", "true"); - index++; - } - } - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnDeviceAdded(logicalAddress); - index++; - } - } - } - - void HdmiCecSinkImplementation::removeDevice(const int logicalAddress) { - JsonObject params; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED){ - LOGERR("Logical Address NOT Allocated"); - return; - } - - if (_instance->deviceList[logicalAddress].m_isDevicePresent) - { - _instance->m_numberOfDevices--; - - for (int i=0; i < m_numofHdmiInput; i++) - { - if (_instance->deviceList[logicalAddress].m_physicalAddr.getByteValue(0) == (hdmiInputs[i].m_portID + 1)) { - hdmiInputs[i].removeChild(_instance->deviceList[logicalAddress].m_physicalAddr); - hdmiInputs[i].update(LogicalAddress(LogicalAddress::UNREGISTERED)); - } - } - - if(logicalAddress == 0x5) - { - LOGINFO(" logicalAddress =%d , Audio device removed, Notify Device Settings", logicalAddress ); - - hdmiCecAudioDeviceConnected = false; - if (m_audioStatusDetectionTimer.isActive()){ - m_audioStatusDetectionTimer.stop(); - } - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - LOGINFO("Audio device removed, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportAudioDeviceConnectedStatus("success", "false"); - index++; - } - } - - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - _instance->deviceList[logicalAddress].clear(); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->OnDeviceRemoved(logicalAddress); - index++; - } - } - } - - void HdmiCecSinkImplementation::request(const int logicalAddress) { - int requestType; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(!(_instance->smConnection)) - { - return; - } - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ){ - LOGERR("Logical Address NOT Allocated Or its not valid"); - return; - } - - requestType = _instance->requestType(logicalAddress); - _instance->deviceList[logicalAddress].m_isRequested = requestType; - - switch (requestType) - { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GivePhysicalAddress()), 200); - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GetCECVersion()), 100); - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDeviceVendorID()), 100); - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveOSDName()), 500); - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - _instance->smConnection->sendTo(LogicalAddress(logicalAddress), MessageEncoder().encode(GiveDevicePowerStatus()), 100); - } - break; - default: - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - break; - } - - _instance->deviceList[logicalAddress].m_requestTime = std::chrono::system_clock::now(); - LOGINFO("request type %d", _instance->deviceList[logicalAddress].m_isRequested); - } - - int HdmiCecSinkImplementation::requestStatus(const int logicalAddress) { - std::chrono::duration elapsed; - bool isElapsed = false; - - if(!HdmiCecSinkImplementation::_instance) - return -1; - - - if ( _instance->m_logicalAddressAllocated == LogicalAddress::UNREGISTERED || logicalAddress >= LogicalAddress::UNREGISTERED + TEST_ADD ) { - LOGERR("Logical Address NOT Allocated Or its not valid"); - return -1; - } - - switch ( _instance->deviceList[logicalAddress].m_isRequested ) { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - if( _instance->deviceList[logicalAddress].m_isPAUpdated && - _instance->deviceList[logicalAddress].m_isDeviceTypeUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - if( _instance->deviceList[logicalAddress].m_isVersionUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - if( _instance->deviceList[logicalAddress].m_isVendorIDUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - if( _instance->deviceList[logicalAddress].m_isOSDNameUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - if( _instance->deviceList[logicalAddress].m_isPowerStatusUpdated ) - { - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - } - break; - default: - break; - } - - if ( _instance->deviceList[logicalAddress].m_isRequested != CECDeviceParams::REQUEST_NONE ) - { - elapsed = std::chrono::system_clock::now() - _instance->deviceList[logicalAddress].m_requestTime; - - if ( elapsed.count() > HDMICECSINK_REQUEST_MAX_WAIT_TIME_MS ) - { - LOGINFO("request elapsed "); - isElapsed = true; - } - } - - if (isElapsed) - { - /* For some request it should be retry, like report physical address etc for other we can have default values */ - switch( _instance->deviceList[logicalAddress].m_isRequested ) - { - case CECDeviceParams::REQUEST_PHISICAL_ADDRESS : - { - LOGINFO("Retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - /* Update with Invalid Physical Address */ - if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) - { - LOGINFO("Max retry for REQUEST_PHISICAL_ADDRESS = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - _instance->deviceList[logicalAddress].update(PhysicalAddress(0xF,0xF,0xF,0xF)); - _instance->deviceList[logicalAddress].update(DeviceType(DeviceType::RESERVED)); - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - } - } - break; - - case CECDeviceParams::REQUEST_CEC_VERSION : - { - /*Defaulting to 1.4*/ - _instance->deviceList[logicalAddress].update(Version(Version::V_1_4)); - } - break; - - case CECDeviceParams::REQUEST_DEVICE_VENDOR_ID : - { - _instance->deviceList[logicalAddress].update(VendorID(0,0,0)); - } - break; - - case CECDeviceParams::REQUEST_OSD_NAME : - { - if ( _instance->deviceList[logicalAddress].m_isRequestRetry++ >= HDMICECSINK_REQUEST_MAX_RETRY ) - { - LOGINFO("Max retry for REQUEST_OSD_NAME = %d", _instance->deviceList[logicalAddress].m_isRequestRetry); - _instance->deviceList[logicalAddress].update(OSDName("")); - _instance->deviceList[logicalAddress].m_isRequestRetry = 0; - } - } - break; - - case CECDeviceParams::REQUEST_POWER_STATUS : - { - _instance->deviceList[logicalAddress].update(PowerStatus(PowerStatus::POWER_STATUS_NOT_KNOWN)); - } - break; - default: - break; - } - - - _instance->deviceList[logicalAddress].m_isRequested = CECDeviceParams::REQUEST_NONE; - } - - if( _instance->deviceList[logicalAddress].m_isRequested == CECDeviceParams::REQUEST_NONE) - { - LOGINFO("Request Done"); - return CECDeviceParams::REQUEST_DONE; - } - - //LOGINFO("Request NOT Done"); - return CECDeviceParams::REQUEST_NOT_DONE; - } - - void HdmiCecSinkImplementation::threadRun() - { - std::vector connected; - std::vector disconnected; - int logicalAddressRequested = LogicalAddress::UNREGISTERED + TEST_ADD; - bool isExit = false; - - if(!HdmiCecSinkImplementation::_instance) - return; - - if(!(_instance->smConnection)) - return; - LOGINFO("Entering ThreadRun: _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); - _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; - - while(1) - { - - if (_instance->m_pollThreadExit || isExit ){ - LOGWARN("Thread Exits _instance->m_pollThreadExit %d isExit %d _instance->m_pollThreadState %d _instance->m_pollNextState %d",_instance->m_pollThreadExit,isExit,_instance->m_pollThreadState,_instance->m_pollNextState ); - break; - } - - if ( _instance->m_pollNextState != POLL_THREAD_STATE_NONE ) - { - _instance->m_pollThreadState = _instance->m_pollNextState; - _instance->m_pollNextState = POLL_THREAD_STATE_NONE; - } - - switch (_instance->m_pollThreadState) { - - case POLL_THREAD_STATE_POLL : - { - //LOGINFO("POLL_THREAD_STATE_POLL"); - _instance->allocateLogicalAddress(DeviceType::TV); - if ( _instance->m_logicalAddressAllocated != LogicalAddress::UNREGISTERED) - { - try{ - - logicalAddress = LogicalAddress(_instance->m_logicalAddressAllocated); - LibCCEC::getInstance().addLogicalAddress(logicalAddress); - _instance->smConnection->setSource(logicalAddress); - _instance->m_numberOfDevices = 0; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType = DeviceType::TV; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_isDevicePresent = true; - _instance->deviceList[_instance->m_logicalAddressAllocated].update(physical_addr); - _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_1_4; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_vendorID = appVendorId; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_powerStatus = PowerStatus(powerState); - _instance->deviceList[_instance->m_logicalAddressAllocated].m_currentLanguage = defaultLanguage; - _instance->deviceList[_instance->m_logicalAddressAllocated].m_osdName = osdName.toString().c_str(); - if(cecVersion == 2.0) { - _instance->deviceList[_instance->m_logicalAddressAllocated].m_cecVersion = Version::V_2_0; - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), - MessageEncoder().encode(ReportFeatures(Version::V_2_0,allDevicetype,rcProfile,deviceFeatures)), 500); - } - _instance->smConnection->addFrameListener(_instance->msgFrameListener); - _instance->smConnection->sendTo(LogicalAddress(LogicalAddress::BROADCAST), - MessageEncoder().encode(ReportPhysicalAddress(physical_addr, _instance->deviceList[_instance->m_logicalAddressAllocated].m_deviceType)), 100); - - _instance->m_sleepTime = 0; - _instance->m_pollThreadState = POLL_THREAD_STATE_PING; - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught while allocated logical address. %s", e.what()); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - catch(IOException &e){ - LOGWARN("IOException caught while allocated logical address. %s", e.what()); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - catch(...){ - LOGWARN("Exception caught while allocated logical address."); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - } - else - { - LOGINFO("Not able allocate Logical Address for TV"); - _instance->m_pollThreadState = POLL_THREAD_STATE_EXIT; - } - } - break; - - case POLL_THREAD_STATE_PING : - { - //LOGINFO("POLL_THREAD_STATE_PING"); - _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; - connected.clear(); - disconnected.clear(); - _instance->pingDevices(connected, disconnected); - - if ( disconnected.size() ){ - for( unsigned int i=0; i< disconnected.size(); i++ ) - { - LOGWARN("Disconnected Devices [%zu]", disconnected.size()); - _instance->removeDevice(disconnected[i]); - } - } - - if (connected.size()) { - LOGWARN("Connected Devices [%zu]", connected.size()); - for( unsigned int i=0; i< connected.size(); i++ ) - { - _instance->addDevice(connected[i]); - /* If new device is connected, then try to aquire the information */ - _instance->m_pollThreadState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - else - { - for(int i=0;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - !_instance->deviceList[i].isAllUpdated() ) - { - _instance->m_pollNextState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - /* Check for any update required */ - _instance->m_pollThreadState = POLL_THREAD_STATE_UPDATE; - _instance->m_sleepTime = 0; - } - } - break; - - case POLL_THREAD_STATE_INFO : - { - //LOGINFO("POLL_THREAD_STATE_INFO"); - - if ( logicalAddressRequested == LogicalAddress::UNREGISTERED + TEST_ADD ) - { - int i = 0; - for(;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - !_instance->deviceList[i].isAllUpdated() ) - { - //LOGINFO("POLL_THREAD_STATE_INFO -> request for %d", i); - logicalAddressRequested = i; - _instance->request(logicalAddressRequested); - _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; - break; - } - } - - if ( i == LogicalAddress::UNREGISTERED) - { - /*So there is no update required, try to ping after some seconds*/ - _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; - _instance->m_sleepTime = 0; - //LOGINFO("POLL_THREAD_STATE_INFO -> state change to Ping", i); - } - } - else - { - /*So there is request sent for logical address, so wait and check the status */ - if ( _instance->requestStatus(logicalAddressRequested) == CECDeviceParams::REQUEST_DONE ) - { - logicalAddressRequested = LogicalAddress::UNREGISTERED; - } - else - { - _instance->m_sleepTime = HDMICECSINK_REQUEST_INTERVAL_TIME_MS; - } - } - } - break; - - /* updating the power status and if required we can add other information later*/ - case POLL_THREAD_STATE_UPDATE : - { - //LOGINFO("POLL_THREAD_STATE_UPDATE"); - - for(int i=0;im_logicalAddressAllocated && - _instance->deviceList[i].m_isDevicePresent && - _instance->deviceList[i].m_isPowerStatusUpdated ) - { - std::chrono::duration elapsed = std::chrono::system_clock::now() - _instance->deviceList[i].m_lastPowerUpdateTime; - - if ( elapsed.count() > HDMICECSINK_UPDATE_POWER_STATUS_INTERVA_MS ) - { - _instance->deviceList[i].m_isPowerStatusUpdated = false; - _instance->m_pollNextState = POLL_THREAD_STATE_INFO; - _instance->m_sleepTime = 0; - } - } - } - - _instance->m_pollThreadState = POLL_THREAD_STATE_IDLE; - _instance->m_sleepTime = 0; - } - break; - - case POLL_THREAD_STATE_IDLE : - { - //LOGINFO("POLL_THREAD_STATE_IDLE"); - _instance->m_sleepTime = HDMICECSINK_PING_INTERVAL_MS; - _instance->m_pollThreadState = POLL_THREAD_STATE_PING; - } - break; - - case POLL_THREAD_STATE_WAIT : - { - /* Wait for Hdmi is connected, in case it disconnected */ - //LOGINFO("19Aug2020-[01] -> POLL_THREAD_STATE_WAIT"); - _instance->m_sleepTime = HDMICECSINK_WAIT_FOR_HDMI_IN_MS; - - if ( _instance->m_isHdmiInConnected == true ) - { - _instance->m_pollThreadState = POLL_THREAD_STATE_POLL; - } - } - break; - - case POLL_THREAD_STATE_EXIT : - { - isExit = true; - _instance->m_sleepTime = 0; - } - break; - } - - std::unique_lock lk(_instance->m_pollExitMutex); - if ( _instance->m_ThreadExitCV.wait_for(lk, std::chrono::milliseconds(_instance->m_sleepTime)) == std::cv_status::timeout ) - continue; - else - LOGINFO("Thread is going to Exit m_pollThreadExit %d\n", _instance->m_pollThreadExit ); - - } - } - - void HdmiCecSinkImplementation::allocateLAforTV() - { - bool gotLogicalAddress = false; - int addr = LogicalAddress::TV; - int i, j; - if (!(_instance->smConnection)) - return; - - for (i = 0; i< HDMICECSINK_NUMBER_TV_ADDR; i++) - { - /* poll for TV logical address - retry 5 times*/ - for (j = 0; j < 5; j++) - { - try { - smConnection->poll(LogicalAddress(addr), Throw_e()); - } - catch(CECNoAckException &e ) - { - LOGWARN("Poll caught %s \r\n",e.what()); - gotLogicalAddress = true; - break; - } - catch(Exception &e) - { - LOGWARN("Poll caught %s \r\n",e.what()); - usleep(250000); - } - } - if (gotLogicalAddress) - { - break; - } - addr = LogicalAddress::SPECIFIC_USE; - } - - if ( gotLogicalAddress ) - { - m_logicalAddressAllocated = addr; - } - else - { - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - } - - LOGWARN("Logical Address for TV 0x%x \r\n",m_logicalAddressAllocated); - } - - void HdmiCecSinkImplementation::allocateLogicalAddress(int deviceType) - { - if( deviceType == DeviceType::TV ) - { - allocateLAforTV(); - } - } - - void HdmiCecSinkImplementation::CECEnable(void) - { - std::lock_guard lock(m_enableMutex); - JsonObject params; - LOGINFO("Entered CECEnable"); - if (cecEnableStatus) - { - LOGWARN("CEC Already Enabled"); - return; - } - - if(0 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().init("HdmiCecSinkImplementation"); - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught in LibCCEC::init %s", e.what()); - } - catch(IOException &e){ - LOGWARN("IOException caught in LibCCEC::init %s", e.what()); - } - catch(...){ - LOGWARN("Exception caught in LibCCEC::init"); - } - } - libcecInitStatus++; - - //Acquire CEC Addresses - _instance->getPhysicalAddress(); - - smConnection = new Connection(LogicalAddress::UNREGISTERED,false,"ServiceManager::Connection::"); - smConnection->open(); - allocateLogicalAddress(DeviceType::TV); - LOGINFO("logical address allocalted: %x \n",m_logicalAddressAllocated); - if ( m_logicalAddressAllocated != LogicalAddress::UNREGISTERED && smConnection) - { - logicalAddress = LogicalAddress(m_logicalAddressAllocated); - LOGINFO(" add logical address %x \n",m_logicalAddressAllocated); - LibCCEC::getInstance().addLogicalAddress(logicalAddress); - smConnection->setSource(logicalAddress); - } - msgProcessor = new HdmiCecSinkProcessor(*smConnection); - msgFrameListener = new HdmiCecSinkFrameListener(*msgProcessor); - if(smConnection) - { - LOGWARN("Start Thread %p", smConnection ); - m_pollThreadState = POLL_THREAD_STATE_POLL; - m_pollNextState = POLL_THREAD_STATE_NONE; - m_pollThreadExit = false; - m_pollThread = std::thread(threadRun); - } - cecEnableStatus = true; - - params["cecEnable"] = string("true"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportCecEnabledEvent("true"); - index++; - } - - return; - } - - void HdmiCecSinkImplementation::CECDisable(void) - { - std::lock_guard lock(m_enableMutex); - JsonObject params; - LOGINFO("Entered CECDisable "); - if(!cecEnableStatus) - { - LOGWARN("CEC Already Disabled "); - return; - } - - if(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) - { - stopArc(); - while(m_currentArcRoutingState != ARC_STATE_ARC_TERMINATED) - { - usleep(500000); - } - } - - LOGINFO(" CECDisable ARC stopped "); - cecEnableStatus = false; - if (smConnection != NULL) - { - LOGWARN("Stop Thread %p", smConnection ); - m_pollThreadExit = true; - m_ThreadExitCV.notify_one(); - - try - { - if (m_pollThread.joinable()) - { - LOGWARN("Join Thread %p", smConnection ); - m_pollThread.join(); - } - } - catch(const std::system_error& e) - { - LOGERR("system_error exception in thread join %s", e.what()); - } - catch(const std::exception& e) - { - LOGERR("exception in thread join %s", e.what()); - } - - m_pollThreadState = POLL_THREAD_STATE_NONE; - m_pollNextState = POLL_THREAD_STATE_NONE; - - LOGWARN("Deleted Thread %p", smConnection ); - - smConnection->close(); - delete smConnection; - smConnection = NULL; - } - - m_logicalAddressAllocated = LogicalAddress::UNREGISTERED; - m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - if (m_audioStatusDetectionTimer.isActive()){ - m_audioStatusDetectionTimer.stop(); - } - m_isAudioStatusInfoUpdated = false; - m_audioStatusReceived = false; - m_audioStatusTimerStarted = false; - LOGINFO("CEC Disabled, reset the audio status info. m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - - for(int i=0; i< 16; i++) - { - if (_instance->deviceList[i].m_isDevicePresent) - { - _instance->deviceList[i].clear(); - } - } - - if(1 == libcecInitStatus) - { - try - { - LibCCEC::getInstance().term(); - } - catch(InvalidStateException &e){ - LOGWARN("InvalidStateException caught in LibCCEC::term %s", e.what()); - } - catch(IOException &e){ - LOGWARN("IOException caught in LibCCEC::term %s", e.what()); - } - catch(...){ - LOGWARN("Exception caught in LibCCEC::term"); - } - - libcecInitStatus--; - LOGWARN("CEC Disabled %d",libcecInitStatus); - - params["cecEnable"] = string("false"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ReportCecEnabledEvent("false"); - index++; - } - } - return; - } - - - void HdmiCecSinkImplementation::getPhysicalAddress() - { - LOGINFO("Entered getPhysicalAddress "); - - uint32_t physAddress = 0x0F0F0F0F; - - try { - LibCCEC::getInstance().getPhysicalAddress(&physAddress); - physical_addr = {(uint8_t)((physAddress >> 24) & 0xFF),(uint8_t)((physAddress >> 16) & 0xFF),(uint8_t) ((physAddress >> 8) & 0xFF),(uint8_t)((physAddress) & 0xFF)}; - LOGINFO("getPhysicalAddress: physicalAddress: %s ", physical_addr.toString().c_str()); - } - catch (const std::exception& e) - { - LOGWARN("exception caught from getPhysicalAddress"); - } - return; - } - - bool HdmiCecSinkImplementation::getEnabled() - { - - - LOGINFO("getEnabled :%d ",cecEnableStatus); - if(true == cecEnableStatus) - return true; - else - return false; - } - - bool HdmiCecSinkImplementation::getAudioDeviceConnectedStatus() - { - LOGINFO("getAudioDeviceConnectedStatus :%d ", hdmiCecAudioDeviceConnected); - if(true == hdmiCecAudioDeviceConnected) - return true; - else - return false; - } - //Arc Routing related functions - void HdmiCecSinkImplementation::startArc() - { - if ( cecEnableStatus != true ) - { - LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); - return; - } - if(!HdmiCecSinkImplementation::_instance) - return; - - LOGINFO("Current ARC State : %d\n", m_currentArcRoutingState); - - _instance->requestArcInitiation(); - - // start initiate ARC timer 3 sec - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - m_arcstarting = true; - m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); - - } - void HdmiCecSinkImplementation::requestArcInitiation() - { - { - std::lock_guard lock(m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_INITIATION; - } - LOGINFO("requestArcInitiation release sem"); - _instance->m_semSignaltoArcRoutingThread.release(); - - } - void HdmiCecSinkImplementation::stopArc() - { - if ( cecEnableStatus != true ) - { - LOGINFO("Initiate_Arc Cec is disabled-> EnableCEC first"); - return; - } - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - if(m_currentArcRoutingState == ARC_STATE_REQUEST_ARC_TERMINATION || m_currentArcRoutingState == ARC_STATE_ARC_TERMINATED) - { - LOGINFO("ARC is either Termination in progress or already Terminated"); - return; - } - - _instance->requestArcTermination(); - /* start a timer for 3 sec to get the desired ARC_STATE_ARC_TERMINATED */ - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - /* m_arcstarting = true means starting the ARC start timer ,false means ARC stopping timer*/ - m_arcstarting = false; - m_arcStartStopTimer.start((HDMISINK_ARC_START_STOP_MAX_WAIT_MS)); - - - } - void HdmiCecSinkImplementation::requestArcTermination() - { - { - std::lock_guard lock(m_arcRoutingStateMutex); - m_currentArcRoutingState = ARC_STATE_REQUEST_ARC_TERMINATION; - } - LOGINFO("requestArcTermination release sem"); - _instance->m_semSignaltoArcRoutingThread.release(); - - } - - void HdmiCecSinkImplementation::Process_InitiateArc() - { - JsonObject params; - - LOGINFO("Command: INITIATE_ARC \n"); - - if(!HdmiCecSinkImplementation::_instance) - return; - - //DD: Check cecSettingEnabled to prevent race conditions which gives immediate UI setting status - //Initiate ARC message may come from AVR/Soundbar while CEC disable is in-progress - if ( cecSettingEnabled != true ) - { - LOGINFO("Process InitiateArc from Audio device: Cec is disabled-> EnableCEC first"); - return; - } - - LOGINFO("Got : INITIATE_ARC and current Arcstate is %d\n",_instance->m_currentArcRoutingState); - - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - if (powerState == DEVICE_POWER_STATE_ON ) { - LOGINFO("Notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - _instance->m_currentArcRoutingState = ARC_STATE_ARC_INITIATED; - - _instance->m_semSignaltoArcRoutingThread.release(); - LOGINFO("Got : ARC_INITIATED and notify Device setting"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcInitiationEvent("success"); - index++; - } - } else { - LOGINFO("Not notifying Arc Initiation event as power state is %s", powerState ? "Off" : "On"); - } - - } - void HdmiCecSinkImplementation::Process_TerminateArc() - { - JsonObject params; - - LOGINFO("Command: TERMINATE_ARC current arc state %d \n",HdmiCecSinkImplementation::_instance->m_currentArcRoutingState); - if (m_arcStartStopTimer.isActive()) - { - m_arcStartStopTimer.stop(); - } - std::lock_guard lock(m_arcRoutingStateMutex); - HdmiCecSinkImplementation::_instance->m_currentArcRoutingState = ARC_STATE_ARC_TERMINATED; - _instance->m_semSignaltoArcRoutingThread.release(); - - // trigger callback to Device setting informing to TERMINATE_ARC - LOGINFO("Got : ARC_TERMINATED and notify Device setting"); - std::list::const_iterator index(_hdmiCecSinkNotifications.begin()); - while (index != _hdmiCecSinkNotifications.end()) { - (*index)->ArcTerminationEvent("success"); - index++; - } - } - - void HdmiCecSinkImplementation::threadSendKeyEvent() - { - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - SendKeyInfo keyInfo = {-1,-1}; - - while(!_instance->m_sendKeyEventThreadExit) - { - keyInfo.logicalAddr = -1; - keyInfo.keyCode = -1; - { - // Wait for a message to be added to the queue - std::unique_lock lk(_instance->m_sendKeyEventMutex); - _instance->m_sendKeyCV.wait(lk, []{return (_instance->m_sendKeyEventThreadRun == true);}); - } - - if (_instance->m_sendKeyEventThreadExit == true) - { - LOGINFO(" threadSendKeyEvent Exiting"); - _instance->m_sendKeyEventThreadRun = false; - break; - } - - if (_instance->m_SendKeyQueue.empty()) { - _instance->m_sendKeyEventThreadRun = false; - continue; - } - - keyInfo = _instance->m_SendKeyQueue.front(); - _instance->m_SendKeyQueue.pop(); - - if(keyInfo.UserControl == "sendUserControlPressed" ) - { - LOGINFO("sendUserControlPressed : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); - _instance->sendUserControlPressed(keyInfo.logicalAddr,keyInfo.keyCode); - } - else if(keyInfo.UserControl == "sendUserControlReleased") - { - LOGINFO("sendUserControlReleased : logical addr:0x%x queue size :%zu \n",keyInfo.logicalAddr,_instance->m_SendKeyQueue.size()); - _instance->sendUserControlReleased(keyInfo.logicalAddr); - } - else - { - LOGINFO("sendKeyPressEvent : logical addr:0x%x keyCode: 0x%x queue size :%zu \n",keyInfo.logicalAddr,keyInfo.keyCode,_instance->m_SendKeyQueue.size()); - _instance->sendKeyPressEvent(keyInfo.logicalAddr,keyInfo.keyCode); - _instance->sendKeyReleaseEvent(keyInfo.logicalAddr); - } - - if((_instance->m_SendKeyQueue.size()<=1 || (_instance->m_SendKeyQueue.size() % 2 == 0)) && ((keyInfo.keyCode == VOLUME_UP) || (keyInfo.keyCode == VOLUME_DOWN) || (keyInfo.keyCode == MUTE)) ) - { - if(keyInfo.keyCode == MUTE) - { - _instance->sendGiveAudioStatusMsg(); - } - else - { - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ",_instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); - if (!_instance->m_isAudioStatusInfoUpdated) - { - if ( !(_instance->m_audioStatusDetectionTimer.isActive())) - { - LOGINFO("Audio status info not updated. Starting the Timer!"); - _instance->m_audioStatusTimerStarted = true; - _instance->m_audioStatusDetectionTimer.start((HDMICECSINK_UPDATE_AUDIO_STATUS_INTERVAL_MS)); - } - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", _instance->m_isAudioStatusInfoUpdated,_instance->m_audioStatusReceived,_instance->m_audioStatusTimerStarted); - } - else - { - if (!_instance->m_audioStatusReceived){ - _instance->sendGiveAudioStatusMsg(); - } - } - } - } - }//while(!_instance->m_sendKeyEventThreadExit) - }//threadSendKeyEvent - - void HdmiCecSinkImplementation::audioStatusTimerFunction() - { - m_audioStatusTimerStarted = false; - m_isAudioStatusInfoUpdated = true; - LOGINFO("Timer Expired. Requesting the AudioStatus since not received.\n"); - sendGiveAudioStatusMsg(); - LOGINFO("m_isAudioStatusInfoUpdated :%d, m_audioStatusReceived :%d, m_audioStatusTimerStarted:%d ", m_isAudioStatusInfoUpdated,m_audioStatusReceived,m_audioStatusTimerStarted); - } - - - void HdmiCecSinkImplementation::threadArcRouting() - { - bool isExit = false; - uint32_t currentArcRoutingState; - - if(!HdmiCecSinkImplementation::_instance) - { - return; - } - - LOGINFO("Running threadArcRouting"); - _instance->getHdmiArcPortID(); - - while(1) - { - - _instance->m_semSignaltoArcRoutingThread.acquire(); - - - - { - LOGINFO(" threadArcRouting Got semaphore"); - std::lock_guard lock(_instance->m_arcRoutingStateMutex); - - currentArcRoutingState = _instance->m_currentArcRoutingState; - - LOGINFO(" threadArcRouting Got Sem arc state %d",currentArcRoutingState); - } - - switch (currentArcRoutingState) - { - - case ARC_STATE_REQUEST_ARC_INITIATION : - { - - _instance->systemAudioModeRequest(); - _instance->Send_Request_Arc_Initiation_Message(); - - } - break; - case ARC_STATE_ARC_INITIATED : - { - _instance->Send_Report_Arc_Initiated_Message(); - } - break; - case ARC_STATE_REQUEST_ARC_TERMINATION : - { - - _instance->Send_Request_Arc_Termination_Message(); - - } - break; - case ARC_STATE_ARC_TERMINATED : - { - _instance->Send_Report_Arc_Terminated_Message(); - } - break; - case ARC_STATE_ARC_EXIT : - { - isExit = true; - } - break; - } - - if (isExit == true) - { - LOGINFO(" threadArcRouting EXITing"); - break; - } - }//while(1) - }//threadArcRouting - - void HdmiCecSinkImplementation::Send_Request_Arc_Initiation_Message() - { - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - LOGINFO(" Send_Request_Arc_Initiation_Message "); - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcInitiation()), 1000); - - } - void HdmiCecSinkImplementation::Send_Report_Arc_Initiated_Message() - { - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcInitiation()), 1000); - - } - void HdmiCecSinkImplementation::Send_Request_Arc_Termination_Message() - { - - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(RequestArcTermination()), 1000); - } - - void HdmiCecSinkImplementation::Send_Report_Arc_Terminated_Message() - { - if(!HdmiCecSinkImplementation::_instance) - return; - if(!(_instance->smConnection)) - return; - _instance->smConnection->sendTo(LogicalAddress::AUDIO_SYSTEM,MessageEncoder().encode(ReportArcTermination()), 1000); - - } - - void HdmiCecSinkImplementation::getHdmiArcPortID() - { - int err; - dsGetHDMIARCPortIdParam_t param; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, - (void *)¶m, - sizeof(param)); - if (IARM_RESULT_SUCCESS == err) - { - LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); - HdmiArcPortID = param.portId; - } - } - - void HdmiCecSinkImplementation::getCecVersion() - { - RFC_ParamData_t param = {0}; - WDMP_STATUS status = getRFCParameter((char*)"thunderapi", TR181_HDMICECSINK_CEC_VERSION, ¶m); - if(WDMP_SUCCESS == status && param.type == WDMP_STRING) { - LOGINFO("CEC Version from RFC = [%s] \n", param.value); - cecVersion = atof(param.value); - } - else { - LOGINFO("Error while fetching CEC Version from RFC "); - } - } - - } // namespace Plugin -} // namespace WPEFrameworklk diff --git a/HdmiCecSink/HdmiCecSinkImplementation.h b/HdmiCecSink/HdmiCecSinkImplementation.h deleted file mode 100644 index c9d91c11..00000000 --- a/HdmiCecSink/HdmiCecSinkImplementation.h +++ /dev/null @@ -1,755 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#pragma once - -#include -#include "ccec/FrameListener.hpp" -#include "ccec/Connection.hpp" - -#include "libIARM.h" -#include "ccec/Assert.hpp" -#include "ccec/Messages.hpp" -#include "ccec/MessageDecoder.hpp" -#include "ccec/MessageProcessor.hpp" - -#undef Assert // this define from Connection.hpp conflicts with WPEFramework - -#include "Module.h" -#include "tptimer.h" -#include -#include -#include -#include - -#include "UtilsLogging.h" -#include -#include "PowerManagerInterface.h" -#include - -using namespace WPEFramework; -using PowerState = WPEFramework::Exchange::IPowerManager::PowerState; -using ThermalTemperature = WPEFramework::Exchange::IPowerManager::ThermalTemperature; - - -namespace WPEFramework { - - namespace Plugin { - class HdmiCecSinkFrameListener : public FrameListener - { - public: - HdmiCecSinkFrameListener(MessageProcessor &processor) : processor(processor) {} - void notify(const CECFrame &in) const; - ~HdmiCecSinkFrameListener() {} - private: - MessageProcessor &processor; - }; - - class HdmiCecSinkProcessor : public MessageProcessor - { - public: - HdmiCecSinkProcessor(Connection &conn) : conn(conn) {} - void process (const ActiveSource &msg, const Header &header); - void process (const InActiveSource &msg, const Header &header); - void process (const ImageViewOn &msg, const Header &header); - void process (const TextViewOn &msg, const Header &header); - void process (const RequestActiveSourceMessage &msg, const Header &header); - void process (const Standby &msg, const Header &header); - void process (const GetCECVersion &msg, const Header &header); - void process (const CECVersion &msg, const Header &header); - void process (const SetMenuLanguageMessage &msg, const Header &header); - void process (const GiveOSDName &msg, const Header &header); - void process (const GivePhysicalAddress &msg, const Header &header); - void process (const GiveDeviceVendorID &msg, const Header &header); - void process (const SetOSDString &msg, const Header &header); - void process (const SetOSDName &msg, const Header &header); - void process (const RoutingChange &msg, const Header &header); - void process (const RoutingInformation &msg, const Header &header); - void process (const SetStreamPath &msg, const Header &header); - void process (const GetMenuLanguage &msg, const Header &header); - void process (const ReportPhysicalAddress &msg, const Header &header); - void process (const DeviceVendorID &msg, const Header &header); - void process (const GiveDevicePowerStatus &msg, const Header &header); - void process (const ReportPowerStatus &msg, const Header &header); - void process (const FeatureAbort &msg, const Header &header); - void process (const Abort &msg, const Header &header); - void process (const Polling &msg, const Header &header); - void process (const InitiateArc &msg, const Header &header); - void process (const TerminateArc &msg, const Header &header); - void process (const ReportShortAudioDescriptor &msg, const Header &header); - void process (const SetSystemAudioMode &msg, const Header &header); - void process (const ReportAudioStatus &msg, const Header &header); - void process (const GiveFeatures &msg, const Header &header); - void process (const RequestCurrentLatency &msg, const Header &header); - private: - Connection conn; - void printHeader(const Header &header) - { - printf("Header : From : %s \n", header.from.toString().c_str()); - printf("Header : to : %s \n", header.to.toString().c_str()); - } - - }; - - class CECDeviceParams { - public: - - enum { - REQUEST_NONE = 0, - REQUEST_PHISICAL_ADDRESS = 1, - REQUEST_CEC_VERSION, - REQUEST_DEVICE_VENDOR_ID, - REQUEST_POWER_STATUS, - REQUEST_OSD_NAME, - }; - - enum { - REQUEST_DONE = 0, - REQUEST_NOT_DONE, - REQUEST_TIME_ELAPSED, - }; - - DeviceType m_deviceType; - LogicalAddress m_logicalAddress; - PhysicalAddress m_physicalAddr; - Version m_cecVersion; - VendorID m_vendorID; - OSDName m_osdName; - PowerStatus m_powerStatus; - bool m_isDevicePresent; - bool m_isDeviceDisconnected; - Language m_currentLanguage; - bool m_isActiveSource; - bool m_isDeviceTypeUpdated; - bool m_isPAUpdated; - bool m_isVersionUpdated; - bool m_isOSDNameUpdated; - bool m_isVendorIDUpdated; - bool m_isPowerStatusUpdated; - int m_isRequested; - int m_isRequestRetry; - std::chrono::system_clock::time_point m_requestTime; - std::vector m_featureAborts; - std::chrono::system_clock::time_point m_lastPowerUpdateTime; - - CECDeviceParams() - : m_deviceType(0), m_logicalAddress(0),m_physicalAddr(0x0f,0x0f,0x0f,0x0f),m_cecVersion(0),m_vendorID(0,0,0),m_osdName(""),m_powerStatus(0),m_currentLanguage("") - { - m_isDevicePresent = false; - m_isActiveSource = false; - m_isPAUpdated = false; - m_isVersionUpdated = false; - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - m_isPowerStatusUpdated = false; - m_isDeviceDisconnected = false; - m_isDeviceTypeUpdated = false; - m_isRequestRetry = 0; - } - - void clear( ) - { - m_deviceType = 0; - m_logicalAddress = 0; - m_physicalAddr = PhysicalAddress(0x0f,0x0f,0x0f,0x0f); - m_cecVersion = 0; - m_vendorID = VendorID(0,0,0); - m_osdName = ""; - m_powerStatus = 0; - m_currentLanguage = ""; - m_isDevicePresent = false; - m_isActiveSource = false; - m_isPAUpdated = false; - m_isVersionUpdated = false; - m_isOSDNameUpdated = false; - m_isVendorIDUpdated = false; - m_isPowerStatusUpdated = false; - m_isDeviceDisconnected = false; - m_isDeviceTypeUpdated = false; - } - - void printVariable() - { - LOGWARN("Device LogicalAddress %s", m_logicalAddress.toString().c_str()); - LOGWARN("Device Type %s", m_deviceType.toString().c_str()); - LOGWARN("Device Present %d", m_isDevicePresent); - LOGWARN("Active Source %d", m_isActiveSource); - LOGWARN("PA Updated %d", m_isPAUpdated); - LOGWARN("Version Updated %d", m_isVersionUpdated); - LOGWARN("OSDName Updated %d", m_isOSDNameUpdated); - LOGWARN("PowerStatus Updated %d", m_isPowerStatusUpdated); - LOGWARN("VendorID Updated %d", m_isPowerStatusUpdated); - LOGWARN("CEC Version : %s", m_cecVersion.toString().c_str()); - LOGWARN("Vendor ID : %s", m_vendorID.toString().c_str()); - LOGWARN("PhisicalAddress : %s", m_physicalAddr.toString().c_str()); - LOGWARN("OSDName : %s", m_osdName.toString().c_str()); - LOGWARN("Power Status : %s", m_powerStatus.toString().c_str()); - LOGWARN("Language : %s", m_currentLanguage.toString().c_str()); - } - - bool isAllUpdated() { - if( !m_isPAUpdated - || !m_isVersionUpdated - || !m_isOSDNameUpdated - || !m_isVendorIDUpdated - || !m_isPowerStatusUpdated - || !m_isDeviceTypeUpdated ){ - return false; - } - return true; - } - - void update( const DeviceType &deviceType ) { - m_deviceType = deviceType; - m_isDeviceTypeUpdated = true; - } - - void update( const PhysicalAddress &physical_addr ) { - m_physicalAddr = physical_addr; - m_isPAUpdated = true; - } - - void update ( const VendorID &vendorId) { - m_vendorID = vendorId; - m_isVendorIDUpdated = true; - } - - void update ( const Version &version ) { - m_cecVersion = version; - m_isVersionUpdated = true; - } - - void update ( const OSDName &osdName ) { - m_osdName = osdName; - m_isOSDNameUpdated = true; - } - - void update ( const PowerStatus &status ) { - m_powerStatus = status; - m_isPowerStatusUpdated = true; - m_lastPowerUpdateTime = std::chrono::system_clock::now(); - } - }; - - class DeviceNode { - public: - uint8_t m_childsLogicalAddr[LogicalAddress::UNREGISTERED]; - - DeviceNode() { - int i; - for (i = 0; i < LogicalAddress::UNREGISTERED; i++ ) - { - m_childsLogicalAddr[i] = LogicalAddress::UNREGISTERED; - } - } - - } ; - typedef struct sendKeyInfo - { - int logicalAddr; - int keyCode; - string UserControl; - }SendKeyInfo; - - class HdmiPortMap { - public: - uint8_t m_portID; - bool m_isConnected; - LogicalAddress m_logicalAddr; - PhysicalAddress m_physicalAddr; - DeviceNode m_deviceChain[3]; - - HdmiPortMap(uint8_t portID) : m_portID(portID), - m_logicalAddr(LogicalAddress::UNREGISTERED), - m_physicalAddr(portID+1,0,0,0) - { - m_isConnected = false; - } - - void update(bool isConnected) - { - m_isConnected = isConnected; - } - - void update( const LogicalAddress &addr ) - { - m_logicalAddr = addr; - } - - void addChild( const LogicalAddress &logical_addr, const PhysicalAddress &physical_addr ) - { - LOGINFO(" logicalAddr = %d, phisicalAddr = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); - - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED && - m_logicalAddr.toInt() != logical_addr.toInt() ) - { - LOGINFO(" update own logicalAddr = %d, new devcie logicalAddress = %d", m_logicalAddr.toInt(), logical_addr.toInt() ); - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = logical_addr.toInt(); - } - else if ( physical_addr.getByteValue(2) != 0 ) - { - m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = logical_addr.toInt(); - } - else if ( physical_addr.getByteValue(1) != 0 ) - { - m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = logical_addr.toInt(); - } - } - } - else if ( physical_addr == m_physicalAddr ) - { - update(logical_addr); - LOGINFO(" update own logicalAddr = %d", m_logicalAddr.toInt()); - } - } - - void removeChild( PhysicalAddress &physical_addr ) - { - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) - { - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1] = LogicalAddress::UNREGISTERED; - } - else if ( physical_addr.getByteValue(2) != 0 ) - { - m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1] = LogicalAddress::UNREGISTERED; - } - else if ( physical_addr.getByteValue(1) != 0 ) - { - m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1] = LogicalAddress::UNREGISTERED; - } - } - } - } - - void getRoute( PhysicalAddress &physical_addr, std::vector & route ) - { - LOGINFO(" logicalAddr = %d, phsical = %s", m_logicalAddr.toInt(), physical_addr.toString().c_str()); - - if ( m_logicalAddr.toInt() != LogicalAddress::UNREGISTERED ) - { - LOGINFO(" search for logicalAddr = %d", m_logicalAddr.toInt()); - /* check matching with this port's physical address */ - if( physical_addr.getByteValue(0) == m_physicalAddr.getByteValue(0) && - physical_addr.getByteValue(1) != 0 ) - { - if ( physical_addr.getByteValue(3) != 0 ) - { - route.push_back(m_deviceChain[2].m_childsLogicalAddr[physical_addr.getByteValue(3) - 1]); - } - - if ( physical_addr.getByteValue(2) != 0 ) - { - route.push_back(m_deviceChain[1].m_childsLogicalAddr[physical_addr.getByteValue(2) - 1]); - } - - if ( physical_addr.getByteValue(1) != 0 ) - { - route.push_back(m_deviceChain[0].m_childsLogicalAddr[physical_addr.getByteValue(1) - 1]); - } - - route.push_back(m_logicalAddr.toInt()); - } - else - { - route.push_back(m_logicalAddr.toInt()); - LOGINFO("logicalAddr = %d, physical = %s", m_logicalAddr.toInt(), m_physicalAddr.toString().c_str()); - } - } - } - }; - - class binary_semaphore { - - public: - - explicit binary_semaphore(int init_count = count_max) - - : count_(init_count) {} - - - - // P-operation / acquire - - void wait() - - { - - std::unique_lock lk(m_); - - cv_.wait(lk, [=]{ return 0 < count_; }); - - --count_; - - } - - bool try_wait() - - { - - std::lock_guard lk(m_); - - if (0 < count_) { - - --count_; - - return true; - - } else { - - return false; - - } - - } - - // V-operation / release - - void signal() - - { - - std::lock_guard lk(m_); - - if (count_ < count_max) { - - ++count_; - - cv_.notify_one(); - - } - - } - - - - // Lockable requirements - - void acquire() { wait(); } - - bool try_lock() { return try_wait(); } - - void release() { signal(); } - - - -private: - - static const int count_max = 1; - - int count_; - - std::mutex m_; - - std::condition_variable cv_; - -}; - // This is a server for a JSONRPC communication channel. - // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. - // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. - // This realization of this interface implements, by default, the following methods on this plugin - // - exists - // - register - // - unregister - // Any other methood to be handled by this plugin can be added can be added by using the - // templated methods Register on the PluginHost::JSONRPC class. - // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, - // this class exposes a public method called, Notify(), using this methods, all subscribed clients - // will receive a JSONRPC message as a notification, in case this method is called. - class HdmiCecSinkImplementation : public Exchange::IHdmiCecSink { - - enum { - POLL_THREAD_STATE_NONE, - POLL_THREAD_STATE_IDLE, - POLL_THREAD_STATE_POLL, - POLL_THREAD_STATE_PING, - POLL_THREAD_STATE_INFO, - POLL_THREAD_STATE_WAIT, - POLL_THREAD_STATE_CLEAN, - POLL_THREAD_STATE_UPDATE, - POLL_THREAD_STATE_EXIT, - }; - enum { - ARC_STATE_REQUEST_ARC_INITIATION, - ARC_STATE_ARC_INITIATED, - ARC_STATE_REQUEST_ARC_TERMINATION, - ARC_STATE_ARC_TERMINATED, - ARC_STATE_ARC_EXIT - }; - enum { - VOLUME_UP = 0x41, - VOLUME_DOWN = 0x42, - MUTE = 0x43, - UP = 0x01, - DOWN = 0x02, - LEFT = 0x03, - RIGHT = 0x04, - SELECT = 0x00, - HOME = 0x09, - BACK = 0x0D, - NUMBER_0 = 0x20, - NUMBER_1 = 0x21, - NUMBER_2 = 0x22, - NUMBER_3 = 0x23, - NUMBER_4 = 0x24, - NUMBER_5 = 0x25, - NUMBER_6 = 0x26, - NUMBER_7 = 0x27, - NUMBER_8 = 0x28, - NUMBER_9 = 0x29 - }; - public: - HdmiCecSinkImplementation(); - virtual ~HdmiCecSinkImplementation(); - static HdmiCecSinkImplementation* _instance; - CECDeviceParams deviceList[16]; - std::vector hdmiInputs; - int m_currentActiveSource; - void updateInActiveSource(const int logical_address, const InActiveSource &source ); - void updateActiveSource(const int logical_address, const ActiveSource &source ); - void updateTextViewOn(const int logicalAddress); - void updateImageViewOn(const int logicalAddress); - void updateDeviceChain(const LogicalAddress &logicalAddress, const PhysicalAddress &phy_addr); - void getActiveRoute(const LogicalAddress &logicalAddress, std::vector &route); - void removeDevice(const int logicalAddress); - void addDevice(const int logicalAddress); - void printDeviceList(); - void setStreamPath( const PhysicalAddress &physical_addr); - void setRoutingChange(const std::string &from, const std::string &to); - void sendStandbyMessage(); - void setCurrentLanguage(const Language &lang); - void sendMenuLanguage(); - void setActiveSource(bool isResponse); - void requestActiveSource(); - void startArc(); - void stopArc(); - void Process_InitiateArc(); - void Process_TerminateArc(); - void updateArcState(); - void requestShortaudioDescriptor(); - void Send_ShortAudioDescriptor_Event(JsonArray audiodescriptor); - void Process_ShortAudioDescriptor_msg(const ReportShortAudioDescriptor &msg); - void Process_SetSystemAudioMode_msg(const SetSystemAudioMode &msg); - void sendDeviceUpdateInfo(const int logicalAddress); - void sendFeatureAbort(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); - void reportFeatureAbortEvent(const LogicalAddress logicalAddress, const OpCode feature, const AbortReason reason); - void systemAudioModeRequest(); - void SendStandbyMsgEvent(const int logicalAddress); - void requestAudioDevicePowerStatus(); - void reportAudioDevicePowerStatusInfo(const int logicalAddress, const int powerStatus); - void updateCurrentLatency(int videoLatency, bool lowLatencyMode, int audioOutputCompensated, int audioOutputDelay); - void setLatencyInfo(); - void Process_ReportAudioStatus_msg(const ReportAudioStatus msg); - void sendKeyPressEvent(const int logicalAddress, int keyCode); - void sendKeyReleaseEvent(const int logicalAddress); - void sendUserControlPressed(const int logicalAddress, int keyCode); - void sendUserControlReleased(const int logicalAddress); - void sendGiveAudioStatusMsg(); - void onPowerModeChanged(const PowerState ¤tState, const PowerState &newState); - void registerEventHandlers(); - void getHdmiArcPortID(); - int m_numberOfDevices; /* Number of connected devices othethan own device */ - bool m_audioDevicePowerStatusRequested; - - BEGIN_INTERFACE_MAP(HdmiCecSinkImplementation) - INTERFACE_ENTRY(Exchange::IHdmiCecSink) - END_INTERFACE_MAP - - private: - class PowerManagerNotification : public Exchange::IPowerManager::IModeChangedNotification { - private: - PowerManagerNotification(const PowerManagerNotification&) = delete; - PowerManagerNotification& operator=(const PowerManagerNotification&) = delete; - - public: - explicit PowerManagerNotification(HdmiCecSinkImplementation& parent) - : _parent(parent) - { - } - ~PowerManagerNotification() override = default; - - public: - void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override - { - _parent.onPowerModeChanged(currentState, newState); - } - - template - T* baseInterface() - { - static_assert(std::is_base_of(), "base type mismatch"); - return static_cast(this); - } - - BEGIN_INTERFACE_MAP(PowerManagerNotification) - INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification) - END_INTERFACE_MAP - - private: - HdmiCecSinkImplementation& _parent; - - }; - // We do not allow this plugin to be copied !! - HdmiCecSinkImplementation(const HdmiCecSinkImplementation&) = delete; - HdmiCecSinkImplementation& operator=(const HdmiCecSinkImplementation&) = delete; - //Begin methods - void InitializePowerManager(PluginHost::IShell *service); - //End methods - std::string logicalAddressDeviceType; - bool cecSettingEnabled; - bool cecOTPSettingEnabled; - bool cecEnableStatus; - bool hdmiCecAudioDeviceConnected; - bool m_isHdmiInConnected; - int m_numofHdmiInput; - uint8_t m_deviceType; - int m_logicalAddressAllocated; - std::thread m_pollThread; - uint32_t m_pollThreadState; - uint32_t m_pollNextState; - bool m_pollThreadExit; - uint32_t m_sleepTime; - std::mutex m_pollExitMutex; - std::mutex m_enableMutex; - /* Send Key event related */ - bool m_sendKeyEventThreadExit; - bool m_sendKeyEventThreadRun; - bool m_isAudioStatusInfoUpdated; - bool m_audioStatusReceived; - bool m_audioStatusTimerStarted; - std::thread m_sendKeyEventThread; - std::mutex m_sendKeyEventMutex; - std::queue m_SendKeyQueue; - std::condition_variable m_sendKeyCV; - std::condition_variable m_ThreadExitCV; - - /* DALS - Latency Values */ - uint8_t m_video_latency; - uint8_t m_latency_flags; - uint8_t m_audio_output_delay; - - /* ARC related */ - std::thread m_arcRoutingThread; - uint32_t m_currentArcRoutingState; - std::mutex m_arcRoutingStateMutex; - binary_semaphore m_semSignaltoArcRoutingThread; - bool m_arcstarting; - TpTimer m_arcStartStopTimer; - TpTimer m_audioStatusDetectionTimer; - - Connection *smConnection; - std::vector m_connectedDevices; - HdmiCecSinkProcessor *msgProcessor; - HdmiCecSinkFrameListener *msgFrameListener; - PowerManagerInterfaceRef _powerManagerPlugin; - Core::Sink _pwrMgrNotification; - bool _registeredEventHandlers; - const void InitializeIARM(); - void DeinitializeIARM(); - void allocateLogicalAddress(int deviceType); - void allocateLAforTV(); - void pingDevices(std::vector &connected , std::vector &disconnected); - void CheckHdmiInState(); - void request(const int logicalAddress); - int requestType(const int logicalAddress); - int requestStatus(const int logicalAddress); - static void threadRun(); - void cecMonitoringThread(); - static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - void onHdmiHotPlug(int portId, int connectStatus); - bool loadSettings(); - void persistSettings(bool enableStatus); - void persistOTPSettings(bool enableStatus); - void persistOSDName(const char *name); - void persistVendorId(unsigned int vendorID); - void setEnabled(bool enabled); - bool getEnabled(); - bool getAudioDeviceConnectedStatus(); - void CECEnable(void); - void CECDisable(void); - void getPhysicalAddress(); - void getLogicalAddress(); - void cecAddressesChanged(int changeStatus); - - // Arc functions - - static void threadSendKeyEvent(); - static void threadArcRouting(); - void requestArcInitiation(); - void requestArcTermination(); - void Send_Request_Arc_Initiation_Message(); - void Send_Report_Arc_Initiated_Message(); - void Send_Request_Arc_Termination_Message(); - void Send_Report_Arc_Terminated_Message(); - void arcStartStopTimerFunction(); - void audioStatusTimerFunction(); - void getCecVersion(); - - - public: - Core::hresult GetActiveRoute(bool &available, uint8_t &length, IHdmiCecSinkActivePathIterator*& pathList, string &ActiveRoute, bool &success) override; - Core::hresult GetActiveSource(bool &available, uint8_t &logicalAddress, string &physicalAddress, string &deviceType, string &cecVersion, string &osdName, string &vendorID, string &powerStatus, string &port, bool &success) override; - Core::hresult GetAudioDeviceConnectedStatus(bool &connected, bool &success) override; - Core::hresult GetDeviceList(uint32_t &numberofdevices, IHdmiCecSinkDeviceListIterator*& deviceList, bool &success) override; - Core::hresult GetEnabled(bool &enabled, bool &success) override; - Core::hresult GetOSDName(string &name, bool &success) override; - Core::hresult GetVendorId(string &vendorid, bool &success) override; - Core::hresult PrintDeviceList(bool &printed, bool &success) override; - Core::hresult RequestActiveSource(HdmiCecSinkSuccess &success) override; - Core::hresult RequestShortAudioDescriptor(HdmiCecSinkSuccess &success) override; - Core::hresult SendAudioDevicePowerOnMessage(HdmiCecSinkSuccess &success) override; - Core::hresult SendGetAudioStatusMessage(HdmiCecSinkSuccess &success) override; - Core::hresult SendKeyPressEvent(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) override; - Core::hresult SendUserControlPressed(const uint32_t &logicalAddress, const uint32_t &keyCode, HdmiCecSinkSuccess &success) override; - Core::hresult SendUserControlReleased(const uint32_t &logicalAddress, HdmiCecSinkSuccess &success) override; - Core::hresult SendStandbyMessage(HdmiCecSinkSuccess &success) override; - Core::hresult SetActivePath(const string &activePath, HdmiCecSinkSuccess &success) override; - Core::hresult SetActiveSource(HdmiCecSinkSuccess &success) override; - Core::hresult SetEnabled(const bool &enabled, HdmiCecSinkSuccess &success) override; - Core::hresult SetOSDName(const string &name, HdmiCecSinkSuccess &success) override; - Core::hresult SetRoutingChange(const string &oldPort, const string &newPort, HdmiCecSinkSuccess &success) override; - Core::hresult SetupARCRouting(const bool &enabled, HdmiCecSinkSuccess &success) override; - Core::hresult SetVendorId(const string &vendorId, HdmiCecSinkSuccess &success) override; - Core::hresult SetLatencyInfo(const string &videoLatency, const string &lowLatencyMode, const string &audioOutputCompensated, const string &audioOutputDelay, HdmiCecSinkSuccess &success) override; - Core::hresult Configure(PluginHost::IShell* service) override; - Core::hresult Register(Exchange::IHdmiCecSink::INotification *notification) override; - Core::hresult Unregister(Exchange::IHdmiCecSink::INotification *notification) override; - Core::hresult SetMenuLanguage(const string &language, HdmiCecSinkSuccess &success) override; - - private: - std::list _hdmiCecSinkNotifications; - mutable Core::CriticalSection _adminLock; - }; - } // namespace Plugin -} // namespace WPEFramework - - - - diff --git a/HdmiCecSource/HdmiCecSourceImplementation.cpp b/HdmiCecSource/HdmiCecSourceImplementation.cpp index 1086f6ac..4a4e3e64 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.cpp +++ b/HdmiCecSource/HdmiCecSourceImplementation.cpp @@ -135,7 +135,7 @@ namespace WPEFramework LOGINFO("Command: TextViewOn\n"); HdmiCecSourceImplementation::_instance->addDevice(header.from.toInt()); } - void HdmiCecSourceProcessor::process (const RequestActiveSourceMessage &msg, const Header &header) + void HdmiCecSourceProcessor::process (const RequestActiveSource &msg, const Header &header) { printHeader(header); LOGINFO("Command: RequestActiveSource\n"); @@ -178,7 +178,7 @@ namespace WPEFramework LOGINFO("Command: CECVersion Version : %s \n",msg.version.toString().c_str()); HdmiCecSourceImplementation::_instance->addDevice(header.from.toInt()); } - void HdmiCecSourceProcessor::process (const SetMenuLanguageMessage &msg, const Header &header) + void HdmiCecSourceProcessor::process (const SetMenuLanguage &msg, const Header &header) { printHeader(header); LOGINFO("Command: SetMenuLanguage Language : %s \n",msg.language.toString().c_str()); @@ -1031,7 +1031,7 @@ namespace WPEFramework LOGINFO("Command: sending GiveDevicePowerStatus \r\n"); smConnection->sendTo(LogicalAddress::TV, MessageEncoder().encode(GiveDevicePowerStatus())); LOGINFO("Command: sending request active Source isDeviceActiveSource is set to false\r\n"); - smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(RequestActiveSourceMessage())); + smConnection->sendTo(LogicalAddress::BROADCAST, MessageEncoder().encode(RequestActiveSource())); isDeviceActiveSource = false; LOGINFO("Command: GiveDeviceVendorID sending VendorID response :%s\n", \ (isLGTvConnected)?lgVendorId.toString().c_str():appVendorId.toString().c_str()); diff --git a/HdmiCecSource/HdmiCecSourceImplementation.h b/HdmiCecSource/HdmiCecSourceImplementation.h index d0494a18..6239dab5 100644 --- a/HdmiCecSource/HdmiCecSourceImplementation.h +++ b/HdmiCecSource/HdmiCecSourceImplementation.h @@ -68,11 +68,11 @@ namespace WPEFramework { void process (const InActiveSource &msg, const Header &header); void process (const ImageViewOn &msg, const Header &header); void process (const TextViewOn &msg, const Header &header); - void process (const RequestActiveSourceMessage &msg, const Header &header); + void process (const RequestActiveSource &msg, const Header &header); void process (const Standby &msg, const Header &header); void process (const GetCECVersion &msg, const Header &header); void process (const CECVersion &msg, const Header &header); - void process (const SetMenuLanguageMessage &msg, const Header &header); + void process (const SetMenuLanguage &msg, const Header &header); void process (const GiveOSDName &msg, const Header &header); void process (const GivePhysicalAddress &msg, const Header &header); void process (const GiveDeviceVendorID &msg, const Header &header); diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index acab058e..ead1b3c2 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -115,8 +115,7 @@ add_plugin_test_ex(PLUGIN_HDMICEC2 tests/test_HdmiCec2.cpp "../../HdmiCec_2" "${ # PLUGIN_HDMICECSINK set (HDMICECSINK_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSink ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) -set (HDMICECSINK_LIBS ${NAMESPACE}HdmiCecSink ${NAMESPACE}HdmiCecSinkImplementation) -add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${HDMICECSINK_LIBS}") +add_plugin_test_ex(PLUGIN_HDMICECSINK tests/test_HdmiCecSink.cpp "${HDMICECSINK_INC}" "${NAMESPACE}HdmiCecSink") # PLUGIN_HDMICECSOURCE set (HDMICECSOURCE_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiCecSource ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) diff --git a/Tests/L1Tests/tests/test_HdmiCecSource.cpp b/Tests/L1Tests/tests/test_HdmiCecSource.cpp index a298e038..3ae56adb 100755 --- a/Tests/L1Tests/tests/test_HdmiCecSource.cpp +++ b/Tests/L1Tests/tests/test_HdmiCecSource.cpp @@ -989,7 +989,7 @@ TEST_F(HdmiCecSourceInitializedEventTest, requestActiveSourceProccess){ Header header; header.from = LogicalAddress(1); //specifies with logicalAddress in the deviceList we're using - RequestActiveSourceMessage requestActiveSource; + RequestActiveSource requestActiveSource; Plugin::HdmiCecSourceProcessor proc(Connection::getInstance()); From 8a6fd55be4c187be3c725d2ca6512720bd6c018b Mon Sep 17 00:00:00 2001 From: svemur170 Date: Tue, 22 Jul 2025 19:41:40 +0000 Subject: [PATCH 02/14] RDKEMW-6279 - Changelog updates for 1.3.4 Signed-off-by: svemur170 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de554a7..1f24687d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.3...1.3.4) + +- RDKEMW-6279: Revert of HdmiCecSink comrpc changes (#129) [`#199`](https://github.com/rdkcentral/entservices-inputoutput/pull/199) +- Merge tag '1.3.3' into develop [`7abaec3`](https://github.com/rdkcentral/entservices-inputoutput/commit/7abaec32ed58c36ef05640ca9baaf8077b90a5d5) + #### [1.3.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.2...1.3.3) +> 10 July 2025 + - RDKEMW-3750 : Upgrade Thunder to Version R4.4.3 [`#133`](https://github.com/rdkcentral/entservices-inputoutput/pull/133) - cmake cleanup [`#151`](https://github.com/rdkcentral/entservices-inputoutput/pull/151) - RDK-42386 : Improve Unit Tests Coverage for AVInput Plugin [`#164`](https://github.com/rdkcentral/entservices-inputoutput/pull/164) +- RDKEMW-3750 - Changelog updates for 1.3.3 [`ced5287`](https://github.com/rdkcentral/entservices-inputoutput/commit/ced52871e5f60487165bf417af781f3f72e10bfa) - Merge tag '1.3.2' into develop [`dab1c4a`](https://github.com/rdkcentral/entservices-inputoutput/commit/dab1c4ab82e2983b04d66bdb975a546a79efc47f) #### [1.3.2](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.1...1.3.2) From 4b8146edce8360b845cc6446fcc414e9279d76b9 Mon Sep 17 00:00:00 2001 From: Yuvaramachandran Gurusamy <123441336+yuvaramachandran-gurusamy@users.noreply.github.com> Date: Wed, 23 Jul 2025 15:57:36 +0530 Subject: [PATCH 03/14] RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink (#203) * RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink Signed-off-by: yuvaramachandran_gurusamy * RDKEMW-6230: Fix L1 test build failure Signed-off-by: yuvaramachandran_gurusamy --------- Signed-off-by: yuvaramachandran_gurusamy --- HdmiCecSink/HdmiCecSink.cpp | 28 ++++++++++++++++-------- Tests/L1Tests/tests/test_HdmiCecSink.cpp | 2 -- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/HdmiCecSink/HdmiCecSink.cpp b/HdmiCecSink/HdmiCecSink.cpp index b5150cf8..ecb5415e 100644 --- a/HdmiCecSink/HdmiCecSink.cpp +++ b/HdmiCecSink/HdmiCecSink.cpp @@ -3531,15 +3531,25 @@ namespace WPEFramework { int err; dsGetHDMIARCPortIdParam_t param; - err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, - (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, - (void *)¶m, - sizeof(param)); - if (IARM_RESULT_SUCCESS == err) - { - LOGINFO("HDMI ARC port ID HdmiArcPortID=[%d] \n", param.portId); - HdmiArcPortID = param.portId; - } + unsigned int retryCount = 1; + do { + usleep(50000); // Sleep for 50ms before retrying + param.portId = -1; // Initialize to an invalid port ID + err = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_dsGetHDMIARCPortId, + (void *)¶m, + sizeof(param)); + if (IARM_RESULT_SUCCESS == err) + { + LOGINFO("HDMI ARC port ID HdmiArcPortID[%d] on retry count[%d]", param.portId, retryCount); + HdmiArcPortID = param.portId; + break; + } + else + { + LOGWARN("IARM_Bus_Call failed with error[%d], retry count[%d]", err, retryCount); + } + } while(retryCount++ <= 6); } void HdmiCecSink::getCecVersion() diff --git a/Tests/L1Tests/tests/test_HdmiCecSink.cpp b/Tests/L1Tests/tests/test_HdmiCecSink.cpp index 38631077..22df165c 100755 --- a/Tests/L1Tests/tests/test_HdmiCecSink.cpp +++ b/Tests/L1Tests/tests/test_HdmiCecSink.cpp @@ -23,8 +23,6 @@ #include -#include "HdmiCecSinkImplementation.h" -#include "HdmiCecSinkMock.h" #include "HdmiCecSink.h" #include "FactoriesImplementation.h" #include "IarmBusMock.h" From b12cd97a05c2dc2b7915cfac28c998fb2277d349 Mon Sep 17 00:00:00 2001 From: siva aditya varma uppalapati Date: Wed, 23 Jul 2025 10:33:32 +0000 Subject: [PATCH 04/14] 1.3.5 release changelog updates --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f24687d..e60fb2bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.3.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.4...1.3.5) + +- RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink [`#203`](https://github.com/rdkcentral/entservices-inputoutput/pull/203) +- Merge tag '1.3.4' into develop [`760ee0f`](https://github.com/rdkcentral/entservices-inputoutput/commit/760ee0f9da46e0b0ed2e2adb4523bfec85c5a927) + #### [1.3.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.3...1.3.4) +> 22 July 2025 + - RDKEMW-6279: Revert of HdmiCecSink comrpc changes (#129) [`#199`](https://github.com/rdkcentral/entservices-inputoutput/pull/199) +- RDKEMW-6279 - Changelog updates for 1.3.4 [`8a6fd55`](https://github.com/rdkcentral/entservices-inputoutput/commit/8a6fd55be4c187be3c725d2ca6512720bd6c018b) - Merge tag '1.3.3' into develop [`7abaec3`](https://github.com/rdkcentral/entservices-inputoutput/commit/7abaec32ed58c36ef05640ca9baaf8077b90a5d5) #### [1.3.3](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.2...1.3.3) From 7b417c62cb1d8daf4ede73b9ca1cf39bb43a66f3 Mon Sep 17 00:00:00 2001 From: Anju Raveendran Date: Tue, 22 Jul 2025 11:01:30 +0100 Subject: [PATCH 05/14] RDKEMW-6325: platfromSupport is missing from dimmingMode capabilities Reason For Change: platfromSupport is missing from getBacklightDimmingModeCaps Test procedure: Mentioned in the ticket Risks: Low Signed-off-by: anju.raveendran@sky.uk --- AVOutput/AVOutputTV.cpp | 14 ++++++++++++++ AVOutput/AVOutputTVHelper.cpp | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index 3f0e8e59..b686669c 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -2016,6 +2016,10 @@ namespace Plugin { returnResponse(false); } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } + if (getParamIndex("DimmingMode",inputInfo,indexInfo) == -1) { LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); returnResponse(false); @@ -2072,6 +2076,10 @@ namespace Plugin { returnResponse(false); } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } + if( !isCapablityCheckPassed( "DimmingMode" , inputInfo )) { LOGERR("%s: CapablityCheck failed for DimmingMode\n", __FUNCTION__); returnResponse(false); @@ -2118,6 +2126,10 @@ namespace Plugin { returnResponse(false); } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } + int retval= updateAVoutputTVParam("reset","DimmingMode", inputInfo,PQ_PARAM_DIMMINGMODE,dMode); if(retval != 0 ) { @@ -2171,6 +2183,8 @@ namespace Plugin { returnResponse(false); } else { + response["platformSupport"] = (info.isPlatformSupportVector[0].compare("true") == 0) ? true : false; + for (index = 0; index < info.rangeVector.size(); index++) { supportedDimmingModeArray.Add(info.rangeVector[index]); } diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 527569a9..6fbcbab0 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -2302,7 +2302,7 @@ namespace Plugin { } - if ((param == "DolbyVisionMode") || (param == "Backlight") || (param == "CMS") || (param == "CustomWhiteBalance") || (param == "HDRMode") || (param == "BacklightControl")) { + if ((param == "DolbyVisionMode") || (param == "Backlight") || (param == "CMS") || (param == "CustomWhiteBalance") || (param == "HDRMode") || (param == "BacklightControl") || (param == "DimmingMode")) { configString = param + ".platformsupport"; info.isPlatformSupport = inFile.Get(configString); printf(" platformsupport : %s\n",info.isPlatformSupport.c_str() ); From 008fa89376b48570d81b21e87c53914da789931c Mon Sep 17 00:00:00 2001 From: PriyaPesala <116076033+PriyaPesala@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:46:15 +0530 Subject: [PATCH 06/14] [RDKEMW-3513] PR action to run with latest change (#163) * [RDKEMW-3513] PR action to run with latest change * Modifying L1,L2 .yml * Modifying artifacts job name * resolving review comments * modifying testframework branch name to develop * pointing to develop * Update tests-trigger.yml --------- Co-authored-by: Prathyushakothuru <142974139+Prathyushakothuru@users.noreply.github.com> Co-authored-by: kprathyusha --- .github/workflows/L1-tests.yml | 16 +++++++++++----- .github/workflows/L2-tests.yml | 18 ++++++++++++------ .github/workflows/tests-trigger.yml | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 11 deletions(-) create mode 100755 .github/workflows/tests-trigger.yml diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 6121092a..f5dfb136 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -1,10 +1,10 @@ name: L1-tests on: - push: - branches: [ main, develop, 'sprint/**', 'release/**' ] - pull_request: - branches: [ main, develop, 'sprint/**', 'release/**' ] + workflow_call: + secrets: + RDKCM_RDKE: + required: true env: BUILD_TYPE: Debug @@ -66,6 +66,10 @@ jobs: python-version: '3.x' - run: pip install jsonref + - name: ACK External Trigger + run: | + echo "Message: External Trigger Received for L1 Tests" + - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 with: @@ -119,7 +123,9 @@ jobs: - name: Checkout entservices-inputoutput uses: actions/checkout@v3 with: + repository: rdkcentral/entservices-inputoutput path: entservices-inputoutput + ref: develop - name: Checkout googletest if: steps.cache.outputs.cache-hit != 'true' @@ -667,7 +673,7 @@ jobs: if: ${{ !env.ACT }} uses: actions/upload-artifact@v4 with: - name: artifacts + name: artifacts-L1-inputoutput path: | coverage/ valgrind_log diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index c8a13eb5..9dc033be 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -1,10 +1,10 @@ name: L2-tests on: - push: - branches: [ main, develop, 'sprint/**', 'release/**' ] - pull_request: - branches: [ main, develop, 'sprint/**', 'release/**' ] + workflow_call: + secrets: + RDKCM_RDKE: + required: true env: BUILD_TYPE: Debug @@ -36,6 +36,10 @@ jobs: python-version: '3.x' - run: pip install jsonref + - name: ACK External Trigger + run: | + echo "Message: External Trigger Received for L2 Tests" + - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 with: @@ -81,7 +85,9 @@ jobs: - name: Checkout entservices-inputoutput uses: actions/checkout@v3 with: + repository: rdkcentral/entservices-inputoutput path: entservices-inputoutput + ref: develop - name: Checkout entservices-testframework uses: actions/checkout@v3 @@ -375,7 +381,7 @@ jobs: -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/iarmmgrs-hal -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices -I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices/proc - -I $GITHUB_WORKSPACE/entservices-deviceanddisplay/helpers + -I $GITHUB_WORKSPACE/entservices-inputoutput/helpers -I $GITHUB_WORKSPACE/install/usr/include -I $GITHUB_WORKSPACE/install/usr/include/WPEFramework -include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h @@ -581,7 +587,7 @@ jobs: if: ${{ !env.ACT }} uses: actions/upload-artifact@v4 with: - name: artifacts + name: artifacts-L2-inputoutput path: | coverage/ valgrind_log diff --git a/.github/workflows/tests-trigger.yml b/.github/workflows/tests-trigger.yml new file mode 100755 index 00000000..3aa84f0f --- /dev/null +++ b/.github/workflows/tests-trigger.yml @@ -0,0 +1,21 @@ +permissions: + contents: read +name: main-workflow + +on: + push: + branches: [ main, develop, 'sprint/**', 'release/**' ] + pull_request: + branches: [ main, develop, 'sprint/**', 'release/**' ] + +jobs: + trigger-L1: + uses: ./.github/workflows/L1-tests.yml + secrets: + RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} + + trigger-L2: + uses: ./.github/workflows/L2-tests.yml + secrets: + RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} + From cc6cb216e9e1a36cc8527db723046391676812f0 Mon Sep 17 00:00:00 2001 From: ssitar583 Date: Thu, 24 Jul 2025 19:56:49 +0530 Subject: [PATCH 07/14] RDKEMW-2942 : Remove the HdmiInput plugin and replace its references with AVInput (#205) Co-authored-by: apatel859 <48992974+apatel859@users.noreply.github.com> --- .github/workflows/L1-tests.yml | 2 - CMakeLists.txt | 4 - HdmiInput/CHANGELOG.md | 27 - HdmiInput/CMakeLists.txt | 64 -- HdmiInput/HdmiInput.conf.in | 4 - HdmiInput/HdmiInput.config | 7 - HdmiInput/HdmiInput.cpp | 1454 ------------------------ HdmiInput/HdmiInput.h | 139 --- HdmiInput/Module.cpp | 22 - HdmiInput/Module.h | 29 - HdmiInput/README.md | 9 - HdmiInput/cmake/FindDS.cmake | 57 - HdmiInput/cmake/FindIARMBus.cmake | 44 - Tests/L1Tests/CMakeLists.txt | 3 - Tests/L1Tests/tests/test_HdmiInput.cpp | 861 -------------- 15 files changed, 2726 deletions(-) delete mode 100644 HdmiInput/CHANGELOG.md delete mode 100644 HdmiInput/CMakeLists.txt delete mode 100644 HdmiInput/HdmiInput.conf.in delete mode 100644 HdmiInput/HdmiInput.config delete mode 100644 HdmiInput/HdmiInput.cpp delete mode 100644 HdmiInput/HdmiInput.h delete mode 100644 HdmiInput/Module.cpp delete mode 100644 HdmiInput/Module.h delete mode 100644 HdmiInput/README.md delete mode 100644 HdmiInput/cmake/FindDS.cmake delete mode 100644 HdmiInput/cmake/FindIARMBus.cmake delete mode 100644 Tests/L1Tests/tests/test_HdmiInput.cpp diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index f5dfb136..0b5cfccd 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -443,7 +443,6 @@ jobs: -DHAS_FRONT_PANEL=ON -DRDK_SERVICES_L1_TEST=ON -DPLUGIN_AVINPUT=ON - -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=ON @@ -521,7 +520,6 @@ jobs: -DCMAKE_BUILD_TYPE=Debug -DDS_FOUND=ON -DPLUGIN_AVINPUT=ON - -DPLUGIN_HDMIINPUT=ON -DPLUGIN_HDCPPROFILE=ON -DPLUGIN_HDMICECSOURCE=ON -DPLUGIN_HDMICECSINK=ON diff --git a/CMakeLists.txt b/CMakeLists.txt index df70686a..6a222334 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,10 +64,6 @@ if(PLUGIN_HDCPPROFILE) add_subdirectory(HdcpProfile) endif() -if(PLUGIN_HDMIINPUT) - add_subdirectory(HdmiInput) -endif() - if(WPEFRAMEWORK_CREATE_IPKG_TARGETS) set(CPACK_GENERATOR "DEB") diff --git a/HdmiInput/CHANGELOG.md b/HdmiInput/CHANGELOG.md deleted file mode 100644 index 3e73c318..00000000 --- a/HdmiInput/CHANGELOG.md +++ /dev/null @@ -1,27 +0,0 @@ -# Changelog - -All notable changes to this RDK Service will be documented in this file. - -* Each RDK Service has a CHANGELOG file that contains all changes done so far. When version is updated, add a entry in the CHANGELOG.md at the top with user friendly information on what was changed with the new version. Please don't mention JIRA tickets in CHANGELOG. - -* Please Add entry in the CHANGELOG for each version change and indicate the type of change with these labels: - * **Added** for new features. - * **Changed** for changes in existing functionality. - * **Deprecated** for soon-to-be removed features. - * **Removed** for now removed features. - * **Fixed** for any bug fixes. - * **Security** in case of vulnerabilities. - -* Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. - -## [1.4.0] - 2025-02-17 -### Added -- Added support for Getting the Maximum HDMI Compatibility version for the given port. - -## [1.0.0] - 2025-02-17 -### Added -- Add CHANGELOG - -### Change -- Reset API version to 1.0.0 -- Change README to inform how to update changelog and API version diff --git a/HdmiInput/CMakeLists.txt b/HdmiInput/CMakeLists.txt deleted file mode 100644 index b5d667a4..00000000 --- a/HdmiInput/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -# If not stated otherwise in this file or this component's license file the -# following copyright and licenses apply: -# -# Copyright 2020 RDK Management -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set(PLUGIN_NAME HdmiInput) -set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME}) - -set(PLUGIN_HDMIINPUT_STARTUPORDER "" CACHE STRING "To configure startup order of HdmiInput plugin") - -find_package(${NAMESPACE}Plugins REQUIRED) -if (USE_THUNDER_R4) - find_package(${NAMESPACE}COM REQUIRED) -else () - find_package(${NAMESPACE}Protocols REQUIRED) -endif (USE_THUNDER_R4) - -add_library(${MODULE_NAME} SHARED - HdmiInput.cpp - Module.cpp - ) - -set_target_properties(${MODULE_NAME} PROPERTIES - CXX_STANDARD 11 - CXX_STANDARD_REQUIRED YES) - -target_compile_definitions(${MODULE_NAME} PRIVATE MODULE_NAME=Plugin_${PLUGIN_NAME}) - -target_include_directories(${MODULE_NAME} PRIVATE ../helpers) - -if (USE_THUNDER_R4) -target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}COM::${NAMESPACE}COM) -else () -target_link_libraries(${MODULE_NAME} PRIVATE ${NAMESPACE}Protocols::${NAMESPACE}Protocols) -endif (USE_THUNDER_R4) - - -find_package(DS) -find_package(IARMBus) - -target_include_directories(${MODULE_NAME} PRIVATE ${DS_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ${IARMBUS_INCLUDE_DIRS}) -target_include_directories(${MODULE_NAME} PRIVATE ../helpers) - -set_source_files_properties(HdmiInput.cpp PROPERTIES COMPILE_FLAGS "-fexceptions") - -target_link_libraries(${MODULE_NAME} PUBLIC ${NAMESPACE}Plugins::${NAMESPACE}Plugins ${IARMBUS_LIBRARIES} ${DS_LIBRARIES} ) - -install(TARGETS ${MODULE_NAME} - DESTINATION lib/${STORAGE_DIRECTORY}/plugins) - -write_config(${PLUGIN_NAME}) diff --git a/HdmiInput/HdmiInput.conf.in b/HdmiInput/HdmiInput.conf.in deleted file mode 100644 index e16bde27..00000000 --- a/HdmiInput/HdmiInput.conf.in +++ /dev/null @@ -1,4 +0,0 @@ -precondition = ["Platform"] -callsign = "org.rdk.HdmiInput" -autostart = "false" -startuporder = "@PLUGIN_HDMIINPUT_STARTUPORDER@" diff --git a/HdmiInput/HdmiInput.config b/HdmiInput/HdmiInput.config deleted file mode 100644 index 2b918b14..00000000 --- a/HdmiInput/HdmiInput.config +++ /dev/null @@ -1,7 +0,0 @@ -set (autostart false) -set (preconditions Platform) -set (callsign "org.rdk.HdmiInput") - -if(PLUGIN_HDMIINPUT_STARTUPORDER) -set (startuporder ${PLUGIN_HDMIINPUT_STARTUPORDER}) -endif() diff --git a/HdmiInput/HdmiInput.cpp b/HdmiInput/HdmiInput.cpp deleted file mode 100644 index ef53a03a..00000000 --- a/HdmiInput/HdmiInput.cpp +++ /dev/null @@ -1,1454 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include "HdmiInput.h" -#include "UtilsJsonRpc.h" -#include "UtilsIarm.h" - -#include "hdmiIn.hpp" -#include "exception.hpp" -#include "dsUtl.h" -#include "dsError.h" -#include "dsMgr.h" -#include "host.hpp" - -#include -#include - -#define HDMI_HOT_PLUG_EVENT_CONNECTED 0 -#define HDMI_HOT_PLUG_EVENT_DISCONNECTED 1 - -#define HDMIINPUT_METHOD_GET_HDMI_INPUT_DEVICES "getHDMIInputDevices" -#define HDMIINPUT_METHOD_WRITE_EDID "writeEDID" -#define HDMIINPUT_METHOD_READ_EDID "readEDID" -#define HDMIINPUT_METHOD_READ_RAWHDMISPD "getRawHDMISPD" -#define HDMIINPUT_METHOD_READ_HDMISPD "getHDMISPD" -#define HDMIINPUT_METHOD_SET_EDID_VERSION "setEdidVersion" -#define HDMIINPUT_METHOD_GET_EDID_VERSION "getEdidVersion" -#define HDMIINPUT_METHOD_SET_MIXER_LEVELS "setMixerLevels" -#define HDMIINPUT_METHOD_START_HDMI_INPUT "startHdmiInput" -#define HDMIINPUT_METHOD_STOP_HDMI_INPUT "stopHdmiInput" -#define HDMIINPUT_METHOD_SCALE_HDMI_INPUT "setVideoRectangle" -#define HDMIINPUT_METHOD_SUPPORTED_GAME_FEATURES "getSupportedGameFeatures" -#define HDMIINPUT_METHOD_GAME_FEATURE_STATUS "getHdmiGameFeatureStatus" - -#define HDMIINPUT_EVENT_ON_DEVICES_CHANGED "onDevicesChanged" -#define HDMIINPUT_EVENT_ON_SIGNAL_CHANGED "onSignalChanged" -#define HDMIINPUT_EVENT_ON_STATUS_CHANGED "onInputStatusChanged" -#define HDMIINPUT_EVENT_ON_VIDEO_MODE_UPDATED "videoStreamInfoUpdate" -#define HDMIINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED "hdmiGameFeatureStatusUpdate" -#define HDMIINPUT_EVENT_ON_AVI_CONTENT_TYPE_CHANGED "hdmiContentTypeUpdate" -#define HDMIINPUT_METHOD_GET_LOW_LATENCY_MODE "getTVLowLatencyMode" -#define HDMIINPUT_METHOD_GET_AV_LATENCY "getAVLatency" -#define HDMIINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION "getHdmiVersion" - -#define HDMICECSINK_CALLSIGN "org.rdk.HdmiCecSink" -#define HDMICECSINK_CALLSIGN_VER HDMICECSINK_CALLSIGN".1" -#define TVSETTINGS_CALLSIGN "org.rdk.tv.ControlSettings" -#define TVSETTINGS_CALLSIGN_VER TVSETTINGS_CALLSIGN".2" - -// TODO: remove this -#define registerMethod(...) for (uint8_t i = 1; GetHandler(i); i++) GetHandler(i)->Register(__VA_ARGS__) - -#define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 4 -#define API_VERSION_NUMBER_PATCH 0 - -static int audio_output_delay = 100; -static int video_latency = 20; -#define TVMGR_GAME_MODE_EVENT "gameModeEvent" -static bool lowLatencyMode = false; -#define SERVER_DETAILS "127.0.0.1:9998" -static int planeType = 0; -static bool isAudioBalanceSet = false; -using namespace std; - -namespace WPEFramework -{ - namespace { - - static Plugin::Metadata metadata( - // Version (Major, Minor, Patch) - API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH, - // Preconditions - {}, - // Terminations - {}, - // Controls - {} - ); - } - - namespace Plugin - { - SERVICE_REGISTRATION(HdmiInput, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); - - HdmiInput* HdmiInput::_instance = nullptr; - - HdmiInput::HdmiInput() - : PluginHost::JSONRPC() - { - HdmiInput::_instance = this; - - m_tv_client = nullptr; - m_client = nullptr; - //InitializeIARM(); - - CreateHandler({2}); - - registerMethod(HDMIINPUT_METHOD_GET_HDMI_INPUT_DEVICES, &HdmiInput::getHDMIInputDevicesWrapper, this); - registerMethod(HDMIINPUT_METHOD_WRITE_EDID, &HdmiInput::writeEDIDWrapper, this); - registerMethod(HDMIINPUT_METHOD_READ_EDID, &HdmiInput::readEDIDWrapper, this); - registerMethod(HDMIINPUT_METHOD_READ_RAWHDMISPD, &HdmiInput::getRawHDMISPDWrapper, this); - registerMethod(HDMIINPUT_METHOD_READ_HDMISPD, &HdmiInput::getHDMISPDWrapper, this); - registerMethod(HDMIINPUT_METHOD_SET_EDID_VERSION, &HdmiInput::setEdidVersionWrapper, this); - registerMethod(HDMIINPUT_METHOD_GET_EDID_VERSION, &HdmiInput::getEdidVersionWrapper, this); - registerMethod(HDMIINPUT_METHOD_START_HDMI_INPUT, &HdmiInput::startHdmiInput, this); - registerMethod(HDMIINPUT_METHOD_STOP_HDMI_INPUT, &HdmiInput::stopHdmiInput, this); - registerMethod(HDMIINPUT_METHOD_SCALE_HDMI_INPUT, &HdmiInput::setVideoRectangleWrapper, this); - registerMethod(HDMIINPUT_METHOD_SET_MIXER_LEVELS, &HdmiInput::setMixerLevels, this); - registerMethod(HDMIINPUT_METHOD_SUPPORTED_GAME_FEATURES, &HdmiInput::getSupportedGameFeatures, this); - registerMethod(HDMIINPUT_METHOD_GAME_FEATURE_STATUS, &HdmiInput::getHdmiGameFeatureStatusWrapper, this); - registerMethod(HDMIINPUT_METHOD_GET_AV_LATENCY, &HdmiInput::getAVLatency, this); - registerMethod(HDMIINPUT_METHOD_GET_LOW_LATENCY_MODE, &HdmiInput::getTVLowLatencyMode, this); - registerMethod(HDMIINPUT_METHOD_GET_HDMI_COMPATIBILITY_VERSION, &HdmiInput::getHdmiVersionWrapper, this); - m_primVolume = DEFAULT_PRIM_VOL_LEVEL; - m_inputVolume = DEFAULT_INPUT_VOL_LEVEL; - } - - HdmiInput::~HdmiInput() - { - } - - const string HdmiInput::Initialize(PluginHost::IShell * service ) - { - LOGINFO("Entering HdmiInput::Initialize"); - ASSERT(service != nullptr); - ASSERT(m_service == nullptr); - - m_service = service; - m_service->AddRef(); - - HdmiInput::_instance = this; - InitializeIARM(); - - subscribeForTvMgrEvent("gameModeEvent"); - LOGINFO("Exiting HdmiInput::Initialize"); - return (string()); - } - - uint32_t HdmiInput::subscribeForTvMgrEvent(const char* eventName) - { - uint32_t err = Core::ERROR_NONE; - LOGINFO("Attempting to subscribe for event: %s\n", eventName); - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T(SERVER_DETAILS))); - if (nullptr == m_tv_client) { - getControlSettingsPlugin(); - if (nullptr == m_tv_client) { - LOGERR("JSONRPC: %s: client initialization failed", TVSETTINGS_CALLSIGN_VER); - err = Core::ERROR_UNAVAILABLE; - } - } - - if(err == Core::ERROR_NONE) { - /* Register handlers for Event reception. */ - if(strcmp(eventName, TVMGR_GAME_MODE_EVENT) == 0) { - err =m_tv_client->Subscribe(1000, eventName, &HdmiInput::onGameModeEventHandler, this); - } - else { - LOGERR("Failed to subscribe for %s with code %d", eventName, err); - } - } - return err; - } - - void setResponseArray(JsonObject& response, const char* key, const vector& items) - { - JsonArray arr; - for(auto& i : items) arr.Add(JsonValue(i)); - - response[key] = arr; - - string json; - response.ToString(json); - } - - void HdmiInput::Deinitialize(PluginHost::IShell* service ) - { - ASSERT(service == m_service); - m_service->Release(); - m_service = nullptr; - - HdmiInput::_instance = nullptr; - - DeinitializeIARM(); - } - - void HdmiInput::InitializeIARM() - { - if (Utils::IARM::init()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, dsHdmiSignalStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, dsHdmiStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, dsHdmiVideoModeEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, dsHdmiGameFeatureStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE, dsHdmiAviContentTypeEventHandler) ); - IARM_CHECK( IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY, dsHdmiAVLatencyEventHandler) ); - } - } - - void HdmiInput::DeinitializeIARM() - { - if (Utils::IARM::isConnected()) - { - IARM_Result_t res; - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, dsHdmiEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, dsHdmiSignalStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, dsHdmiStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, dsHdmiVideoModeEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, dsHdmiGameFeatureStatusEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE,dsHdmiAviContentTypeEventHandler) ); - IARM_CHECK( IARM_Bus_RemoveEventHandler(IARM_BUS_DSMGR_NAME,IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY,dsHdmiAVLatencyEventHandler) ); - } - } - - uint32_t HdmiInput::startHdmiInput(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - - string sPortId = parameters["portId"].String(); - bool audioMix = parameters["requestAudioMix"].Boolean(); - int portId = 0; - bool topMostPlane = parameters["topMost"].Boolean(); - - //planeType = 0 - primary, 1 - secondary video plane type - planeType = 0; - try { - portId = stoi(sPortId); - if (parameters.HasLabel("plane")){ - string sPlaneType = parameters["plane"].String(); - planeType = stoi(sPlaneType); - if(!(planeType == 0 || planeType == 1))// planeType has to be primary(0) or secondary(1) - { - LOGWARN("planeType is invalid\n"); - returnResponse(false); - } - } - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - bool success = true; - try - { - device::HdmiInput::getInstance().selectPort(portId,audioMix,planeType,topMostPlane); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(sPortId); - success = false; - } - returnResponse(success); - - } - - uint32_t HdmiInput::stopHdmiInput(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool success = true; - try - { - // Restoring the Audio Mixer Levels when the Input is stopped. - if (isAudioBalanceSet){ - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_PRIMARY,MAX_PRIM_VOL_LEVEL); - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_SYSTEM,DEFAULT_INPUT_VOL_LEVEL); - isAudioBalanceSet = false; - } - planeType = -1;// plane index when stopping hdmi input - device::HdmiInput::getInstance().selectPort(-1); - } - catch (const device::Exception& err) - { - LOGWARN("HdmiInputService::stopHdmiInput Failed"); - success = false; - } - returnResponse(success); - - } - uint32_t HdmiInput::setMixerLevels(const JsonObject& parameters, JsonObject& response) - { - returnIfParamNotFound(parameters, "primaryVolume"); - returnIfParamNotFound(parameters, "inputVolume"); - - int primVol = 0, inputVol = 0; - try { - primVol = parameters["primaryVolume"].Number(); - inputVol = parameters["inputVolume"].Number() ; - } catch(...) { - LOGERR("Incompatible params passed !!!\n"); - response["success"] = false; - returnResponse(false); - } - - if( (primVol >=0) && (inputVol >=0) ) { - m_primVolume = primVol; - m_inputVolume = inputVol; - } - else { - LOGERR("Incompatible params passed !!!\n"); - response["success"] = false; - returnResponse(false); - } - - if(m_primVolume > MAX_PRIM_VOL_LEVEL) { - LOGWARN("Primary Volume greater than limit. Set to MAX_PRIM_VOL_LEVEL(100) !!!\n"); - m_primVolume = MAX_PRIM_VOL_LEVEL; - } - if(m_inputVolume > DEFAULT_INPUT_VOL_LEVEL) { - LOGWARN("Input Volume greater than limit. Set to DEFAULT_INPUT_VOL_LEVEL(100) !!!\n"); - m_inputVolume = DEFAULT_INPUT_VOL_LEVEL; - } - LOGINFO("GLOBAL primary Volume=%d input Volume=%d \n",m_primVolume , m_inputVolume ); - - try{ - - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_PRIMARY,primVol); - device::Host::getInstance().setAudioMixerLevels(dsAUDIO_INPUT_SYSTEM,inputVol); - } - catch(...){ - LOGWARN("Not setting SoC volume !!!\n"); - returnResponse(false); - } - isAudioBalanceSet = true; - returnResponse(true); - } - - uint32_t HdmiInput::setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - bool result = true; - if (!parameters.HasLabel("x") && !parameters.HasLabel("y")) - { - result = false; - response["message"] = "please specif coordinates (x,y)"; - } - - if (!parameters.HasLabel("w") && !parameters.HasLabel("h")) - { - result = false; - response["message"] = "please specify window width and height (w,h)"; - } - - if (result) - { - int x = 0; - int y = 0; - int w = 0; - int h = 0; - - try - { - if (parameters.HasLabel("x")) - { - x = std::stoi(parameters["x"].String()); - } - if (parameters.HasLabel("y")) - { - y = std::stoi(parameters["y"].String()); - } - if (parameters.HasLabel("w")) - { - w = std::stoi(parameters["w"].String()); - } - if (parameters.HasLabel("h")) - { - h = std::stoi(parameters["h"].String()); - } - } - catch (const std::exception& err) { - LOGWARN("Invalid paramater X: %s,Y: %s, W: %s, H:%s ", parameters["x"].String().c_str(),parameters["y"].String().c_str(),parameters["w"].String().c_str(),parameters["h"].String().c_str()); - returnResponse(false); - } - - result = setVideoRectangle(x, y, w, h); - if (false == result) { - LOGWARN("HdmiInputService::setVideoRectangle Failed"); - response["message"] = "failed to set scale"; - } - } - - returnResponse(result); - - } - - bool HdmiInput::setVideoRectangle(int x, int y, int width, int height) - { - bool ret = true; - - try - { - device::HdmiInput::getInstance().scaleVideo(x, y, width, height); - } - catch (const device::Exception& err) - { - ret = false; - } - - return ret; - } - - uint32_t HdmiInput::getHDMIInputDevicesWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - response["devices"] = getHDMIInputDevices(); - - returnResponse(true); - } - - uint32_t HdmiInput::writeEDIDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - int deviceId; - std::string message; - - if (parameters.HasLabel("deviceId") && parameters.HasLabel("message")) - { - getNumberParameter("deviceId", deviceId); - message = parameters["message"].String(); - } - else - { - LOGWARN("Required parameters are not passed"); - returnResponse(false); - } - - - writeEDID(deviceId, message); - returnResponse(true); - - } - - uint32_t HdmiInput::readEDIDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - - string sPortId = parameters.HasLabel("deviceId") ? parameters["deviceId"].String() : "0";; - int portId = 0; - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - string edid = readEDID (portId); - response["EDID"] = edid; - if (edid.empty()) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - JsonArray HdmiInput::getHDMIInputDevices() - { - JsonArray list; - try - { - int num = device::HdmiInput::getInstance().getNumberOfInputs(); - if (num > 0) { - int i = 0; - for (i = 0; i < num; i++) { - //Input ID is aleays 0-indexed, continuous number starting 0 - JsonObject hash; - hash["id"] = i; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << i; - hash["locator"] = locator.str(); - hash["connected"] = device::HdmiInput::getInstance().isPortConnected(i) ? "true" : "false"; - LOGWARN("HdmiInputService::getHDMIInputDevices id %d, locator=[%s], connected=[%s]", i, hash["locator"].String().c_str(), hash["connected"].String().c_str()); - list.Add(hash); - } - } - } - catch (const std::exception& e) { - LOGWARN("HdmiInputService::getHDMIInputDevices Failed"); - } - - return list; - } - - void HdmiInput::writeEDID(int deviceId, std::string message) - { - - } - - std::string HdmiInput::readEDID(int iPort) - { - vector edidVec({'u','n','k','n','o','w','n' }); - string edidbase64 = ""; - try - { - vector edidVec2; - device::HdmiInput::getInstance().getEDIDBytesInfo (iPort, edidVec2); - edidVec = edidVec2;//edidVec must be "unknown" unless we successfully get to this line - - //convert to base64 - uint16_t size = min(edidVec.size(), (size_t)numeric_limits::max()); - - LOGWARN("HdmiInput::readEDID size:%u edidVec.size:%d", size, (int)edidVec.size()); - - if(edidVec.size() > (size_t)numeric_limits::max()) { - LOGERR("Size too large to use ToString base64 wpe api"); - return edidbase64; - } - - Core::ToString((uint8_t*)&edidVec[0], size, true, edidbase64); - - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return edidbase64; - } - - /** - * @brief This function is used to translate HDMI input hotplug to - * deviceChanged event. - * - * @param[in] input Number of input port integer. - * @param[in] connection status of input port integer. - */ - void HdmiInput::hdmiInputHotplug( int input , int connect) - { - LOGWARN("hdmiInputHotplug [%d, %d]", input, connect); - - JsonObject params; - params["devices"] = getHDMIInputDevices(); - sendNotify(HDMIINPUT_EVENT_ON_DEVICES_CHANGED, params); - } - - /** - * @brief This function is used to translate HDMI input signal change to - * signalChanged event. - * - * @param[in] port HDMI In port id. - * @param[in] signalStatus signal status of HDMI In port. - */ - void HdmiInput::hdmiInputSignalChange( int port , int signalStatus) - { - LOGWARN("hdmiInputSignalStatus [%d, %d]", port, signalStatus); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - switch (signalStatus) { - case dsHDMI_IN_SIGNAL_STATUS_NOSIGNAL: - params["signalStatus"] = "noSignal"; - break; - - case dsHDMI_IN_SIGNAL_STATUS_UNSTABLE: - params["signalStatus"] = "unstableSignal"; - break; - - case dsHDMI_IN_SIGNAL_STATUS_NOTSUPPORTED: - params["signalStatus"] = "notSupportedSignal"; - break; - - case dsHDMI_IN_SIGNAL_STATUS_STABLE: - params["signalStatus"] = "stableSignal"; - break; - - default: - params["signalStatus"] = "none"; - break; - } - - sendNotify(HDMIINPUT_EVENT_ON_SIGNAL_CHANGED, params); - } - - /** - * @brief This function is used to translate HDMI input status change to - * inputStatusChanged event. - * - * @param[in] port HDMI In port id. - * @param[bool] isPresented HDMI In presentation started/stopped. - */ - void HdmiInput::hdmiInputStatusChange( int port , bool isPresented) - { - LOGWARN("hdmiInputStatus [%d, %d]", port, isPresented); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - if(isPresented) { - params["status"] = "started"; - } - else { - params["status"] = "stopped"; - } - params["plane"] = planeType; - sendNotify(HDMIINPUT_EVENT_ON_STATUS_CHANGED, params); - } - - /** - * @brief This function is used to translate HDMI input video mode change to - * videoStreamInfoUpdate event. - * - * @param[in] port HDMI In port id. - * @param[dsVideoPortResolution_t] video resolution data - */ - void HdmiInput::hdmiInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution) - { - LOGWARN("hdmiInputVideoModeUpdate [%d]", port); - - JsonObject params; - params["id"] = port; - std::stringstream locator; - locator << "hdmiin://localhost/deviceid/" << port; - params["locator"] = locator.str(); - - switch(resolution.pixelResolution) { - case dsVIDEO_PIXELRES_720x480: - params["width"] = 720; - params["height"] = 480; - break; - - case dsVIDEO_PIXELRES_720x576: - params["width"] = 720; - params["height"] = 576; - break; - - case dsVIDEO_PIXELRES_1280x720: - params["width"] = 1280; - params["height"] = 720; - break; - - case dsVIDEO_PIXELRES_1920x1080: - params["width"] = 1920; - params["height"] = 1080; - break; - - case dsVIDEO_PIXELRES_3840x2160: - params["width"] = 3840; - params["height"] = 2160; - break; - - case dsVIDEO_PIXELRES_4096x2160: - params["width"] = 4096; - params["height"] = 2160; - break; - - default: - params["width"] = 1920; - params["height"] = 1080; - break; - } - - params["progressive"] = (!resolution.interlaced); - - switch(resolution.frameRate) { - case dsVIDEO_FRAMERATE_24: - params["frameRateN"] = 24000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_25: - params["frameRateN"] = 25000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_30: - params["frameRateN"] = 30000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_50: - params["frameRateN"] = 50000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_60: - params["frameRateN"] = 60000; - params["frameRateD"] = 1000; - break; - - case dsVIDEO_FRAMERATE_23dot98: - params["frameRateN"] = 24000; - params["frameRateD"] = 1001; - break; - - case dsVIDEO_FRAMERATE_29dot97: - params["frameRateN"] = 30000; - params["frameRateD"] = 1001; - break; - - case dsVIDEO_FRAMERATE_59dot94: - params["frameRateN"] = 60000; - params["frameRateD"] = 1001; - break; - case dsVIDEO_FRAMERATE_100: - params["frameRateN"] = 100000; - params["frameRateD"] = 1000; - break; - case dsVIDEO_FRAMERATE_119dot88: - params["frameRateN"] = 120000; - params["frameRateD"] = 1001; - break; - case dsVIDEO_FRAMERATE_120: - params["frameRateN"] = 120000; - params["frameRateD"] = 1000; - break; - case dsVIDEO_FRAMERATE_200: - params["frameRateN"] = 200000; - params["frameRateD"] = 1000; - break; - case dsVIDEO_FRAMERATE_239dot76: - params["frameRateN"] = 240000; - params["frameRateD"] = 1001; - break; - case dsVIDEO_FRAMERATE_240: - params["frameRateN"] = 240000; - params["frameRateD"] = 100; - break; - default: - params["frameRateN"] = 60000; - params["frameRateD"] = 1000; - break; - } - - sendNotify(HDMIINPUT_EVENT_ON_VIDEO_MODE_UPDATED, params); - } - - void HdmiInput::getHdmiCecSinkPlugin() - { - - if(m_client == nullptr) - { - LOGINFO("getting the hdmicecsink client\n"); - string token; - - // TODO: use interfaces and remove token - auto security = m_service->QueryInterfaceByCallsign("SecurityAgent"); - if (security != nullptr) { - string payload = "http://localhost"; - if (security->CreateToken( - static_cast(payload.length()), - reinterpret_cast(payload.c_str()), - token) - == Core::ERROR_NONE) { - LOGINFO("HdmiInput got security token\n"); - } - else { - LOGINFO("HdmiInput failed to get security token\n"); - } - security->Release(); - } - else { - LOGINFO("No security agent\n"); - } - - string query = "token=" + token; - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_client = new WPEFramework::JSONRPC::LinkType(_T(HDMICECSINK_CALLSIGN_VER), (_T(HDMICECSINK_CALLSIGN_VER)), false, query); - LOGINFO("HdmiInput getHdmiCecSinkPlugin init m_client\n"); - } - } - - void HdmiInput::reportLatencyInfoToHdmiCecSink() - { - - PluginHost::IShell::state state; - if ((getServiceState(m_service, HDMICECSINK_CALLSIGN, state) == Core::ERROR_NONE) && (state == PluginHost::IShell::state::ACTIVATED)) { - LOGINFO("%s is active", HDMICECSINK_CALLSIGN); - - getHdmiCecSinkPlugin(); - if (!m_client) { - LOGERR("HdmiCecSink Initialisation failed\n"); - } - else { - JsonObject hdmiCecSinkResult; - JsonObject param; - - param["audioOutputDelay"] = std::to_string(audio_output_delay); - param["videoLatency"] = std::to_string(video_latency); - param["lowLatencyMode"] = std::to_string(lowLatencyMode); - param["audioOutputCompensated"] ="3";//hard-coded for now - LOGINFO("latency - Info: %d : %d, %d\n",audio_output_delay,video_latency,lowLatencyMode); - m_client->Invoke(2000, "setLatencyInfo", param, hdmiCecSinkResult); - if (!hdmiCecSinkResult["success"].Boolean()) { - LOGERR("HdmiCecSink Plugin returned error\n"); - } - } - } - else { - LOGERR("HdmiCecSink plugin not ready\n"); - } - - - } - void HdmiInput::dsHdmiAVLatencyEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY == eventId) - { - LOGINFO("received the latency mode change event in dsHdmiAVLatencyEventHandler\n"); - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - audio_output_delay = eventData->data.hdmi_in_av_latency.audio_output_delay; - video_latency= eventData->data.hdmi_in_av_latency.video_latency; - - // HdmiInput::_instance->hdmiInAVLatencyChange(audio_output_delay,video_latency); - LOGINFO("Latency Info Change occurs: AV Latencies -- Report to HdmiCecSink\n"); - HdmiInput::_instance->reportLatencyInfoToHdmiCecSink(); - } - } - - void HdmiInput::onGameModeEventHandler(const JsonObject& parameters) - { - LOGINFO("Entered in onGameModeEventHandler\n"); - lowLatencyMode = parameters["lowLatencyMode"].Boolean(); - LOGINFO("Low Latency Mode : %d\n", lowLatencyMode); - HdmiInput::_instance->reportLatencyInfoToHdmiCecSink(); - } - - void HdmiInput::dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmiin_hotplug_port = eventData->data.hdmi_in_connect.port; - int hdmiin_hotplug_conn = eventData->data.hdmi_in_connect.isPortConnected; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG event data:%d", hdmiin_hotplug_port); - - HdmiInput::_instance->hdmiInputHotplug(hdmiin_hotplug_port, hdmiin_hotplug_conn ? HDMI_HOT_PLUG_EVENT_CONNECTED : HDMI_HOT_PLUG_EVENT_DISCONNECTED); - } - } - - void HdmiInput::dsHdmiSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_sig_status.port; - int hdmi_in_signal_status = eventData->data.hdmi_in_sig_status.status; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS event port: %d, signal status: %d", hdmi_in_port,hdmi_in_signal_status); - - HdmiInput::_instance->hdmiInputSignalChange(hdmi_in_port, hdmi_in_signal_status); - - } - } - - void HdmiInput::dsHdmiStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_status.port; - bool hdmi_in_status = eventData->data.hdmi_in_status.isPresented; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS event port: %d, started: %d", hdmi_in_port,hdmi_in_status); - - HdmiInput::_instance->hdmiInputStatusChange(hdmi_in_port, hdmi_in_status); - - } - } - - void HdmiInput::dsHdmiVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_video_mode.port; - dsVideoPortResolution_t resolution = {}; - resolution.pixelResolution = eventData->data.hdmi_in_video_mode.resolution.pixelResolution; - resolution.interlaced = eventData->data.hdmi_in_video_mode.resolution.interlaced; - resolution.frameRate = eventData->data.hdmi_in_video_mode.resolution.frameRate; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE event port: %d, pixelResolution: %d, interlaced : %d, frameRate: %d \n", hdmi_in_port,resolution.pixelResolution, resolution.interlaced, resolution.frameRate); - - HdmiInput::_instance->hdmiInputVideoModeUpdate(hdmi_in_port, resolution); - - } - } - - void HdmiInput::dsHdmiGameFeatureStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_allm_mode.port; - bool allm_mode = eventData->data.hdmi_in_allm_mode.allm_mode; - LOGWARN("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS event port: %d, ALLM Mode: %d", hdmi_in_port,allm_mode); - - HdmiInput::_instance->hdmiInputALLMChange(hdmi_in_port, allm_mode); - } - } - - void HdmiInput::hdmiInputALLMChange( int port , bool allm_mode) - { - JsonObject params; - params["id"] = port; - params["gameFeature"] = "ALLM"; - params["mode"] = allm_mode; - - sendNotify(HDMIINPUT_EVENT_ON_GAME_FEATURE_STATUS_CHANGED, params); - } - - void HdmiInput::dsHdmiAviContentTypeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len) - { - if(!HdmiInput::_instance) - return; - - if (IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE == eventId) - { - IARM_Bus_DSMgr_EventData_t *eventData = (IARM_Bus_DSMgr_EventData_t *)data; - int hdmi_in_port = eventData->data.hdmi_in_content_type.port; - int avi_content_type = eventData->data.hdmi_in_content_type.aviContentType; - LOGINFO("Received IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE event port: %d, Content Type : %d", hdmi_in_port,avi_content_type); - HdmiInput::_instance->hdmiInputAviContentTypeChange(hdmi_in_port, avi_content_type); - } - } - - void HdmiInput::hdmiInputAviContentTypeChange( int port , int content_type) - { - JsonObject params; - params["id"] = port; - params["aviContentType"] = content_type; - sendNotify(HDMIINPUT_EVENT_ON_AVI_CONTENT_TYPE_CHANGED, params); - } - - uint32_t HdmiInput::getSupportedGameFeatures(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - vector supportedFeatures; - try - { - device::HdmiInput::getInstance().getSupportedGameFeatures (supportedFeatures); - for (size_t i = 0; i < supportedFeatures.size(); i++) - { - LOGINFO("Supported Game Feature [%d]: %s\n",(int)i,supportedFeatures.at(i).c_str()); - } - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION0(); - } - - if (supportedFeatures.empty()) { - returnResponse(false); - } - else { - setResponseArray(response, "supportedGameFeatures", supportedFeatures); - returnResponse(true); - } - } - - uint32_t HdmiInput::getHdmiGameFeatureStatusWrapper(const JsonObject& parameters, JsonObject& response) - { - string sPortId = parameters["portId"].String(); - string sGameFeature = parameters["gameFeature"].String(); - int portId = 0; - - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - returnIfParamNotFound(parameters, "gameFeature"); - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - if (strcmp (sGameFeature.c_str(), "ALLM") == 0) - { - bool allm = getHdmiALLMStatus(portId); - LOGWARN("HdmiInput::getHdmiGameFeatureStatusWrapper ALLM MODE:%d", allm); - response["mode"] = allm; - } - else - { - LOGWARN("HdmiInput::getHdmiGameFeatureStatusWrapper Mode is not supported. Supported mode: ALLM"); - response["message"] = "Mode is not supported. Supported mode: ALLM"; - returnResponse(false); - } - returnResponse(true); - } - - bool HdmiInput::getHdmiALLMStatus(int iPort) - { - bool allm = false; - - try - { - device::HdmiInput::getInstance().getHdmiALLMStatus (iPort, &allm); - LOGWARN("HdmiInput::getHdmiALLMStatus ALLM MODE: %d", allm); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return allm; - } - - uint32_t HdmiInput::getRawHDMISPDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - - string sPortId = parameters["portId"].String(); - int portId = 0; - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - string spdInfo = getRawHDMISPD (portId); - response["HDMISPD"] = spdInfo; - if (spdInfo.empty()) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - uint32_t HdmiInput::getHDMISPDWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - - string sPortId = parameters["portId"].String(); - int portId = 0; - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - string spdInfo = getHDMISPD (portId); - response["HDMISPD"] = spdInfo; - if (spdInfo.empty()) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - std::string HdmiInput::getRawHDMISPD(int iPort) - { - LOGINFO("HdmiInput::getHDMISPDInfo"); - vector spdVect({'u','n','k','n','o','w','n' }); - std::string spdbase64 = ""; - try - { - LOGWARN("HdmiInput::getHDMISPDInfo"); - vector spdVect2; - device::HdmiInput::getInstance().getHDMISPDInfo(iPort, spdVect2); - spdVect = spdVect2;//edidVec must be "unknown" unless we successfully get to this line - - //convert to base64 - uint16_t size = min(spdVect.size(), (size_t)numeric_limits::max()); - - LOGWARN("HdmiInput::getHDMISPD size:%u spdVec.size:%d", size, (int)spdVect.size()); - - if(spdVect.size() > (size_t)numeric_limits::max()) { - LOGERR("Size too large to use ToString base64 wpe api"); - return spdbase64; - } - - LOGINFO("------------getHDMISPD: "); - for (unsigned int itr =0; itr < spdVect.size(); itr++) { - LOGINFO("%02X ", spdVect[itr]); - } - Core::ToString((uint8_t*)&spdVect[0], size, false, spdbase64); - - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return spdbase64; - } - - std::string HdmiInput::getHDMISPD(int iPort) - { - LOGINFO("HdmiInput::getHDMISPDInfo"); - vector spdVect({'u','n','k','n','o','w','n' }); - std::string spdbase64 = ""; - try - { - LOGWARN("HdmiInput::getHDMISPDInfo"); - vector spdVect2; - device::HdmiInput::getInstance().getHDMISPDInfo(iPort, spdVect2); - spdVect = spdVect2;//edidVec must be "unknown" unless we successfully get to this line - - //convert to base64 - uint16_t size = min(spdVect.size(), (size_t)numeric_limits::max()); - - LOGWARN("HdmiInput::getHDMISPD size:%u spdVec.size:%d", size, (int)spdVect.size()); - - if(spdVect.size() > (size_t)numeric_limits::max()) { - LOGERR("Size too large to use ToString base64 wpe api"); - return spdbase64; - } - - LOGINFO("------------getHDMISPD: "); - for (unsigned int itr =0; itr < spdVect.size(); itr++) { - LOGINFO("%02X ", spdVect[itr]); - } - if (spdVect.size() > 0) { - struct dsSpd_infoframe_st pre; - memcpy(&pre,spdVect.data(),sizeof(struct dsSpd_infoframe_st)); - - char str[200] = {0}; - snprintf(str, sizeof(str), "Packet Type:%02X,Version:%u,Length:%u,vendor name:%s,product des:%s,source info:%02X" -,pre.pkttype,pre.version,pre.length,pre.vendor_name,pre.product_des,pre.source_info); - spdbase64 = str; - } - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return spdbase64; - } - - uint32_t HdmiInput::setEdidVersionWrapper(const JsonObject& parameters, JsonObject& response) - { - int portId = 0; - - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - returnIfParamNotFound(parameters, "edidVersion"); - string sPortId = parameters["portId"].String(); - string sVersion = parameters["edidVersion"].String(); - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - int edidVer = -1; - if (strcmp (sVersion.c_str(), "HDMI1.4") == 0) { - edidVer = HDMI_EDID_VER_14; - } - else if (strcmp (sVersion.c_str(), "HDMI2.0") == 0) { - edidVer = HDMI_EDID_VER_20; - } - - if (edidVer < 0) { - returnResponse(false); - } - bool result = setEdidVersion (portId, edidVer); - if (result == false) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - uint32_t HdmiInput::getAVLatency(const JsonObject& parameters, JsonObject& response) - { - int audio_output_delay = 0; - int video_latency = 0; - - LOGINFO("calling HdmiInput::getHdmiDAL_AudioVideoLatency \n"); - try - { - device::HdmiInput::getInstance().getAVLatency(&audio_output_delay,&video_latency); - LOGINFO("HdmiInput::getHdmiDAL_AudioVideoLatency Audio Latency: %d, Video Latency: %d\n", audio_output_delay,video_latency); - response["AudioLatency"] = audio_output_delay; - response["VideoLatency"] = video_latency; - returnResponse(true); - } - catch(const device::Exception& err) - { - std::string api = "getHdmiDAL_AudioVideoLatency"; - LOG_DEVICE_EXCEPTION1(std::string(api)); - response["message"] = "Invalid response from getHdmiDAL_AudioVideoLatency"; - LOGINFO("ERROR:HdmiInput::getHdmiDAL_AudioVideoLatency Audio Latency: %d, Video Latency: %d\n", audio_output_delay,video_latency); - returnResponse(false); - } - - } - uint32_t HdmiInput::getHdmiVersionWrapper(const JsonObject& parameters, JsonObject& response) - { - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - string sPortId = parameters["portId"].String(); - int portId = 0; - - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - dsHdmiMaxCapabilityVersion_t hdmiCapVersion = HDMI_COMPATIBILITY_VERSION_14; - - try { - device::HdmiInput::getInstance().getHdmiVersion(portId, &(hdmiCapVersion)); - LOGWARN("HdmiInput::getHdmiVersion Hdmi Version:%d", hdmiCapVersion); - } - catch (const device::Exception& err) { - LOG_DEVICE_EXCEPTION1(std::to_string(portId)); - returnResponse(false); - } - - - switch ((int)hdmiCapVersion){ - case HDMI_COMPATIBILITY_VERSION_14: - response["HdmiCapabilityVersion"] = "1.4"; - break; - case HDMI_COMPATIBILITY_VERSION_20: - response["HdmiCapabilityVersion"] = "2.0"; - break; - case HDMI_COMPATIBILITY_VERSION_21: - response["HdmiCapabilityVersion"] = "2.1"; - break; - } - - - if(hdmiCapVersion == HDMI_COMPATIBILITY_VERSION_MAX) - { - returnResponse(false); - }else{ - returnResponse(true); - } - } - - uint32_t HdmiInput::getServiceState(PluginHost::IShell* shell, const string& callsign, PluginHost::IShell::state& state) - { - LOGINFO("entering getServiceState\n"); - uint32_t result; - auto interface = shell->QueryInterfaceByCallsign(callsign); - LOGINFO("received interface:\n"); - - if (interface == nullptr) { - result = Core::ERROR_UNAVAILABLE; - LOGINFO("no IShell\n"); - } - else { - result = Core::ERROR_NONE; - state = interface->State(); - LOGINFO("IShell state\n"); - interface->Release(); - } - LOGINFO("at the end of getSErviceState\n"); - return result; - } - - void HdmiInput::getControlSettingsPlugin() - { - LOGINFO("entering getControlSettingsPlugin\n"); - if(m_tv_client == nullptr) - { - LOGINFO("in if case\n"); - string token; - - // TODO: use interfaces and remove token - auto security = m_service->QueryInterfaceByCallsign("SecurityAgent"); - LOGINFO("received security code\n"); - if (security != nullptr) { - string payload = "http://localhost"; - if (security->CreateToken( - static_cast(payload.length()), - reinterpret_cast(payload.c_str()), - token) - == Core::ERROR_NONE) - { - LOGINFO("ControlSettings got security token\n"); - } - else { - LOGINFO("ControlSettings failed to get security token\n"); - } - security->Release(); - } - else { - LOGINFO("No security agent\n"); - } - - string query = "token=" + token; - Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), (_T("127.0.0.1:9998"))); - m_tv_client = new WPEFramework::JSONRPC::LinkType(_T(TVSETTINGS_CALLSIGN_VER), (_T(TVSETTINGS_CALLSIGN_VER)), false, query); - LOGINFO("HdmiInput getControlSettingsPlugin init m_tv_client\n"); - } - } - - uint32_t HdmiInput::getTVLowLatencyMode(const JsonObject& parameters, JsonObject& response) - { - PluginHost::IShell::state state; - LOGINFOMETHOD(); - if ((getServiceState(m_service, TVSETTINGS_CALLSIGN, state) == Core::ERROR_NONE) && (state == PluginHost::IShell::state::ACTIVATED)) - { - LOGINFO("%s is active", TVSETTINGS_CALLSIGN); - - getControlSettingsPlugin(); - if(!m_tv_client) - { - LOGERR("TV Settings Initialisation failed\n"); - } - else{ - - JsonObject result; - JsonObject param; - - - int llmode = 0; - m_tv_client->Invoke(2000, "getLowLatencyState", param, result); - - if(result["success"].Boolean()) - { - string value = result.HasLabel("lowLatencyState") ? result["lowLatencyState"].String() : ""; - llmode = stoi(value); - - LOGINFO("value of the result: %d\n",llmode); - - if(llmode){ - response["lowLatencyMode"] = true; - LOGINFO("Low Latency Mode is enabled\n"); - returnResponse(true); - } - else{ - response["lowLatencyMode"] = false; - LOGINFO("Low Latency Mode is disabled\n"); - returnResponse(true); - } - } - else{ - - LOGERR("control settings Plugin returned error\n"); - returnResponse(false); - - } - } - } - else - { - LOGERR("control settings Plugin not ready\n"); - returnResponse(false); - } - - returnResponse(true); - } - - int HdmiInput::setEdidVersion(int iPort, int iEdidVer) - { - bool ret = true; - try - { - device::HdmiInput::getInstance().setEdidVersion (iPort, iEdidVer); - LOGWARN("HdmiInput::setEdidVersion EDID Version:%d", iEdidVer); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - ret = false; - } - return ret; - } - - uint32_t HdmiInput::getEdidVersionWrapper(const JsonObject& parameters, JsonObject& response) - { - string sPortId = parameters["portId"].String(); - int portId = 0; - - LOGINFOMETHOD(); - returnIfParamNotFound(parameters, "portId"); - try { - portId = stoi(sPortId); - }catch (const std::exception& err) { - LOGWARN("sPortId invalid paramater: %s ", sPortId.c_str()); - returnResponse(false); - } - - int edidVer = getEdidVersion (portId); - switch (edidVer) - { - case HDMI_EDID_VER_14: - response["edidVersion"] = "HDMI1.4"; - break; - case HDMI_EDID_VER_20: - response["edidVersion"] = "HDMI2.0"; - break; - } - - if (edidVer < 0) { - returnResponse(false); - } - else { - returnResponse(true); - } - } - - int HdmiInput::getEdidVersion(int iPort) - { - int edidVersion = -1; - - try - { - device::HdmiInput::getInstance().getEdidVersion (iPort, &edidVersion); - LOGWARN("HdmiInput::getEdidVersion EDID Version:%d", edidVersion); - } - catch (const device::Exception& err) - { - LOG_DEVICE_EXCEPTION1(std::to_string(iPort)); - } - return edidVersion; - } - - } // namespace Plugin -} // namespace WPEFramework diff --git a/HdmiInput/HdmiInput.h b/HdmiInput/HdmiInput.h deleted file mode 100644 index ff93202e..00000000 --- a/HdmiInput/HdmiInput.h +++ /dev/null @@ -1,139 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#pragma once - -#include "libIBus.h" - -#include "Module.h" -#include "dsTypes.h" - -#define DEFAULT_PRIM_VOL_LEVEL 25 -#define MAX_PRIM_VOL_LEVEL 100 -#define DEFAULT_INPUT_VOL_LEVEL 100 - -namespace WPEFramework { - - namespace Plugin { - - // This is a server for a JSONRPC communication channel. - // For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC. - // By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher. - // This realization of this interface implements, by default, the following methods on this plugin - // - exists - // - register - // - unregister - // Any other methood to be handled by this plugin can be added can be added by using the - // templated methods Register on the PluginHost::JSONRPC class. - // As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC, - // this class exposes a public method called, Notify(), using this methods, all subscribed clients - // will receive a JSONRPC message as a notification, in case this method is called. - class HdmiInput : public PluginHost::IPlugin, public PluginHost::JSONRPC { - private: - - // We do not allow this plugin to be copied !! - HdmiInput(const HdmiInput&) = delete; - HdmiInput& operator=(const HdmiInput&) = delete; - - void InitializeIARM(); - void DeinitializeIARM(); - int m_primVolume; - int m_inputVolume; //Player Volume - - //Begin methods - uint32_t getHDMIInputDevicesWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t writeEDIDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t readEDIDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getRawHDMISPDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getHDMISPDWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t setEdidVersionWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getEdidVersionWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t startHdmiInput(const JsonObject& parameters, JsonObject& response); - uint32_t stopHdmiInput(const JsonObject& parameters, JsonObject& response); - uint32_t setMixerLevels(const JsonObject& parameters, JsonObject& response); - uint32_t setVideoRectangleWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getSupportedGameFeatures(const JsonObject& parameters, JsonObject& response); - uint32_t getHdmiGameFeatureStatusWrapper(const JsonObject& parameters, JsonObject& response); - uint32_t getAVLatency(const JsonObject& parameters, JsonObject& response); - uint32_t getTVLowLatencyMode(const JsonObject& parameters, JsonObject& response); - uint32_t getHdmiVersionWrapper(const JsonObject& parameters, JsonObject& response); - //End methods - - JsonArray getHDMIInputDevices(); - void writeEDID(int deviceId, std::string message); - std::string readEDID(int iPort); - std::string getRawHDMISPD(int iPort); - std::string getHDMISPD(int iPort); - int setEdidVersion(int iPort, int iEdidVer); - int getEdidVersion(int iPort); - bool getHdmiALLMStatus(int iPort); - - bool setVideoRectangle(int x, int y, int width, int height); - - void getControlSettingsPlugin(); - void getHdmiCecSinkPlugin(void); - PluginHost::IShell* m_service = nullptr; - WPEFramework::JSONRPC::LinkType* m_client; - WPEFramework::JSONRPC::LinkType* m_tv_client; - std::vector m_clientRegisteredEventNames; - uint32_t getServiceState(PluginHost::IShell* shell, const string& callsign, PluginHost::IShell::state& state); - - void hdmiInputHotplug( int input , int connect); - static void dsHdmiEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputSignalChange( int port , int signalStatus); - static void dsHdmiSignalStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputStatusChange( int port , bool isPresented); - static void dsHdmiStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputVideoModeUpdate( int port , dsVideoPortResolution_t resolution); - static void dsHdmiVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputALLMChange( int port , bool allmMode); - static void dsHdmiGameFeatureStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInputAviContentTypeChange(int port, int content_type); - static void dsHdmiAviContentTypeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void hdmiInAVLatencyChange(int audio_output_delay,int video_latency); - static void dsHdmiAVLatencyEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); - - void reportLatencyInfoToHdmiCecSink(); - void onGameModeEventHandler(const JsonObject& parameters); - uint32_t subscribeForTvMgrEvent(const char* eventName); - public: - HdmiInput(); - virtual ~HdmiInput(); - virtual const string Initialize(PluginHost::IShell* shell) override; - virtual void Deinitialize(PluginHost::IShell* service) override; - virtual string Information() const override { return {}; } - - void terminate(); - - BEGIN_INTERFACE_MAP(HdmiInput) - INTERFACE_ENTRY(PluginHost::IPlugin) - INTERFACE_ENTRY(PluginHost::IDispatcher) - END_INTERFACE_MAP - - public: - static HdmiInput* _instance; - }; - } // namespace Plugin -} // namespace WPEFramework diff --git a/HdmiInput/Module.cpp b/HdmiInput/Module.cpp deleted file mode 100644 index ce759b61..00000000 --- a/HdmiInput/Module.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include "Module.h" - -MODULE_NAME_DECLARATION(BUILD_REFERENCE) diff --git a/HdmiInput/Module.h b/HdmiInput/Module.h deleted file mode 100644 index 54e672c3..00000000 --- a/HdmiInput/Module.h +++ /dev/null @@ -1,29 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2019 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#pragma once -#ifndef MODULE_NAME -#define MODULE_NAME Plugin_HdmiInput -#endif - -#include -#include - -#undef EXTERNAL -#define EXTERNAL diff --git a/HdmiInput/README.md b/HdmiInput/README.md deleted file mode 100644 index 998e3280..00000000 --- a/HdmiInput/README.md +++ /dev/null @@ -1,9 +0,0 @@ ------------------ -Build: - -bitbake wpeframework-service-plugins - ------------------ -Test: - -curl --header "Content-Type: application/json" --request POST --data '{"jsonrpc":"2.0","id":"3","method": "HdmiInput.1."}' http://127.0.0.1:9998/jsonrpc diff --git a/HdmiInput/cmake/FindDS.cmake b/HdmiInput/cmake/FindDS.cmake deleted file mode 100644 index 926c02e0..00000000 --- a/HdmiInput/cmake/FindDS.cmake +++ /dev/null @@ -1,57 +0,0 @@ -# If not stated otherwise in this file or this component's license file the -# following copyright and licenses apply: -# -# Copyright 2020 RDK Management -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# - Try to find Display Settings library -# Once done this will define -# DS_FOUND - System has DS -# DS_INCLUDE_DIRS - The DS include directories -# DS_LIBRARIES - The libraries needed to use DS -# DS_FLAGS - The flags needed to use DS -# - -find_package(PkgConfig) - -find_library(DS_LIBRARIES NAMES ds) -find_path(DS_INCLUDE_DIRS NAMES hdmiIn.hpp PATH_SUFFIXES rdk/ds) - -set(DS_LIBRARIES ${DS_LIBRARIES}) -set(DS_LIBRARIES ${DS_LIBRARIES} CACHE PATH "Path to DS library") -set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS}) -set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS} CACHE PATH "Path to DS include") - - -find_library(DS_LIBRARIES NAMES ds) -#find_library(DSHAL_LIBRARIES NAMES dshalcli) -#find_path(DS_INCLUDE_DIRS NAMES manager.hpp PATH_SUFFIXES rdk/ds) -find_path(DSHAL_INCLUDE_DIRS NAMES dsTypes.h PATH_SUFFIXES rdk/halif/ds-hal) -find_path(DSRPC_INCLUDE_DIRS NAMES dsMgr.h PATH_SUFFIXES rdk/ds-rpc) - -#set(DS_LIBRARIES ${DS_LIBRARIES} ${DSHAL_LIBRARIES}) -#set(DS_LIBRARIES ${DS_LIBRARIES} CACHE PATH "Path to DS library") -set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS} ${DSHAL_INCLUDE_DIRS} ${DSRPC_INCLUDE_DIRS}) -#set(DS_INCLUDE_DIRS ${DS_INCLUDE_DIRS} CACHE PATH "Path to DS include") - - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(DS DEFAULT_MSG DS_INCLUDE_DIRS DS_LIBRARIES) - -mark_as_advanced( - DS_FOUND - DS_INCLUDE_DIRS - DS_LIBRARIES - DS_LIBRARY_DIRS - DS_FLAGS) diff --git a/HdmiInput/cmake/FindIARMBus.cmake b/HdmiInput/cmake/FindIARMBus.cmake deleted file mode 100644 index bc716bcd..00000000 --- a/HdmiInput/cmake/FindIARMBus.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# If not stated otherwise in this file or this component's license file the -# following copyright and licenses apply: -# -# Copyright 2020 RDK Management -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# - Try to find IARMBus -# Once done this will define -# IARMBUS_FOUND - System has IARMBus -# IARMBUS_INCLUDE_DIRS - The IARMBus include directories -# IARMBUS_LIBRARIES - The libraries needed to use IARMBus -# IARMBUS_FLAGS - The flags needed to use IARMBus -# - -find_package(PkgConfig) - -find_library(IARMBUS_LIBRARIES NAMES IARMBus) -find_path(IARMIR_INCLUDE_DIRS NAMES sysMgr.h PATH_SUFFIXES rdk/iarmmgrs/sysmgr) - -set(IARMBUS_LIBRARIES ${IARMBUS_LIBRARIES} CACHE PATH "Path to IARMBus library") -set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${SYSMGR_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS../sysmgr} ) -set(IARMBUS_INCLUDE_DIRS ${IARMBUS_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS} ${SYSMGR_INCLUDE_DIRS} ${IARMIR_INCLUDE_DIRS../sysmgr} CACHE PATH "Path to IARMBus include") - - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(IARMBUS DEFAULT_MSG IARMBUS_INCLUDE_DIRS IARMBUS_LIBRARIES) - -mark_as_advanced( - IARMBUS_FOUND - IARMBUS_INCLUDE_DIRS - IARMBUS_LIBRARIES - IARMBUS_LIBRARY_DIRS - IARMBUS_FLAGS) diff --git a/Tests/L1Tests/CMakeLists.txt b/Tests/L1Tests/CMakeLists.txt index ead1b3c2..3d6639c9 100755 --- a/Tests/L1Tests/CMakeLists.txt +++ b/Tests/L1Tests/CMakeLists.txt @@ -106,9 +106,6 @@ set (HDCPPROFILE_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdcpProfile set (HDCPPROFILE_LIBS ${NAMESPACE}HdcpProfile ${NAMESPACE}HdcpProfileImplementation) add_plugin_test_ex(PLUGIN_HDCPPROFILE tests/test_HdcpProfile.cpp "${HDCPPROFILE_INC}" "${HDCPPROFILE_LIBS}") -# PLUGIN_HDMIINPUT -set (HDMIINPUT_INC ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/HdmiInput ${CMAKE_SOURCE_DIR}/../entservices-inputoutput/helpers) -add_plugin_test_ex(PLUGIN_HDMIINPUT tests/test_HdmiInput.cpp "${HDMIINPUT_INC}" "${NAMESPACE}HdmiInput") # PLUGIN_HDMICEC2 add_plugin_test_ex(PLUGIN_HDMICEC2 tests/test_HdmiCec2.cpp "../../HdmiCec_2" "${NAMESPACE}HdmiCec_2") diff --git a/Tests/L1Tests/tests/test_HdmiInput.cpp b/Tests/L1Tests/tests/test_HdmiInput.cpp deleted file mode 100644 index 9b0b1f66..00000000 --- a/Tests/L1Tests/tests/test_HdmiInput.cpp +++ /dev/null @@ -1,861 +0,0 @@ -/** -* If not stated otherwise in this file or this component's LICENSE -* file the following copyright and licenses apply: -* -* Copyright 2024 RDK Management -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -**/ - -#include - -#include "HdmiInput.h" - -#include "FactoriesImplementation.h" - -#include "HdmiInputMock.h" -#include "IarmBusMock.h" -#include "ServiceMock.h" - -#include "dsMgr.h" -#include "ThunderPortability.h" - -using namespace WPEFramework; - -using ::testing::NiceMock; - -class HdmiInputTest : public ::testing::Test { -protected: - Core::ProxyType plugin; - Core::JSONRPC::Handler& handler; - Core::JSONRPC::Handler& handlerV2; - DECL_CORE_JSONRPC_CONX connection; - string response; - - HdmiInputTest() - : plugin(Core::ProxyType::Create()) - , handler(*(plugin)) - , handlerV2(*(plugin->GetHandler(2))) - , INIT_CONX(1, 0) - { - } - virtual ~HdmiInputTest() = default; -}; - -class HdmiInputDsTest : public HdmiInputTest { -protected: - HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; - - HdmiInputDsTest() - : HdmiInputTest() - { - p_hdmiInputImplMock = new NiceMock ; - device::HdmiInput::setImpl(p_hdmiInputImplMock); - } - virtual ~HdmiInputDsTest() override - { - device::HdmiInput::setImpl(nullptr); - if (p_hdmiInputImplMock != nullptr) - { - delete p_hdmiInputImplMock; - p_hdmiInputImplMock = nullptr; - } - } -}; - -class HdmiInputInitializedTest : public HdmiInputTest { -protected: - IarmBusImplMock *p_iarmBusImplMock = nullptr ; - IARM_EventHandler_t dsHdmiEventHandler; - IARM_EventHandler_t dsHdmiStatusEventHandler; - IARM_EventHandler_t dsHdmiSignalStatusEventHandler; - IARM_EventHandler_t dsHdmiVideoModeEventHandler; - IARM_EventHandler_t dsHdmiGameFeatureStatusEventHandler; - - // NiceMock service; - ServiceMock service; - - HdmiInputInitializedTest() - : HdmiInputTest() - { - p_iarmBusImplMock = new NiceMock ; - IarmBus::setImpl(p_iarmBusImplMock); - - EXPECT_CALL(service, QueryInterfaceByCallsign(::testing::_, ::testing::_)) - .Times(::testing::AnyNumber()) - .WillRepeatedly(::testing::Invoke( - [&](const uint32_t, const string& name) -> void* { - return nullptr; - })); - ON_CALL(*p_iarmBusImplMock, IARM_Bus_RegisterEventHandler(::testing::_, ::testing::_, ::testing::_)) - .WillByDefault(::testing::Invoke( - [&](const char* ownerName, IARM_EventId_t eventId, IARM_EventHandler_t handler) { - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiStatusEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiSignalStatusEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiVideoModeEventHandler = handler; - } - if ((string(IARM_BUS_DSMGR_NAME) == string(ownerName)) && (eventId == IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS)) { - EXPECT_TRUE(handler != nullptr); - dsHdmiGameFeatureStatusEventHandler = handler; - } - return IARM_RESULT_SUCCESS; - })); - - EXPECT_EQ(string(""), plugin->Initialize(&service)); - } - virtual ~HdmiInputInitializedTest() override - { - plugin->Deinitialize(&service); - - IarmBus::setImpl(nullptr); - if (p_iarmBusImplMock != nullptr) - { - delete p_iarmBusImplMock; - p_iarmBusImplMock = nullptr; - } - } -}; - - -class HdmiInputInitializedEventTest : public HdmiInputInitializedTest { -protected: - NiceMock service; - NiceMock factoriesImplementation; - PLUGINHOST_DISPATCHER* dispatcher; - Core::JSONRPC::Message message; - - HdmiInputInitializedEventTest() - : HdmiInputInitializedTest() - { - PluginHost::IFactories::Assign(&factoriesImplementation); - - dispatcher = static_cast( - plugin->QueryInterface(PLUGINHOST_DISPATCHER_ID)); - dispatcher->Activate(&service); - } - - virtual ~HdmiInputInitializedEventTest() override - { - dispatcher->Deactivate(); - dispatcher->Release(); - - PluginHost::IFactories::Assign(nullptr); - } -}; - -class HdmiInputInitializedEventDsTest : public HdmiInputInitializedEventTest { -protected: - HdmiInputImplMock *p_hdmiInputImplMock = nullptr ; - - HdmiInputInitializedEventDsTest() - : HdmiInputInitializedEventTest() - { - p_hdmiInputImplMock = new NiceMock ; - device::HdmiInput::setImpl(p_hdmiInputImplMock); - } - - virtual ~HdmiInputInitializedEventDsTest() override - { - device::HdmiInput::setImpl(nullptr); - if (p_hdmiInputImplMock != nullptr) - { - delete p_hdmiInputImplMock; - p_hdmiInputImplMock = nullptr; - } - } -}; - -TEST_F(HdmiInputTest, RegisteredMethods) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHDMIInputDevices"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("writeEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("readEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getRawHDMISPD"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHDMISPD"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("setEdidVersion"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getEdidVersion"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("startHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("stopHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("setVideoRectangle"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getSupportedGameFeatures"))); - EXPECT_EQ(Core::ERROR_NONE, handler.Exists(_T("getHdmiGameFeatureStatus"))); - - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHDMIInputDevices"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("writeEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("readEDID"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("startHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("stopHdmiInput"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("setVideoRectangle"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getSupportedGameFeatures"))); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Exists(_T("getHdmiGameFeatureStatus"))); -} - -TEST_F(HdmiInputDsTest, getHDMIInputDevices) -{ - - ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) - .WillByDefault(::testing::Return(1)); - ON_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) - .WillByDefault(::testing::Return(true)); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHDMIInputDevices"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"devices\":[{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}],\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, writeEDIDEmpty) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("writeEDID"), _T("{\"message\": \"message\"}"), response)); - EXPECT_EQ(response, string("")); -} - - -TEST_F(HdmiInputDsTest, writeEDID) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("writeEDID"), _T("{\"deviceId\": 0, \"message\": \"message\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, writeEDIDInvalid) -{ - ON_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector &edidVec2) { - edidVec2 = std::vector({ 't', 'e', 's', 't' }); - })); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("readEDID"), _T("{\"deviceId\": \"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, readEDID) -{ - ON_CALL(*p_hdmiInputImplMock, getEDIDBytesInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector &edidVec2) { - edidVec2 = std::vector({ 't', 'e', 's', 't' }); - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("readEDID"), _T("{\"deviceId\": 0}"), response)); - EXPECT_EQ(response, string("{\"EDID\":\"dGVzdA==\",\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, getRawHDMISPD) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = { 't', 'e', 's', 't' }; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getRawHDMISPD"), _T("{\"portId\":0}"), response)); - EXPECT_EQ(response, string("{\"HDMISPD\":\"dGVzdA\",\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getRawHDMISPDInvalid) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = { 't', 'e', 's', 't' }; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getRawHDMISPD"), _T("{\"portId\":\"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, getHDMISPD) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = {'0','1','2','n', 'p', '1','2','3','4','5','6','7',0,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',0,'q','r'}; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getHDMISPD"), _T("{\"portId\":0}"), response)); - EXPECT_EQ(response, string("{\"HDMISPD\":\"Packet Type:30,Version:49,Length:50,vendor name:1234567,product des:abcdefghijklmno,source info:71\",\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getHDMISPDInvalid) -{ - ON_CALL(*p_hdmiInputImplMock, getHDMISPDInfo(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, std::vector& edidVec2) { - edidVec2 = {'0','1','2','n', 'p', '0'}; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getHDMISPD"), _T("{\"portId\":\"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - - -TEST_F(HdmiInputDsTest, setEdidVersionInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"b\", \"edidVersion\":\"HDMI1.4\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, setEdidVersion14) -{ - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"HDMI1.4\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, setEdidVersion20) -{ - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"HDMI2.0\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} -TEST_F(HdmiInputDsTest, setEdidVersionEmpty) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("setEdidVersion"), _T("{\"portId\": \"0\", \"edidVersion\":\"\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, getEdidVersionInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"b\", \"edidVersion\":\"HDMI1.4\"}"), response)); - EXPECT_EQ(response, string("")); -} -TEST_F(HdmiInputDsTest, getEdidVersionVer14) -{ - ON_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iPort, int *edidVersion) { - *edidVersion = 0; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI1.4\",\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getEdidVersionVer20) -{ - ON_CALL(*p_hdmiInputImplMock, getEdidVersion(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iPort, int *edidVersion) { - *edidVersion = 1; - })); - EXPECT_EQ(Core::ERROR_NONE, handlerV2.Invoke(connection, _T("getEdidVersion"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"edidVersion\":\"HDMI2.0\",\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, startHdmiInputInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"b\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, startHdmiInput) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, stopHdmiInput) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopHdmiInput"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - -TEST_F(HdmiInputDsTest, setVideoRectangleInvalid) -{ - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": \"b\",\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, setVideoRectangle) -{ - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("setVideoRectangle"), _T("{\"x\": 0,\"y\": 0,\"w\": 1920,\"h\": 1080}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, getSupportedGameFeatures) -{ - ON_CALL(*p_hdmiInputImplMock, getSupportedGameFeatures(::testing::_)) - .WillByDefault(::testing::Invoke( - [&](std::vector &supportedFeatures) { - supportedFeatures = {"ALLM"}; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getSupportedGameFeatures"), _T("{\"supportedGameFeatures\": \"ALLM\"}"), response)); - EXPECT_EQ(response, string("{\"supportedGameFeatures\":[\"ALLM\"],\"success\":true}")); -} - - -TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatusInvalidPort) -{ - ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, bool *allm) { - *allm = true; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"b\",\"gameFeature\": \"ALLM\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatus) -{ - ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, bool *allm) { - *allm = true; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"0\",\"gameFeature\": \"ALLM\"}"), response)); - EXPECT_EQ(response, string("{\"mode\":true,\"success\":true}")); -} -TEST_F(HdmiInputDsTest, getHdmiGameFeatureStatusInvalidFeature) -{ - ON_CALL(*p_hdmiInputImplMock, getHdmiALLMStatus(::testing::_,::testing::_)) - .WillByDefault(::testing::Invoke( - [&](int iport, bool *allm) { - *allm = true; - })); - EXPECT_EQ(Core::ERROR_GENERAL, handler.Invoke(connection, _T("getHdmiGameFeatureStatus"), _T("{\"portId\": \"0\",\"gameFeature\": \"Invalid\"}"), response)); - EXPECT_EQ(response, string("")); -} - -TEST_F(HdmiInputInitializedEventDsTest, onDevicesChanged) -{ - ASSERT_TRUE(dsHdmiEventHandler != nullptr); - ON_CALL(*p_hdmiInputImplMock, getNumberOfInputs()) - .WillByDefault(::testing::Return(1)); - ON_CALL(*p_hdmiInputImplMock, isPortConnected(::testing::_)) - .WillByDefault(::testing::Return(true)); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onDevicesChanged.onDevicesChanged\",\"params\":{\"devices\":[{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"connected\":\"true\"}]}}"))); - - return Core::ERROR_NONE; - })); - - - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_connect.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_connect.isPortConnected = true; - - EVENT_SUBSCRIBE(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); - - dsHdmiEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onDevicesChanged"), _T("client.events.onDevicesChanged"), message); -} - -TEST_F(HdmiInputInitializedEventDsTest, onInputStatusChangeOn) -{ - ASSERT_TRUE(dsHdmiStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"started\",\"plane\":0}}"))); - return Core::ERROR_NONE; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("startHdmiInput"), _T("{\"portId\": \"0\"}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_status.isPresented = true; - - EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); - - dsHdmiStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onInputStatusChangeOff) -{ - ASSERT_TRUE(dsHdmiStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onInputStatusChanged.onInputStatusChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"status\":\"stopped\",\"plane\":-1}}"))); - return Core::ERROR_NONE; - })); - EXPECT_EQ(Core::ERROR_NONE, handler.Invoke(connection, _T("stopHdmiInput"), _T("{}"), response)); - EXPECT_EQ(response, string("{\"success\":true}")); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_status.isPresented = false; - - EVENT_SUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); - - dsHdmiStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onInputStatusChanged"), _T("client.events.onInputStatusChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedStable) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"stableSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_STABLE; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedNoSignal) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"noSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOSIGNAL; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedUnstable) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"unstableSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_UNSTABLE; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedNotSupported) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"notSupportedSignal\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_NOTSUPPORTED; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - -} -TEST_F(HdmiInputInitializedEventDsTest, onSignalChangedDefault) -{ - ASSERT_TRUE(dsHdmiSignalStatusEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.onSignalChanged.onSignalChanged\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"signalStatus\":\"none\"}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_sig_status.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_sig_status.status = dsHDMI_IN_SIGNAL_STATUS_MAX; - - EVENT_SUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); - - dsHdmiSignalStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("onSignalChanged"), _T("client.events.onSignalChanged"), message); -} - -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate1) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1920,\"height\":1080,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1920x1080; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_59dot94; - - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate2) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":720,\"height\":480,\"progressive\":false,\"frameRateN\":24000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x480; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_24; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate3) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":720,\"height\":576,\"progressive\":false,\"frameRateN\":25000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_720x576; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_25; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate4) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":3840,\"height\":2160,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_3840x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_30; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate5) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":50000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_50; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate6) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_60; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate7) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":24000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_23dot98; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate8) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":4096,\"height\":2160,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_4096x2160; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdate9) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1280,\"height\":720,\"progressive\":false,\"frameRateN\":30000,\"frameRateD\":1001}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_1280x720; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate = dsVIDEO_FRAMERATE_29dot97; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, videoStreamInfoUpdateDefault) -{ - ASSERT_TRUE(dsHdmiVideoModeEventHandler != nullptr); - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.videoStreamInfoUpdate.videoStreamInfoUpdate\",\"params\":{\"id\":0,\"locator\":\"hdmiin:\\/\\/localhost\\/deviceid\\/0\",\"width\":1920,\"height\":1080,\"progressive\":false,\"frameRateN\":60000,\"frameRateD\":1000}}"))); - return Core::ERROR_NONE; - })); - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_video_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_video_mode.resolution.pixelResolution = dsVIDEO_PIXELRES_MAX; - eventData.data.hdmi_in_video_mode.resolution.interlaced = true; - eventData.data.hdmi_in_video_mode.resolution.frameRate= dsVIDEO_FRAMERATE_MAX; - EVENT_SUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); - dsHdmiVideoModeEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &eventData , 0); - EVENT_UNSUBSCRIBE(0, _T("videoStreamInfoUpdate"), _T("client.events.videoStreamInfoUpdate"), message); -} -TEST_F(HdmiInputInitializedEventDsTest, hdmiGameFeatureStatusUpdate) -{ - ASSERT_TRUE(dsHdmiGameFeatureStatusEventHandler != nullptr); - - EXPECT_CALL(service, Submit(::testing::_, ::testing::_)) - .Times(1) - .WillOnce(::testing::Invoke( - [&](const uint32_t, const Core::ProxyType& json) { - string text; - EXPECT_TRUE(json->ToString(text)); - EXPECT_EQ(text, string(_T("{\"jsonrpc\":\"2.0\",\"method\":\"client.events.hdmiGameFeatureStatusUpdate.hdmiGameFeatureStatusUpdate\",\"params\":{\"id\":0,\"gameFeature\":\"ALLM\",\"mode\":true}}"))); - - return Core::ERROR_NONE; - })); - - - IARM_Bus_DSMgr_EventData_t eventData; - eventData.data.hdmi_in_allm_mode.port =dsHDMI_IN_PORT_0; - eventData.data.hdmi_in_allm_mode.allm_mode = true; - EVENT_SUBSCRIBE(0, _T("hdmiGameFeatureStatusUpdate"), _T("client.events.hdmiGameFeatureStatusUpdate"), message); - - dsHdmiGameFeatureStatusEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, &eventData , 0); - - EVENT_UNSUBSCRIBE(0, _T("hdmiGameFeatureStatusUpdate"), _T("client.events.hdmiGameFeatureStatusUpdate"), message); -} From b969871181dd194dd835750ec8eb908b66d34537 Mon Sep 17 00:00:00 2001 From: svemur170 Date: Mon, 28 Jul 2025 14:28:26 +0000 Subject: [PATCH 08/14] RDKTV-37015 - Changelog updates for 1.4.0 Signed-off-by: svemur170 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e60fb2bf..96b97f66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [1.4.0](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.5...1.4.0) + +- RDKEMW-2942 : Remove the HdmiInput plugin and replace its references with AVInput [`#205`](https://github.com/rdkcentral/entservices-inputoutput/pull/205) +- [RDKEMW-3513] PR action to run with latest change [`#163`](https://github.com/rdkcentral/entservices-inputoutput/pull/163) +- RDKEMW-6325: platfromSupport is missing from dimmingMode capabilities [`#198`](https://github.com/rdkcentral/entservices-inputoutput/pull/198) +- Merge tag '1.3.5' into develop [`024be52`](https://github.com/rdkcentral/entservices-inputoutput/commit/024be52d58d512b138b84aee9b12609e603d7110) + #### [1.3.5](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.4...1.3.5) +> 23 July 2025 + - RDKEMW-6230: Retry logic used dsGetHDMIARCPortId in HdmiCecSink [`#203`](https://github.com/rdkcentral/entservices-inputoutput/pull/203) +- 1.3.5 release changelog updates [`b12cd97`](https://github.com/rdkcentral/entservices-inputoutput/commit/b12cd97a05c2dc2b7915cfac28c998fb2277d349) - Merge tag '1.3.4' into develop [`760ee0f`](https://github.com/rdkcentral/entservices-inputoutput/commit/760ee0f9da46e0b0ed2e2adb4523bfec85c5a927) #### [1.3.4](https://github.com/rdkcentral/entservices-inputoutput/compare/1.3.3...1.3.4) From 71b85003456290ee18a71cecfdaacf97662a0158 Mon Sep 17 00:00:00 2001 From: PriyaPesala <116076033+PriyaPesala@users.noreply.github.com> Date: Wed, 30 Jul 2025 20:40:10 +0530 Subject: [PATCH 09/14] [RDKEMW-5410] RDKEMW-6572 : Compilation error was not reported for the PR branch (#211) * Reffering to current branch * For PR purpose added github.head_ref * Fixing copilot review comments * Adding description to caller_branch * Adding develop branch in ref * Modifying L1, L2 yml files * Modifying README in Tests folder * Modifying Branch to Trigger Source --- .github/workflows/L1-tests.yml | 13 +++++++ .github/workflows/L2-tests.yml | 13 +++++++ .github/workflows/tests-trigger.yml | 5 ++- Tests/README.md | 59 ++++++++++++++++------------- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 0b5cfccd..4f85ca8a 100755 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -2,6 +2,11 @@ name: L1-tests on: workflow_call: + inputs: + caller_source: + description: "Specifies the source type (e.g., local or test framework) for the workflow." + required: true + type: string secrets: RDKCM_RDKE: required: true @@ -69,6 +74,7 @@ jobs: - name: ACK External Trigger run: | echo "Message: External Trigger Received for L1 Tests" + echo "Trigger Source: ${{ inputs.caller_source }}" - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 @@ -121,6 +127,13 @@ jobs: token: ${{ secrets.RDKCM_RDKE }} - name: Checkout entservices-inputoutput + if: ${{ inputs.caller_source == 'local' }} + uses: actions/checkout@v3 + with: + path: entservices-inputoutput + + - name: Checkout entservices-inputoutput-testframework + if: ${{ inputs.caller_source == 'testframework' }} uses: actions/checkout@v3 with: repository: rdkcentral/entservices-inputoutput diff --git a/.github/workflows/L2-tests.yml b/.github/workflows/L2-tests.yml index 9dc033be..70b3894a 100755 --- a/.github/workflows/L2-tests.yml +++ b/.github/workflows/L2-tests.yml @@ -2,6 +2,11 @@ name: L2-tests on: workflow_call: + inputs: + caller_source: + description: "Specifies the source type (e.g., local or test framework) for the workflow." + required: true + type: string secrets: RDKCM_RDKE: required: true @@ -39,6 +44,7 @@ jobs: - name: ACK External Trigger run: | echo "Message: External Trigger Received for L2 Tests" + echo "Trigger Source: ${{ inputs.caller_source }}" - name: Set up CMake uses: jwlawson/actions-setup-cmake@v1.13 @@ -83,6 +89,13 @@ jobs: ref: R4.4.3 - name: Checkout entservices-inputoutput + if: ${{ inputs.caller_source == 'local' }} + uses: actions/checkout@v3 + with: + path: entservices-inputoutput + + - name: Checkout entservices-inputoutput-testframework + if: ${{ inputs.caller_source == 'testframework' }} uses: actions/checkout@v3 with: repository: rdkcentral/entservices-inputoutput diff --git a/.github/workflows/tests-trigger.yml b/.github/workflows/tests-trigger.yml index 3aa84f0f..bb3de6af 100755 --- a/.github/workflows/tests-trigger.yml +++ b/.github/workflows/tests-trigger.yml @@ -11,11 +11,14 @@ on: jobs: trigger-L1: uses: ./.github/workflows/L1-tests.yml + with: + caller_source: local secrets: RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} trigger-L2: uses: ./.github/workflows/L2-tests.yml + with: + caller_source: local secrets: RDKCM_RDKE: ${{ secrets.RDKCM_RDKE }} - diff --git a/Tests/README.md b/Tests/README.md index 4b6eb4ac..48e14c27 100644 --- a/Tests/README.md +++ b/Tests/README.md @@ -6,30 +6,20 @@ Hence, any modifications/additions related to mocks should be commited to entser # Individual Repo Handling Each individual entservices-* repo was added with a .yml file to trigger L1, L2, L2-OOP test job in github workflow. This yml file triggers below mentioned build jobs in addition to regular build jobs (thunder, thunder tools & etc,). - +``` a/ Build mocks => To create TestMock Lib from all required mock relates stubs and copy to install/usr/lib path. b/ Build entservices- => To create Test Lib of .so type from all applicable test files which are enabled for plugin test. c/ Build entservices-testframework => To create L1/L2 executable by linking the plugins/test .so files. - +``` This ensures everything in-tact in repo level across multiple related plugins when there is a new change comes in. -# testframework Repo Handling -The entservices-testframework repo contains yml files corresponds to L1, L2 & L2-OOP to trigger test job in github workflow. - -This yml file triggers below mentioned build jobs in addition to regular build jobs (thunder, thunder tools & etc,). - -a/ Build mocks => To create TestMock Lib from all required mock relates stubs and copy to install/usr/lib path. -b/ Build entservices-* => Jobs to checkout/build all individual repo's plugin & test files which are enabled for plugin test and copy all required libs to install/usr/lib path. -c/ Build entservices-testframework => To create L1/L2 executable by linking the plugins/test .so files. - -This ensures everything in-tact across multiple repos when there is a new change comes either in mocks or test case or plugins. - ##### Steps to run L1, L2, L2-OOP test locally ##### +``` 1. checkout the entservices- to your working directory in your build machine. -example: git clone https://github.com/rdkcentral/entservices-testframework.git +example: git clone https://github.com/rdkcentral/entservices-deviceanddisplay.git 2. switch to entservices- directory -example: cd entservices-testframework +example: cd entservices-deviceanddisplay 3. check and ensure current working branch points to develop example: git branch @@ -37,18 +27,33 @@ example: git branch 4. Run below curl command to download act executable to your repo. example: curl -SL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -5. 5a/to run L1 test -example: ./bin/act -W .github/workflows/L1-tests.yml -s GITHUB_TOKEN= +5. Run L1, L2, L2-oop test +example: ./bin/act -W .github/workflows/tests-trigger.yml -s GITHUB_TOKEN= -5. 5b/to run L2 test -example: ./bin/act -W .github/workflows/L2-tests.yml -s GITHUB_TOKEN= - -5. 5c/to run L2 test OOP -example: ./bin/act -W .github/workflows/L2-tests-oop.yml -s GITHUB_TOKEN= +NOTE: By default test-trigger.yml will trigger all tests(L1, L2 and etc) parallely, if you want any one test alone to be triggered/verified then remove the other trigger rules from the tests-trigger.yml +``` +# testframework Repo Handling +tf-trigger.yml file of testframework repo will get loaded into github action whenever there is a pull or push happens. This file in-turn triggers all individual repos L1, L2, L2-oop tests. testframework repo test can run only in github workflow. -NOTES: -a/ If you face any secret token related error while run your yml, pls comment the below mentioned line +NOTE: +If you face any secret token related error while run your yml, pls comment the below mentioned line #token: ${{ secrets.RDKE_GITHUB_TOKEN }} -b/ Coverage Report of both L1 and L2 test are uploaded to artifacts server. -c/ For the case, which has modification in plugin and/or test files as well in entservices-testframework mock files, change the ref key of checkout job to point your own branch instead of develop, in both entservices-testframework and entservices-* repo and ensure L1, L2, L2-OOP test jobs are passing for your PR. -example: ref: feature/L1-test + +# Execution usecases where manual change required before triggering the test: +``` +a/ changes in testframework repo only: +Need to change ref pointer of "Checkout entservices-testframework" job in individual repo yml file, to point your current working branch of testframework and in tftrigger.yml of testframework repo need to change trigger branch name to your individual repo branch name instead of develop which is default. +example: +ref: topic/method_1 /* Checkout entservices-testframework job */ +uses: rdkcentral/entservices-deviceanddisplay/.github/workflows/L1-tests.yml@topic/method_1 /* tf-trigger.yml */ + +b/ changes in both testframework repo and invidual repo: +Changes mentioned in step (a) above + "Checkout entservices-deviceanddisplay-testframework" job in individual repo yml file, ref field to point your deviceanddisplay current working branch. +example: +ref: topic/method_1 /* Checkout entservices-testframework job */ +ref: topic/method_1 /* Checkout entservices-deviceanddisplay-testframework job */ +uses: rdkcentral/entservices-deviceanddisplay/.github/workflows/L1-tests.yml@topic/method_1 /* tf-trigger.yml */ + +c/ changes in individual entservices-* repo only +no changes required +``` From 96f62a8dfb3144554aa12190db53854a7feeb289 Mon Sep 17 00:00:00 2001 From: aktamilbe <59253707+aktamilbe@users.noreply.github.com> Date: Tue, 15 Jul 2025 13:09:05 +0100 Subject: [PATCH 10/14] RDKEMW-5197 AVOutput Advance PQParams --- AVOutput/AVOutput.cpp | 19 +- AVOutput/AVOutput.h | 2 + AVOutput/AVOutputTV.cpp | 4967 ++++++++++++++++++++++++--------- AVOutput/AVOutputTV.h | 307 +- AVOutput/AVOutputTVHelper.cpp | 2244 +++++++++++++-- AVOutput/CHANGELOG.md | 3 + 6 files changed, 6029 insertions(+), 1513 deletions(-) diff --git a/AVOutput/AVOutput.cpp b/AVOutput/AVOutput.cpp index fc8dd79f..b8a3a229 100644 --- a/AVOutput/AVOutput.cpp +++ b/AVOutput/AVOutput.cpp @@ -22,10 +22,27 @@ #include "UtilsIarm.h" #include "UtilsSearchRDKProfile.h" +#define API_VERSION_NUMBER_MAJOR 1 +#define API_VERSION_NUMBER_MINOR 2 +#define API_VERSION_NUMBER_PATCH 0 + namespace WPEFramework { namespace Plugin { - SERVICE_REGISTRATION(AVOutput,1, 0); + static Plugin::Metadata metadata( + // Version (Major, Minor, Patch) + API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH, + // Preconditions + {}, + // Terminations + {}, + // Controls + {} + ); + + + SERVICE_REGISTRATION(AVOutput, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH); + AVOutput::AVOutput() { diff --git a/AVOutput/AVOutput.h b/AVOutput/AVOutput.h index 13536705..fb260ada 100644 --- a/AVOutput/AVOutput.h +++ b/AVOutput/AVOutput.h @@ -60,6 +60,8 @@ namespace Plugin { const std::string Initialize(PluginHost::IShell* service); void Deinitialize(PluginHost::IShell* service); virtual string Information() const override { return {}; } + virtual void AddRef() const { } + virtual uint32_t Release() const {return 0; } BEGIN_INTERFACE_MAP(AVOutput) INTERFACE_ENTRY(PluginHost::IPlugin) INTERFACE_ENTRY(PluginHost::IDispatcher) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index b686669c..1bc5c8a2 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -358,6 +358,55 @@ namespace Plugin { registerMethod("resetAutoBacklightMode", &AVOutputTV::resetAutoBacklightMode, this); registerMethod("getAutoBacklightModeCaps", &AVOutputTV::getAutoBacklightModeCaps, this); + registerMethod("getBacklightCapsV2", &AVOutputTV::getBacklightCapsV2, this); + registerMethod("getBrightnessCapsV2", &AVOutputTV::getBrightnessCapsV2, this); + registerMethod("getContrastCapsV2", &AVOutputTV::getContrastCapsV2, this); + registerMethod("getSharpnessCapsV2", &AVOutputTV::getSharpnessCapsV2, this); + registerMethod("getSaturationCapsV2", &AVOutputTV::getSaturationCapsV2, this); + registerMethod("getHueCapsV2", &AVOutputTV::getHueCapsV2, this); + registerMethod("getLowLatencyStateCapsV2", &AVOutputTV::getLowLatencyStateCapsV2, this); + registerMethod("getColorTemperatureCapsV2", &AVOutputTV::getColorTemperatureCapsV2, this); + registerMethod("getBacklightDimmingModeCapsV2", &AVOutputTV::getBacklightDimmingModeCapsV2, this); + registerMethod("getZoomModeCapsV2", &AVOutputTV::getZoomModeCapsV2, this); + registerMethod("getDolbyVisionCalibrationCaps", &AVOutputTV::getDolbyVisionCalibrationCaps, this); + registerMethod("getPictureModeCapsV2", &AVOutputTV::getPictureModeCapsV2, this); + registerMethod("getAutoBacklightModeCapsV2", &AVOutputTV::getAutoBacklightModeCapsV2, this); + registerMethod("getCMSCapsV2", &AVOutputTV::getCMSCapsV2, this); + registerMethod("get2PointWBCapsV2", &AVOutputTV::get2PointWBCapsV2, this); + registerMethod("getSDRGammaCaps", &AVOutputTV::getSDRGammaCaps, this); + + registerMethod("getPrecisionDetailCaps", &AVOutputTV::getPrecisionDetailCaps, this); + registerMethod("getPrecisionDetail", &AVOutputTV::getPrecisionDetail, this); + registerMethod("setPrecisionDetail", &AVOutputTV::setPrecisionDetail, this); + registerMethod("resetPrecisionDetail", &AVOutputTV::resetPrecisionDetail, this); + + registerMethod("getLocalContrastEnhancementCaps", &AVOutputTV::getLocalContrastEnhancementCaps, this); + registerMethod("getLocalContrastEnhancement", &AVOutputTV::getLocalContrastEnhancement, this); + registerMethod("setLocalContrastEnhancement", &AVOutputTV::setLocalContrastEnhancement, this); + registerMethod("resetLocalContrastEnhancement", &AVOutputTV::resetLocalContrastEnhancement, this); + + registerMethod("getMPEGNoiseReductionCaps", &AVOutputTV::getMPEGNoiseReductionCaps, this); + registerMethod("getMPEGNoiseReduction", &AVOutputTV::getMPEGNoiseReduction, this); + registerMethod("setMPEGNoiseReduction", &AVOutputTV::setMPEGNoiseReduction, this); + registerMethod("resetMPEGNoiseReduction", &AVOutputTV::resetMPEGNoiseReduction, this); + + registerMethod("getDigitalNoiseReductionCaps", &AVOutputTV::getDigitalNoiseReductionCaps, this); + registerMethod("getDigitalNoiseReduction", &AVOutputTV::getDigitalNoiseReduction, this); + registerMethod("setDigitalNoiseReduction", &AVOutputTV::setDigitalNoiseReduction, this); + registerMethod("resetDigitalNoiseReduction", &AVOutputTV::resetDigitalNoiseReduction, this); + + registerMethod("getMEMCCaps", &AVOutputTV::getMEMCCaps, this); + registerMethod("getMEMC", &AVOutputTV::getMEMC, this); + registerMethod("setMEMC", &AVOutputTV::setMEMC, this); + registerMethod("resetMEMC", &AVOutputTV::resetMEMC, this); + + registerMethod("getAISuperResolutionCaps", &AVOutputTV::getAISuperResolutionCaps, this); + registerMethod("getAISuperResolution", &AVOutputTV::getAISuperResolution, this); + registerMethod("setAISuperResolution", &AVOutputTV::setAISuperResolution, this); + registerMethod("resetAISuperResolution", &AVOutputTV::resetAISuperResolution, this); + + registerMethod("getMultiPointWBCaps", &AVOutputTV::getMultiPointWBCaps, this); + LOGINFO("Exit\n"); } @@ -459,6 +508,796 @@ namespace Plugin { LOGINFO("Exit\n"); } + // Shared zoom mode mappings + static const std::unordered_map zoomModeReverseMap = { + {tvDisplayMode_16x9, "TV 16X9 STRETCH"}, + {tvDisplayMode_4x3, "TV 4X3 PILLARBOX"}, + {tvDisplayMode_NORMAL, "TV NORMAL"}, + {tvDisplayMode_DIRECT, "TV DIRECT"}, + {tvDisplayMode_AUTO, "TV AUTO"}, + {tvDisplayMode_ZOOM, "TV ZOOM"}, + {tvDisplayMode_FULL, "TV FULL"} + }; + static const std::unordered_map zoomModeMap = { + {"TV 16X9 STRETCH", tvDisplayMode_16x9}, + {"TV 4X3 PILLARBOX", tvDisplayMode_4x3}, + {"TV NORMAL", tvDisplayMode_NORMAL}, + {"TV DIRECT", tvDisplayMode_DIRECT}, + {"TV AUTO", tvDisplayMode_AUTO}, + {"TV ZOOM", tvDisplayMode_ZOOM}, + {"TV FULL", tvDisplayMode_FULL} + }; + static const std::unordered_map dimmingModeReverseMap = { + { tvDimmingMode_Fixed, "Fixed" }, + { tvDimmingMode_Local, "Local" }, + { tvDimmingMode_Global, "Global" } + }; + static const std::unordered_map dimmingModeMap = { + { "Fixed", tvDimmingMode_Fixed }, + { "Local", tvDimmingMode_Local }, + { "Global", tvDimmingMode_Global } + }; + + bool AVOutputTV::getPQParamFromContext(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t paramType, + int& outValue) + { + tvConfigContext_t validContext = getValidContextFromGetParameters(parameters, paramName); + if ((validContext.videoSrcType == VIDEO_SOURCE_ALL && + validContext.videoFormatType == VIDEO_FORMAT_NONE && + validContext.pq_mode == PQ_MODE_INVALID)) + { + LOGWARN("No Valid context for get %s", paramName.c_str()); + return false; + } + + paramIndex_t indexInfo + { + .sourceIndex = static_cast(validContext.videoSrcType), + .pqmodeIndex = static_cast(validContext.pq_mode), + .formatIndex = static_cast(validContext.videoFormatType) + }; + + int value = 0; + tvError_t err = static_cast(getLocalparam(paramName.c_str(), indexInfo, value, paramType)); + if (err == tvERROR_NONE) { + outValue = value; + return true; + } + + LOGERR("getLocalparam failed for %s with error code %d", paramName.c_str(), err); + return false; + } + + bool AVOutputTV::getEnumPQParamString( + const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqType, + const std::unordered_map& enumToStrMap, + std::string& outStr) + { + LOGINFO("getEnumPQParamString Entry for %s\n", paramName.c_str()); + + tvConfigContext_t validContext = getValidContextFromGetParameters(parameters, paramName); + if ((validContext.videoSrcType == VIDEO_SOURCE_ALL && + validContext.videoFormatType == VIDEO_FORMAT_NONE && + validContext.pq_mode == PQ_MODE_INVALID)) + { + LOGWARN("No valid context for get %s", paramName.c_str()); + return false; + } + + paramIndex_t indexInfo { + .sourceIndex = static_cast(validContext.videoSrcType), + .pqmodeIndex = static_cast(validContext.pq_mode), + .formatIndex = static_cast(validContext.videoFormatType) + }; + + int paramValue = 0; + int err = getLocalparam(paramName, indexInfo, paramValue, pqType); + if (err != 0) { + LOGERR("Failed to get %s from localparam", paramName.c_str()); + return false; + } + + auto it = enumToStrMap.find(paramValue); + if (it != enumToStrMap.end()) { + outStr = it->second; + LOGINFO("%s = %s", paramName.c_str(), outStr.c_str()); + return true; + } else { + LOGERR("Enum value %d not found in map for %s", paramValue, paramName.c_str()); + return false; + } + } + bool AVOutputTV::setCMSParam(const JsonObject& parameters) + { + LOGINFO("Entry: setCMSParam"); + + std::string colorStr = parameters.HasLabel("color") ? parameters["color"].String() : ""; + std::string componentStr = parameters.HasLabel("component") ? parameters["component"].String() : ""; + std::string levelStr = parameters.HasLabel("level") ? parameters["level"].String() : ""; + + if (colorStr.empty() || componentStr.empty() || levelStr.empty()) { + LOGERR("Missing color/component/level"); + return false; + } + + int level = 0; + try { + level = std::stoi(levelStr); + } catch (...) { + LOGERR("Invalid level value: %s", levelStr.c_str()); + return false; + } + + int maxCap = 0; + if (componentStr == "Hue") + maxCap = m_maxCmsHue; + else if (componentStr == "Saturation") + maxCap = m_maxCmsSaturation; + else if (componentStr == "Luma") + maxCap = m_maxCmsLuma; + else { + LOGERR("Invalid component: %s", componentStr.c_str()); + return false; + } + + if (level < 0 || level > maxCap) { + LOGERR("Level out of range: %d (0-%d)", level, maxCap); + return false; + } + + tvDataComponentColor_t colorEnum; + if (getCMSColorEnumFromString(colorStr, colorEnum) != 0) { + LOGERR("Invalid color: %s", colorStr.c_str()); + return false; + } + + + if( isSetRequiredForParam(parameters, "CMS") ) { + LOGINFO("Proceed with SetCMSState \n"); + tvError_t ret = SetCMSState(true); + if(ret != tvERROR_NONE) { + LOGWARN("CMS enable failed\n"); + return false; + } + if (componentStr == "Hue") + ret = SetCurrentComponentHue(colorEnum, level); + else if (componentStr == "Saturation") + ret = SetCurrentComponentSaturation(colorEnum, level); + else if (componentStr == "Luma") + ret = SetCurrentComponentLuma(colorEnum, level); + + if (ret != tvERROR_NONE) { + LOGERR("HAL set failed for %s", componentStr.c_str()); + return false; + } + } + + try { + int retVal = updateAVoutputTVParamV2("set", "CMS", parameters, PQ_PARAM_CMS, level); + if (retVal < 0) { + LOGERR("setCMSParam: Failed to save CMS param, return code: %d", retVal); + return false; + } + } catch (const std::exception& e) { + LOGERR("Exception in updateAVoutputTVParamV2: %s", e.what()); + return false; + } catch (...) { + LOGERR("Unknown exception in updateAVoutputTVParamV2"); + return false; + } + + LOGINFO("Exit: setCMSParam success"); + return true; + } + + + bool AVOutputTV::setEnumPQParam(const JsonObject& parameters, + const std::string& inputKey, + const std::string& paramName, + const std::unordered_map& valueMap, + tvPQParameterIndex_t paramType, + std::function halSetter) + { + if (!parameters.HasLabel(inputKey.c_str())) { + LOGERR("Missing input field: %s", inputKey.c_str()); + return false; + } + + std::string value = parameters[inputKey.c_str()].String(); + auto it = valueMap.find(value); + if (it == valueMap.end()) { + LOGERR("Invalid value '%s' for parameter: %s", value.c_str(), inputKey.c_str()); + return false; + } + + int intVal = it->second; + + // Only call HAL for current system context + if (isSetRequiredForParam(parameters, paramName)) { + LOGINFO("Calling HAL for %s = %s intVal %d", paramName.c_str(), value.c_str(), intVal); + tvError_t ret = halSetter(intVal); + if (ret != tvERROR_NONE) { + LOGERR("HAL setter failed for %s", paramName.c_str()); + return false; + } + } + + // Persist the parameter contextually + int result = updateAVoutputTVParamV2("set", paramName, parameters, paramType, intVal); + if (result != 0) { + LOGERR("Persistence failed for %s", paramName.c_str()); + return false; + } + + LOGINFO("setEnumPQParam successful: %s = %s", paramName.c_str(), value.c_str()); + return true; + } + + bool AVOutputTV::setIntPQParam(const JsonObject& parameters, const std::string& paramName, + tvPQParameterIndex_t pqType, tvSetFunction halSetter, int maxCap) + { + LOGINFO("Entry: %s\n", paramName.c_str()); + int paramValue = 0; + tvError_t ret = tvERROR_NONE; + std::string value = ""; + std::string lowerParamName = paramName; + std::transform(lowerParamName.begin(), lowerParamName.end(), lowerParamName.begin(), ::tolower); + + if (!parameters.HasLabel(lowerParamName.c_str())) { + LOGERR("%s: Missing parameter: %s", __FUNCTION__, lowerParamName.c_str()); + return false; + } + + value = parameters[lowerParamName.c_str()].String(); + + try { + paramValue = std::stoi(value); + } catch (const std::exception& e) { + LOGERR("Invalid %s value: %s. Exception: %s", paramName.c_str(), value.c_str(), e.what()); + return false; + } + + if (paramValue < 0 || paramValue > maxCap) { + LOGERR("Input value %d is out of range (0 - %d) for %s", paramValue, maxCap, paramName.c_str()); + return false; + } + + if (isSetRequiredForParam(parameters, paramName)) { + LOGINFO("Proceed with set%s\n", paramName.c_str()); + ret = halSetter(paramValue); + LOGINFO("halsetter ret %d \n", ret); + if (ret != tvERROR_NONE){ + LOGERR("Failed to set %s\n", paramName.c_str()); + return false; + } + } + LOGINFO("Calling updateAVOutputTVParamV2 \n"); + int retval = updateAVoutputTVParamV2("set", paramName, parameters, pqType, paramValue); + if (retval != 0) { + LOGERR("Failed to Save %s to ssm_data. retval: %d\n", paramName.c_str(), retval); + return false; + } + + LOGINFO("Exit: set%s successful to value: %d\n", paramName.c_str(), paramValue); + return true; + } + + uint32_t AVOutputTV::getPQCapabilityWithContext( + const std::function& getCapsFunc, + const JsonObject& parameters, + JsonObject& response) + { + int max_value = 0; + tvContextCaps_t* context_caps = nullptr; + + // Call the HAL function + tvError_t result = getCapsFunc(&context_caps, &max_value); + LOGWARN("AVOutputPlugins: %s: result: %d", __FUNCTION__, result); + + if (result != tvERROR_NONE) { + returnResponse(false); + } + + response["platformSupport"] = true; + + if (max_value > 0) { + JsonObject rangeInfo; + rangeInfo["from"] = 0; + rangeInfo["to"] = max_value; + response["rangeInfo"] = rangeInfo; + } + + response["context"] = parseContextCaps(context_caps); + + returnResponse(true); + } + + + JsonObject AVOutputTV::parseContextCaps(tvContextCaps_t* context_caps) { + JsonObject contextObj; + if (context_caps && context_caps->num_contexts > 0) { + for (size_t i = 0; i < context_caps->num_contexts; ++i) { + int pqMode = context_caps->contexts[i].pq_mode; + int videoFormat = context_caps->contexts[i].videoFormatType; + int videoSource = context_caps->contexts[i].videoSrcType; + + auto pqModeIt = AVOutputTV::pqModeMap.find(pqMode); + auto videoFormatIt = AVOutputTV::videoFormatMap.find(videoFormat); + auto videoSrcIt = AVOutputTV::videoSrcMap.find(videoSource); + + if (pqModeIt != AVOutputTV::pqModeMap.end() && + videoFormatIt != AVOutputTV::videoFormatMap.end() && + videoSrcIt != AVOutputTV::videoSrcMap.end()) { + + const char* pqModeStr = pqModeIt->second.c_str(); + const char* videoFormatStr = videoFormatIt->second.c_str(); + const char* videoSrcStr = videoSrcIt->second.c_str(); + + if (!contextObj.HasLabel(pqModeStr)) { + contextObj[pqModeStr] = JsonObject(); + } + JsonObject pqModeObj = contextObj[pqModeStr].Object(); + + if (!pqModeObj.HasLabel(videoFormatStr)) { + pqModeObj[videoFormatStr] = JsonArray(); + } + JsonArray formatArray = pqModeObj[videoFormatStr].Array(); + // **Manually check for existence before adding** + bool exists = false; + for (size_t j = 0; j < formatArray.Length(); ++j) { + if (strcmp(formatArray[j].String().c_str(), videoSrcStr) == 0) { + exists = true; + break; + } + } + if (!exists) { + formatArray.Add(videoSrcStr); + } + // Update objects + pqModeObj[videoFormatStr] = formatArray; + contextObj[pqModeStr] = pqModeObj; + } + } + } + return contextObj; + } + + uint32_t AVOutputTV::getBacklightCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_backlight) { +#if HAL_NOT_READY + return this->GetBacklightCaps(max_backlight, context_caps); +#else + return GetBacklightCaps(max_backlight, context_caps); +#endif + }, parameters, response); + } + + uint32_t AVOutputTV::getBrightnessCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_brightness) { +#if HAL_NOT_READY + return this->GetBrightnessCaps(max_brightness, context_caps); +#else + return GetBrightnessCaps(max_brightness, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getContrastCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_contrast) { +#if HAL_NOT_READY + return this->GetContrastCaps(max_contrast, context_caps); +#else + return GetContrastCaps(max_contrast, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getSharpnessCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_sharpness) { +#if HAL_NOT_READY + return this->GetSharpnessCaps(max_sharpness, context_caps); +#else + return GetSharpnessCaps(max_sharpness, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getSaturationCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_saturation) { +#if HAL_NOT_READY + return this->GetSaturationCaps(max_saturation, context_caps); +#else + return GetSaturationCaps(max_saturation, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getHueCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_hue) { +#if HAL_NOT_READY + return this->GetHueCaps(max_hue, context_caps); +#else + return GetHueCaps(max_hue, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getPrecisionDetailCaps(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_precision) { +#if HAL_NOT_READY + return this->GetPrecisionDetailCaps(max_precision, context_caps); +#else + return GetPrecisionDetailCaps(max_precision, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getLocalContrastEnhancementCaps(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { +#if HAL_NOT_READY + return this->GetLocalContrastEnhancementCaps(max_val, context_caps); +#else + return GetLocalContrastEnhancementCaps(max_val, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getMPEGNoiseReductionCaps(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { +#if HAL_NOT_READY + return this->GetMPEGNoiseReductionCaps(max_val, context_caps); +#else + return GetMPEGNoiseReductionCaps(max_val, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getDigitalNoiseReductionCaps(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { +#if HAL_NOT_READY + return this->GetDigitalNoiseReductionCaps(max_val, context_caps); +#else + return GetDigitalNoiseReductionCaps(max_val, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getAISuperResolutionCaps(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { +#if HAL_NOT_READY + return this->GetAISuperResolutionCaps(max_val, context_caps); +#else + return GetAISuperResolutionCaps(max_val, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getMultiPointWBCaps(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + + int num_hal_matrix_points = 0; + int rgb_min = 0, rgb_max = 0; + int num_ui_matrix_points = 0; + double* ui_matrix_positions = nullptr; + tvContextCaps_t* context_caps = nullptr; + + tvError_t ret = GetMultiPointWBCaps( + &num_hal_matrix_points, + &rgb_min, + &rgb_max, + &num_ui_matrix_points, + &ui_matrix_positions, + &context_caps + ); + + if (ret != tvERROR_NONE) { + LOGWARN("GetMultiPointWBCaps failed: %s", getErrorString(ret).c_str()); + returnResponse(false); + } + response["platformSupport"] = true; + + response["numHalMatrixPoints"] = num_hal_matrix_points; + response["rgbMin"] = rgb_min; + response["rgbMax"] = rgb_max; + response["numUiMatrixPoints"] = num_ui_matrix_points; + + // Add UI matrix positions + JsonArray uiPosArray; + for (int i = 0; i < num_ui_matrix_points; ++i) { + uiPosArray.Add(ui_matrix_positions[i]); + } + response["uiMatrixPositions"] = uiPosArray; + response["context"] = parseContextCaps(context_caps); +#if HAL_NOT_READY + // TODO:: Review cleanup once HAL is available, as memory will be allocated in HAL. + delete[] ui_matrix_positions; +#endif + LOGINFO("Exit\n"); + returnResponse(true); + } + + uint32_t AVOutputTV::getMEMCCaps(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { +#if HAL_NOT_READY + return this->GetMEMCCaps(max_val, context_caps); +#else + return GetMEMCCaps(max_val, context_caps); +#endif + }, + parameters, response); + } + + uint32_t AVOutputTV::getLowLatencyStateCapsV2(const JsonObject& parameters, JsonObject& response) { + return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_latency) { +#if HAL_NOT_READY + return this->GetLowLatencyStateCaps(max_latency, context_caps); +#else + return GetLowLatencyStateCaps(max_latency, context_caps); +#endif + }, + parameters, response); + } + + // Forward lookup: string → enum + const std::unordered_map colorTempMap = { + {"Standard", tvColorTemp_STANDARD}, + {"Warm", tvColorTemp_WARM}, + {"Cold", tvColorTemp_COLD}, + {"UserDefined", tvColorTemp_USER}, + {"Supercold", tvColorTemp_SUPERCOLD}, + {"BoostStandard", tvColorTemp_BOOST_STANDARD}, + {"BoostWarm", tvColorTemp_BOOST_WARM}, + {"BoostCold", tvColorTemp_BOOST_COLD}, + {"BoostUserDefined", tvColorTemp_BOOST_USER}, + {"BoostSupercold", tvColorTemp_BOOST_SUPERCOLD} + }; + + // Reverse lookup: enum → string + const std::unordered_map colorTempReverseMap = { + {tvColorTemp_STANDARD, "Standard"}, + {tvColorTemp_WARM, "Warm"}, + {tvColorTemp_COLD, "Cold"}, + {tvColorTemp_USER, "UserDefined"}, + {tvColorTemp_SUPERCOLD, "Supercold"}, + {tvColorTemp_BOOST_STANDARD, "BoostStandard"}, + {tvColorTemp_BOOST_WARM, "BoostWarm"}, + {tvColorTemp_BOOST_COLD, "BoostCold"}, + {tvColorTemp_BOOST_USER, "BoostUserDefined"}, + {tvColorTemp_BOOST_SUPERCOLD, "BoostSupercold"} + }; + + uint32_t AVOutputTV::getColorTemperatureCapsV2(const JsonObject& parameters, JsonObject& response) { + tvColorTemp_t* color_temp = nullptr; + size_t num_color_temp = 0; + tvContextCaps_t* context_caps = nullptr; + + tvError_t err = GetColorTemperatureCaps(&color_temp, &num_color_temp, &context_caps); + if (err != tvERROR_NONE) { + return err; + } + + response["platformSupport"] = true; + + JsonArray optionsArray; + for (size_t i = 0; i < num_color_temp; ++i) { + auto it = colorTempReverseMap.find(color_temp[i]); + if (it != colorTempReverseMap.end()) { + optionsArray.Add(it->second); + } + } + response["options"] = optionsArray; + response["context"] = parseContextCaps(context_caps); + + #if HAL_NOT_READY + free(color_temp); + #endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getSDRGammaCaps(const JsonObject& parameters, JsonObject& response) + { + tvSdrGamma_t* sdr_gamma = nullptr; + size_t num_sdr_gamma = 0; + tvContextCaps_t* context_caps = nullptr; + + tvError_t err = GetSdrGammaCaps(&sdr_gamma, &num_sdr_gamma, &context_caps); + if (err != tvERROR_NONE) { + return err; + } + + response["platformSupport"] = true; + + JsonArray optionsArray; + for (size_t i = 0; i < num_sdr_gamma; ++i) { + switch (sdr_gamma[i]) { + case tvSdrGamma_1_8: optionsArray.Add("1.8"); break; + case tvSdrGamma_1_9: optionsArray.Add("1.9"); break; + case tvSdrGamma_2_0: optionsArray.Add("2.0"); break; + case tvSdrGamma_2_1: optionsArray.Add("2.1"); break; + case tvSdrGamma_2_2: optionsArray.Add("2.2"); break; + case tvSdrGamma_2_3: optionsArray.Add("2.3"); break; + case tvSdrGamma_2_4: optionsArray.Add("2.4"); break; + case tvSdrGamma_BT_1886: optionsArray.Add("BT.1886"); break; + default: break; + } + } + response["options"] = optionsArray; + + response["context"] = parseContextCaps(context_caps); + + #if HAL_NOT_READY + free(sdr_gamma); + #endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getBacklightDimmingModeCapsV2(const JsonObject& parameters, JsonObject& response) + { + tvDimmingMode_t* dimming_mode = nullptr; + size_t num_dimming_mode = 0; + tvContextCaps_t* context_caps = nullptr; + + tvError_t err = GetTVDimmingModeCaps(&dimming_mode, &num_dimming_mode, &context_caps); + if (err != tvERROR_NONE) { + return err; + } + + response["platformSupport"] = true; + + JsonArray optionsArray; + for (size_t i = 0; i < num_dimming_mode; ++i) { + auto it = dimmingModeReverseMap.find(dimming_mode[i]); + if (it != dimmingModeReverseMap.end()) { + optionsArray.Add(it->second); + } + } + response["options"] = optionsArray; + + response["context"] = parseContextCaps(context_caps); + + #if HAL_NOT_READY + free(dimming_mode); + #endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getZoomModeCapsV2(const JsonObject& parameters, JsonObject& response) + { + response["platformSupport"] = true; + + JsonArray optionsArray; + for (size_t i = 0; i < m_numAspectRatio; ++i) { + auto it = zoomModeReverseMap.find(m_aspectRatio[i]); + if (it != zoomModeReverseMap.end()) { + optionsArray.Add(it->second); + } + } + response["options"] = optionsArray; + + response["context"] = parseContextCaps(m_aspectRatioCaps); + + #if HAL_NOT_READY + free(m_aspectRatio); + #endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getPictureModeCapsV2(const JsonObject& parameters, JsonObject& response) + { + response["platformSupport"] = true; + + JsonArray optionsArray; + for (size_t i = 0; i < m_numPictureModes; ++i) { + auto it = pqModeMap.find(m_pictureModes[i]); + if (it != pqModeMap.end()) { + optionsArray.Add(it->second); + } + } + response["options"] = optionsArray; + + response["context"] = parseContextCaps(m_pictureModeCaps); + + #if HAL_NOT_READY + free(m_pictureModes); + #endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getAutoBacklightModeCapsV2(const JsonObject& parameters, JsonObject& response) + { + response["platformSupport"] = true; + + JsonArray optionsArray; + for (size_t i = 0; i < m_numBacklightModes; ++i) { + switch (m_backlightModes[i]) { + case tvBacklightMode_MANUAL: + optionsArray.Add("Manual"); + break; + case tvBacklightMode_AMBIENT: + optionsArray.Add("Ambient"); + break; + case tvBacklightMode_ECO: + optionsArray.Add("Eco"); + break; + default: + LOGINFO("Unknown backlightMode option\n"); + break; + } + } + response["options"] = optionsArray; + + response["context"] = parseContextCaps(m_backlightModeCaps); + + #if HAL_NOT_READY + // TODO: Review cleanup once HAL is available, as memory will be allocated in HAL. + free(m_backlightModes); + #endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getDolbyVisionCalibrationCaps(const JsonObject& parameters, JsonObject& response) + { + tvDVCalibrationSettings_t* min_values = nullptr; + tvDVCalibrationSettings_t* max_values = nullptr; + tvContextCaps_t* context_caps = nullptr; + + if (GetDVCalibrationCaps(&min_values, &max_values, &context_caps) != tvERROR_NONE) { + returnResponse(false); + } + + // Set platform support + response["platformSupport"] = true; + + // Add all range fields (flattened as per expected JSON) + response["rangeTmax"] = JsonObject({{"from", min_values->Tmax}, {"to", max_values->Tmax}}); + response["rangeTmin"] = JsonObject({{"from", min_values->Tmin}, {"to", max_values->Tmin}}); + response["rangeTgamma"] = JsonObject({{"from", min_values->Tgamma}, {"to", max_values->Tgamma}}); + response["rangeRx"] = JsonObject({{"from", min_values->Rx}, {"to", max_values->Rx}}); + response["rangeRy"] = JsonObject({{"from", min_values->Ry}, {"to", max_values->Ry}}); + response["rangeGx"] = JsonObject({{"from", min_values->Gx}, {"to", max_values->Gx}}); + response["rangeGy"] = JsonObject({{"from", min_values->Gy}, {"to", max_values->Gy}}); + response["rangeBx"] = JsonObject({{"from", min_values->Bx}, {"to", max_values->Bx}}); + response["rangeBy"] = JsonObject({{"from", min_values->By}, {"to", max_values->By}}); + response["rangeWx"] = JsonObject({{"from", min_values->Wx}, {"to", max_values->Wx}}); + response["rangeWy"] = JsonObject({{"from", min_values->Wy}, {"to", max_values->Wy}}); + + // Add context list + response["context"] = parseContextCaps(context_caps); + + // Indicate success + response["success"] = true; + +#if HAL_NOT_READY + // TODO: Clean up when HAL handles memory + delete min_values; + delete max_values; +#endif + + returnResponse(true); + } + + uint32_t AVOutputTV::getZoomModeCaps(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); @@ -509,81 +1348,117 @@ namespace Plugin { uint32_t AVOutputTV::setZoomMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - std::string value; - tvDisplayMode_t mode = tvDisplayMode_16x9; - capDetails_t inputInfo; + if(m_aspectRatioStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + std::string value; + tvDisplayMode_t mode = tvDisplayMode_16x9; + capDetails_t inputInfo; - value = parameters.HasLabel("zoomMode") ? parameters["zoomMode"].String() : ""; - returnIfParamNotFound(parameters,"zoomMode"); + value = parameters.HasLabel("zoomMode") ? parameters["zoomMode"].String() : ""; + returnIfParamNotFound(parameters,"zoomMode"); - if (validateInputParameter("AspectRatio",value) != 0) { - LOGERR("%s: Range validation failed for AspectRatio\n", __FUNCTION__); - returnResponse(false); - } + if (validateInputParameter("AspectRatio",value) != 0) { + LOGERR("%s: Range validation failed for AspectRatio\n", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters,"AspectRatio",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters,"AspectRatio",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "AspectRatio",inputInfo )) { - LOGERR("%s: CapablityCheck failed for AspectRatio\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "AspectRatio",inputInfo )) { + LOGERR("%s: CapablityCheck failed for AspectRatio\n", __FUNCTION__); + returnResponse(false); + } - if(!value.compare("TV 16X9 STRETCH")) { - mode = tvDisplayMode_16x9; - } - else if (!value.compare("TV 4X3 PILLARBOX")) { - mode = tvDisplayMode_4x3; - } - else if (!value.compare("TV NORMAL")) { - mode = tvDisplayMode_NORMAL; - } - else if (!value.compare("TV DIRECT")) { - mode = tvDisplayMode_DIRECT; - } - else if (!value.compare("TV AUTO")) { - mode = tvDisplayMode_AUTO; - } - else if (!value.compare("TV ZOOM")) { - mode = tvDisplayMode_ZOOM; - } - else { - returnResponse(false); - } - m_videoZoomMode = mode; - tvError_t ret = setAspectRatioZoomSettings (mode); + if(!value.compare("TV 16X9 STRETCH")) { + mode = tvDisplayMode_16x9; + } + else if (!value.compare("TV 4X3 PILLARBOX")) { + mode = tvDisplayMode_4x3; + } + else if (!value.compare("TV NORMAL")) { + mode = tvDisplayMode_NORMAL; + } + else if (!value.compare("TV DIRECT")) { + mode = tvDisplayMode_DIRECT; + } + else if (!value.compare("TV AUTO")) { + mode = tvDisplayMode_AUTO; + } + else if (!value.compare("TV ZOOM")) { + mode = tvDisplayMode_ZOOM; + } + else { + returnResponse(false); + } + m_videoZoomMode = mode; + tvError_t ret = setAspectRatioZoomSettings (mode); - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + //Save DisplayMode to localstore and ssm_data + int retval=updateAVoutputTVParam("set","AspectRatio",inputInfo,PQ_PARAM_ASPECT_RATIO,mode); + + if(retval != 0) { + LOGERR("Failed to Save DisplayMode to ssm_data\n"); + returnResponse(false); + } + + tr181ErrorCode_t err = setLocalParam(rfc_caller_id, AVOUTPUT_ASPECTRATIO_RFC_PARAM, value.c_str()); + if ( err != tr181Success ) { + LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_ASPECTRATIO_RFC_PARAM, getTR181ErrorString(err)); + returnResponse(false); + } + else { + LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_ASPECTRATIO_RFC_PARAM, value.c_str()); + } + LOGINFO("Exit : SetAspectRatio() value : %s\n",value.c_str()); + returnResponse(true); + } } - else { - //Save DisplayMode to localstore and ssm_data - int retval=updateAVoutputTVParam("set","AspectRatio",inputInfo,PQ_PARAM_ASPECT_RATIO,mode); + else + { + std::string value = parameters.HasLabel("zoomMode") ? parameters["zoomMode"].String() : ""; + returnIfParamNotFound(parameters, "zoomMode"); - if(retval != 0) { - LOGERR("Failed to Save DisplayMode to ssm_data\n"); + auto it = zoomModeMap.find(value); + if (it == zoomModeMap.end()) { + LOGERR("Invalid zoom mode: %s. Not in supported options.", value.c_str()); returnResponse(false); } - - tr181ErrorCode_t err = setLocalParam(rfc_caller_id, AVOUTPUT_ASPECTRATIO_RFC_PARAM, value.c_str()); - if ( err != tr181Success ) { - LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_ASPECTRATIO_RFC_PARAM, getTR181ErrorString(err)); + tvDisplayMode_t mode = it->second; + tvError_t ret = setAspectRatioZoomSettings(mode); + if (ret != tvERROR_NONE) { returnResponse(false); } - else { - LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_ASPECTRATIO_RFC_PARAM, value.c_str()); + else + { + // Save DisplayMode to local store and ssm_data + int retval = updateAVoutputTVParamV2("set", "AspectRatio", parameters, PQ_PARAM_ASPECT_RATIO, mode); + if (retval != 0) { + LOGERR("Failed to Save DisplayMode to ssm_data\n"); + returnResponse(false); + } + tr181ErrorCode_t err = setLocalParam(rfc_caller_id, AVOUTPUT_ASPECTRATIO_RFC_PARAM, value.c_str()); + if (err != tr181Success) { + LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_ASPECTRATIO_RFC_PARAM, getTR181ErrorString(err)); + returnResponse(false); + } else { + LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_ASPECTRATIO_RFC_PARAM, value.c_str()); + } + LOGINFO("Exit : SetAspectRatio() value : %s\n", value.c_str()); + returnResponse(true); } - LOGINFO("Exit : SetAspectRatio() value : %s\n",value.c_str()); - returnResponse(true); } } uint32_t AVOutputTV::getZoomMode(const JsonObject& parameters, JsonObject& response) { - LOGINFO("Entry\n"); tvDisplayMode_t mode; @@ -707,151 +1582,669 @@ namespace Plugin { response["currentVideoFrameRate"] = "NONE"; returnResponse(false); } - else { - response["currentVideoFrameRate"] = getVideoFrameRateTypeToString(videoFramerate); - LOGINFO("Exit: videoFramerate :%d success \n",videoFramerate); - returnResponse(true); + else { + response["currentVideoFrameRate"] = getVideoFrameRateTypeToString(videoFramerate); + LOGINFO("Exit: videoFramerate :%d success \n",videoFramerate); + returnResponse(true); + } + } + + uint32_t AVOutputTV::resetPrecisionDetail(const JsonObject& parameters, JsonObject& response) + { + #if HAL_NOT_READY + bool success = false; + #else + bool success = resetPQParamToDefault(parameters, "PrecisionDetail", + PQ_PARAM_PRECISION_DETAIL, SetPrecisionDetail); + #endif + returnResponse(success); + } + + uint32_t AVOutputTV::resetLocalContrastEnhancement(const JsonObject& parameters, JsonObject& response) + { + #if HAL_NOT_READY + bool success = false; + #else + #if ENABLE_PQ_PARAM + bool success = resetPQParamToDefault(parameters, "LocalContrastEnhancement", + PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT, SetLocalContrastEnhancement); + #else + bool success = true; + #endif + #endif + returnResponse(success); + } + + uint32_t AVOutputTV::resetMPEGNoiseReduction(const JsonObject& parameters, JsonObject& response) + { + #if HAL_NOT_READY + bool success = false; + #else + #if ENABLE_PQ_PARAM + bool success = resetPQParamToDefault(parameters, "MPEGNoiseReduction", + PQ_PARAM_MPEG_NOISE_REDUCTION, SetMPEGNoiseReduction); + #else + bool success = true; + #endif + #endif + returnResponse(success); + } + + uint32_t AVOutputTV::resetDigitalNoiseReduction(const JsonObject& parameters, JsonObject& response) + { + #if HAL_NOT_READY + bool success = false; + #else + #if ENABLE_PQ_PARAM + bool success = resetPQParamToDefault(parameters, "DigitalNoiseReduction", + PQ_PARAM_DIGITAL_NOISE_REDUCTION, SetDigitalNoiseReduction); + #else + bool success = true; + #endif + + #endif + returnResponse(success); + } + + uint32_t AVOutputTV::resetMEMC(const JsonObject& parameters, JsonObject& response) + { + #if HAL_NOT_READY + bool success = false; + #else + bool success = resetPQParamToDefault(parameters, "MEMC", + PQ_PARAM_MEMC, SetMEMC); + #endif + returnResponse(success); + } + + uint32_t AVOutputTV::resetAISuperResolution(const JsonObject& parameters, JsonObject& response) + { +#if HAL_NOT_READY + bool success= false; +#else + bool success= resetPQParamToDefault(parameters,"AISuperResolution", + PQ_PARAM_AI_SUPER_RESOLUTION, SetAISuperResolution); +#endif + returnResponse(success); + } + + uint32_t AVOutputTV::getPrecisionDetail(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + int precisionDetail = 0; + bool success = getPQParamFromContext(parameters, + "PrecisionDetail", + PQ_PARAM_PRECISION_DETAIL, + precisionDetail); + if (success) { + response["precisionDetail"] = precisionDetail; + } + returnResponse(success); + } + + uint32_t AVOutputTV::getLocalContrastEnhancement(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + int localContraseEnhancement = 0; + bool success = getPQParamFromContext(parameters, + "LocalContrastEnhancement", + PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT, + localContraseEnhancement); + if (success) { + response["localContrastEnhancement"] = localContraseEnhancement; + } + returnResponse(success); + } + + uint32_t AVOutputTV::getMPEGNoiseReduction(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + int MPEGNoiseReduction = 0; + bool success = getPQParamFromContext(parameters, + "MPEGNoiseReduction", + PQ_PARAM_MPEG_NOISE_REDUCTION, + MPEGNoiseReduction); + if (success) { + response["mpegNoiseReduction"] = MPEGNoiseReduction; + } + returnResponse(success); + } + + uint32_t AVOutputTV::getDigitalNoiseReduction(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + int digitalNoiseReduction = 0; + bool success = getPQParamFromContext(parameters, + "DigitalNoiseReduction", + PQ_PARAM_DIGITAL_NOISE_REDUCTION, + digitalNoiseReduction); + if (success) { + response["digitalNoiseReduction"] = digitalNoiseReduction; + } + returnResponse(success); + } + + uint32_t AVOutputTV::getMEMC(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + int MEMC = 0; + bool success = getPQParamFromContext(parameters, + "MEMC", + PQ_PARAM_MEMC, + MEMC); + if (success) { + response["memc"] = MEMC; + } + returnResponse(success); + } + + uint32_t AVOutputTV::getAISuperResolution(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + int aiSuperResolution = 0; + bool success = getPQParamFromContext(parameters, + "AISuperResolution", + PQ_PARAM_AI_SUPER_RESOLUTION, + aiSuperResolution); + if (success) { + response["aiSuperResolution"] = aiSuperResolution; + } + returnResponse(success); + } + + uint32_t AVOutputTV::setContextPQParam(const JsonObject& parameters, JsonObject& response, + const std::string& inputParamName, + const std::string& tr181ParamName, + int maxAllowedValue, + tvPQParameterIndex_t pqParamType, + std::function halSetter) + { + LOGINFO("Entry"); + + if (!parameters.HasLabel(inputParamName.c_str())) { + LOGERR("Missing parameter: %s", inputParamName.c_str()); + returnResponse(false); + } + + std::string valueStr = parameters[inputParamName.c_str()].String(); + int value = std::stoi(valueStr); + + if (value < 0 || value > maxAllowedValue) { + LOGERR("Input value %d is out of range for %s", value, inputParamName.c_str()); + returnResponse(false); + } + + // Get current context + tvVideoSrcType_t currentSrc = VIDEO_SOURCE_IP; + tvVideoFormatType_t currentFmt = VIDEO_FORMAT_SDR; + tvPQModeIndex_t currentPQMode = PQ_MODE_STANDARD; + + GetCurrentVideoSource(¤tSrc); + GetCurrentVideoFormat(¤tFmt); + if (currentFmt == VIDEO_FORMAT_NONE) + currentFmt = VIDEO_FORMAT_SDR; + + char picMode[PIC_MODE_NAME_MAX] = {0}; + if (getCurrentPictureMode(picMode)) + { + auto it = pqModeReverseMap.find(picMode); + if (it != pqModeReverseMap.end()) + { + currentPQMode = static_cast(it->second); + } + else + { + LOGERR("Unknown picture mode"); + } + } + else + { + LOGERR("Failed to get current picture mode"); + } + + LOGINFO("currentPQMode: %d, currentFmt: %d, currentSrc: %d", currentPQMode, currentFmt, currentSrc); + + if (isSetRequiredForParam(parameters, tr181ParamName)) { + #if HAL_NOT_READY + #else + tvError_t ret = halSetter(currentSrc, currentPQMode, currentFmt, value); + if (ret != tvERROR_NONE) { + LOGERR("HAL setter failed for %s", inputParamName.c_str()); + returnResponse(false); + } + #endif + } + + // Persist + int retval = updateAVoutputTVParamV2("set", tr181ParamName, parameters, pqParamType, value); + if (retval != 0) { + LOGERR("Failed to save %s to ssm_data", inputParamName.c_str()); + returnResponse(false); + } + + LOGINFO("Exit: %s set successfully to %d", inputParamName.c_str(), value); + returnResponse(true); + } + + uint32_t AVOutputTV::setAISuperResolution(const JsonObject& parameters, JsonObject& response) + { + return setContextPQParam( + parameters, response, + "aiSuperResolution", + "AISuperResolution", + m_maxAISuperResolution, + PQ_PARAM_AI_SUPER_RESOLUTION, + [](tvVideoSrcType_t src, tvPQModeIndex_t mode, tvVideoFormatType_t fmt, int val) { + return SetAISuperResolution(src, mode, fmt, val); + } + ); + } + + uint32_t AVOutputTV::setMEMC(const JsonObject& parameters, JsonObject& response) + { + return setContextPQParam( + parameters, response, + "memc", "MEMC", + m_maxMEMC, + PQ_PARAM_MEMC, + [](tvVideoSrcType_t src, tvPQModeIndex_t mode, tvVideoFormatType_t fmt, int val) { + return SetMEMC(src, mode, fmt, val); + } + ); + } + + uint32_t AVOutputTV::setPrecisionDetail(const JsonObject& parameters, JsonObject& response) + { + return setContextPQParam( + parameters, response, + "precisionDetail", "PrecisionDetail", + m_maxPrecisionDetail, + PQ_PARAM_PRECISION_DETAIL, + [](tvVideoSrcType_t src, tvPQModeIndex_t mode, tvVideoFormatType_t fmt, int val) { + return SetPrecisionDetail(src, mode, fmt, val); + } + ); + } + + uint32_t AVOutputTV::setLocalContrastEnhancement(const JsonObject& parameters, JsonObject& response) + { +#if ENABLE_PQ_PARAM + return setContextPQParam( + parameters, response, + "localContrastEnhancement", "LocalContrastEnhancement", + m_maxLocalContrastEnhancement, + PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT, + [](tvVideoSrcType_t src, tvPQModeIndex_t mode, tvVideoFormatType_t fmt, int val) { + return SetLocalContrastEnhancement(src, mode, fmt, val); + } + ); +#else + returnResponse(true); +#endif + } + + uint32_t AVOutputTV::setMPEGNoiseReduction(const JsonObject& parameters, JsonObject& response) + { +#if ENABLE_PQ_PARAM + return setContextPQParam( + parameters, response, + "mpegNoiseReduction", "MPEGNoiseReduction", + m_maxMPEGNoiseReduction, + PQ_PARAM_MPEG_NOISE_REDUCTION, + [](tvVideoSrcType_t src, tvPQModeIndex_t mode, tvVideoFormatType_t fmt, int val) { + return SetMPEGNoiseReduction(src, mode, fmt, val); + } + ); +#else + returnResponse(true); +#endif + } + + uint32_t AVOutputTV::setDigitalNoiseReduction(const JsonObject& parameters, JsonObject& response) + { +#if ENABLE_PQ_PARAM + return setContextPQParam( + parameters, response, + "digitalNoiseReduction", "DigitalNoiseReduction", + m_maxDigitalNoiseReduction, + PQ_PARAM_DIGITAL_NOISE_REDUCTION, + [](tvVideoSrcType_t src, tvPQModeIndex_t mode, tvVideoFormatType_t fmt, int val) { + return SetDigitalNoiseReduction(src, mode, fmt, val); + } + ); +#else + returnResponse(true); +#endif + } + + uint32_t AVOutputTV::getBacklight(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry"); + if(m_backlightStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + std::string key; + paramIndex_t indexInfo; + int backlight = 0,err = 0; + + if (parsingGetInputArgument(parameters, "Backlight",inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } + + if (isPlatformSupport("Backlight") != 0) { + returnResponse(false); + } + + if (getParamIndex("Backlight", inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } + + err = getLocalparam("Backlight",indexInfo,backlight, PQ_PARAM_BACKLIGHT); + if( err == 0 ) { + response["backlight"] = backlight; + LOGINFO("Exit : Backlight Value: %d \n", backlight); + returnResponse(true); + } + else { + returnResponse(false); + } + } + else + { + int backlight = 0; + bool success = getPQParamFromContext(parameters, + "Backlight", + PQ_PARAM_BACKLIGHT, + backlight); + if (success) { + response["backlight"] = backlight; + } + returnResponse(success); + + } + } + + uint32_t AVOutputTV::setBacklight(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry\n"); + if(m_backlightStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + std::string value; + capDetails_t inputInfo; + int backlight = 0; + tvError_t ret = tvERROR_NONE; + + value = parameters.HasLabel("backlight") ? parameters["backlight"].String() : ""; + returnIfParamNotFound(parameters,"backlight"); + backlight = std::stoi(value); + + if (validateIntegerInputParameter("Backlight",backlight) != 0) { + LOGERR("Failed in Backlight range validation:%s", __FUNCTION__); + returnResponse(false); + } + + if (parsingSetInputArgument(parameters,"Backlight",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } + + if (isPlatformSupport("Backlight") != 0 ) { + returnResponse(false); + } + + if( !isCapablityCheckPassed( "Backlight" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for Backlight\n", __FUNCTION__); + returnResponse(false); + } + + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with setBacklight\n"); + ret = SetBacklight(backlight); + } + + if(ret != tvERROR_NONE) { + LOGERR("Failed to set Backlight\n"); + returnResponse(false); + } + else { + int retval= updateAVoutputTVParam("set","Backlight",inputInfo,PQ_PARAM_BACKLIGHT,backlight); + if(retval != 0 ) { + LOGERR("Failed to Save Backlight to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setBacklight successful to value: %d\n", backlight); + returnResponse(true); + } + } + else + { + bool success = setIntPQParam(parameters, "Backlight", PQ_PARAM_BACKLIGHT, SetBacklight, m_maxBacklight); + returnResponse(success); } - } - uint32_t AVOutputTV::getBacklight(const JsonObject& parameters, JsonObject& response) + } + bool AVOutputTV::resetEnumPQParamToDefault( + const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqIndex, + const std::unordered_map& valueMap, + std::function&)> halSetter) { - LOGINFO("Entry"); + LOGINFO("Entry: %s\n", paramName.c_str()); capDetails_t inputInfo; - std::string key; paramIndex_t indexInfo; - int backlight = 0,err = 0; + int intVal = 0; + tvError_t ret = tvERROR_NONE; - if (parsingGetInputArgument(parameters, "Backlight",inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); + // Step 1: Save reset state using V2 persistence + LOGINFO("Updating AVOutputTVParamV2 for: %s\n", paramName.c_str()); + int retval = updateAVoutputTVParamV2("reset", paramName, parameters, pqIndex, intVal); + if (retval != 0) { + LOGERR("Failed to reset %s via updateAVoutputTVParamV2. retval: %d\n", paramName.c_str(), retval); + return false; } - if (isPlatformSupport("Backlight") != 0) { - returnResponse(false); - } + // Step 2: Apply value from persisted config to HAL if needed + if (isSetRequiredForParam(parameters, paramName)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; - if (getParamIndex("Backlight", inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex(paramName, inputInfo, indexInfo) == 0 && + getLocalparam(paramName, indexInfo, intVal, pqIndex) == 0) + { + LOGINFO("%s: getLocalparam success for %s [format=%d, source=%d, mode=%d] → value=%d\n", + __FUNCTION__, paramName.c_str(), indexInfo.formatIndex, + indexInfo.sourceIndex, indexInfo.pqmodeIndex, intVal); - err = getLocalparam("Backlight",indexInfo,backlight, PQ_PARAM_BACKLIGHT); - if( err == 0 ) { - response["backlight"] = backlight; - LOGINFO("Exit : Backlight Value: %d \n", backlight); - returnResponse(true); - } - else { - returnResponse(false); + if (valueMap.find(intVal) == valueMap.end()) { + LOGERR("%s: Invalid enum value %d for %s\n", __FUNCTION__, intVal, paramName.c_str()); + return false; + } + + ret = halSetter(intVal, valueMap); + if (ret != tvERROR_NONE) { + LOGERR("%s: HAL setter failed for value %d\n", paramName.c_str(), intVal); + return false; + } + } + else { + LOGERR("%s: Failed to get local param for %s\n", __FUNCTION__, paramName.c_str()); + return false; + } } + + LOGINFO("Exit: resetEnumPQParamToDefault for %s successful (value: %d)\n", paramName.c_str(), intVal); + return true; } - uint32_t AVOutputTV::setBacklight(const JsonObject& parameters, JsonObject& response) + bool AVOutputTV::resetPQParamToDefault(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqIndex, + tvSetFunctionV2 halSetter) { - LOGINFO("Entry\n"); + LOGINFO("Entry: %s\n", paramName.c_str()); - std::string value; capDetails_t inputInfo; - int backlight = 0; - tvError_t ret = tvERROR_NONE; - - value = parameters.HasLabel("backlight") ? parameters["backlight"].String() : ""; - returnIfParamNotFound(parameters,"backlight"); - backlight = std::stoi(value); + paramIndex_t indexInfo; + int level = 0; + tvError_t ret = tvERROR_NONE; - if (validateIntegerInputParameter("Backlight",backlight) != 0) { - LOGERR("Failed in Backlight range validation:%s", __FUNCTION__); - returnResponse(false); + // Save reset state using V2 path + LOGINFO("Updating AVOutputTVParamV2 for: %s\n", paramName.c_str()); + int retval = updateAVoutputTVParamV2("reset", paramName, parameters, pqIndex, level); + if (retval != 0) + { + LOGERR("Failed to update %s via updateAVoutputTVParamV2. retval: %d\n", paramName.c_str(), retval); + return false; } - if (parsingSetInputArgument(parameters,"Backlight",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + // If update succeeded, apply value from local config to HAL + if (isSetRequiredForParam(parameters, paramName)) + { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; - if (isPlatformSupport("Backlight") != 0 ) { - returnResponse(false); + if (getParamIndex(paramName, inputInfo, indexInfo) == 0 && + getLocalparam(paramName, indexInfo, level, pqIndex) == 0) + { + LOGINFO("%s: getLocalparam success for %s: format=%d, source=%d, mode=%d, value=%d\n", + __FUNCTION__, paramName.c_str(), indexInfo.formatIndex, + indexInfo.sourceIndex, indexInfo.pqmodeIndex, level); + if (halSetter) { + ret = halSetter( + static_cast(indexInfo.sourceIndex), + static_cast(indexInfo.pqmodeIndex), + static_cast(indexInfo.formatIndex), + level); + LOGINFO("%s halSetter return value: %d\n", paramName.c_str(), ret); + } else { + LOGERR("halSetter is null for %s\n", paramName.c_str()); + return false; + } + } + else + { + LOGERR("%s: Failed to get local param for %s\n", __FUNCTION__, paramName.c_str()); + return false; + } } - if( !isCapablityCheckPassed( "Backlight" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for Backlight\n", __FUNCTION__); - returnResponse(false); - } + LOGINFO("Exit: reset%s successful to value: %d\n", paramName.c_str(), level); + return true; + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with setBacklight\n"); - ret = SetBacklight(backlight); - } + bool AVOutputTV::resetPQParamToDefault(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqIndex, + tvSetFunction halSetter) + { + LOGINFO("Entry: %s\n", paramName.c_str()); - if(ret != tvERROR_NONE) { - LOGERR("Failed to set Backlight\n"); - returnResponse(false); + capDetails_t inputInfo; + paramIndex_t indexInfo; + int level = 0; + tvError_t ret = tvERROR_NONE; + + // Save reset state using V2 path + LOGINFO("Updating AVOutputTVParamV2 for: %s\n", paramName.c_str()); + int retval = updateAVoutputTVParamV2("reset", paramName, parameters, pqIndex, level); + if (retval != 0) + { + LOGERR("Failed to update %s via updateAVoutputTVParamV2. retval: %d\n", paramName.c_str(), retval); + return false; } - else { - int retval= updateAVoutputTVParam("set","Backlight",inputInfo,PQ_PARAM_BACKLIGHT,backlight); - if(retval != 0 ) { - LOGERR("Failed to Save Backlight to ssm_data\n"); - returnResponse(false); + + // If update succeeded, apply value from local config to HAL + if (isSetRequiredForParam(parameters, paramName)) + { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + + if (getParamIndex(paramName, inputInfo, indexInfo) == 0 && + getLocalparam(paramName, indexInfo, level, pqIndex) == 0) + { + LOGINFO("%s: getLocalparam success for %s: format=%d, source=%d, mode=%d, value=%d\n", + __FUNCTION__, paramName.c_str(), indexInfo.formatIndex, + indexInfo.sourceIndex, indexInfo.pqmodeIndex, level); + ret = halSetter(level); + LOGINFO("%s halSetter return value: %d\n", paramName.c_str(), ret); + } + else + { + LOGERR("%s: Failed to get local param for %s\n", __FUNCTION__, paramName.c_str()); + return false; } - LOGINFO("Exit : setBacklight successful to value: %d\n", backlight); - returnResponse(true); } + LOGINFO("Exit: reset%s successful to value: %d\n", paramName.c_str(), level); + return true; } uint32_t AVOutputTV::resetBacklight(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - capDetails_t inputInfo; - int backlight=0; - paramIndex_t indexInfo; - tvError_t ret = tvERROR_NONE; + if(m_backlightStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + int backlight=0; + paramIndex_t indexInfo; + tvError_t ret = tvERROR_NONE; - if (parsingSetInputArgument(parameters, "Backlight",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Backlight",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if (isPlatformSupport("Backlight") != 0) { - returnResponse(false); - } + if (isPlatformSupport("Backlight") != 0) { + returnResponse(false); + } - if( !isCapablityCheckPassed( "Backlight",inputInfo )) { - LOGERR("%s: CapablityCheck failed for Backlight\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Backlight",inputInfo )) { + LOGERR("%s: CapablityCheck failed for Backlight\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","Backlight",inputInfo,PQ_PARAM_BACKLIGHT,backlight); - if(retval != 0 ) { - LOGERR("Failed to reset Backlight\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("Backlight", inputInfo,indexInfo); - int err = getLocalparam("Backlight",indexInfo,backlight, PQ_PARAM_BACKLIGHT); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,backlight); - ret = SetBacklight(backlight); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + int retval= updateAVoutputTVParam("reset","Backlight",inputInfo,PQ_PARAM_BACKLIGHT,backlight); + if(retval != 0 ) { + LOGERR("Failed to reset Backlight\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("Backlight", inputInfo,indexInfo); + int err = getLocalparam("Backlight",indexInfo,backlight, PQ_PARAM_BACKLIGHT); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,backlight); + ret = SetBacklight(backlight); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetBacklight Successful to value : %d \n",backlight); + returnResponse(true); + } } - else { - LOGINFO("Exit : resetBacklight Successful to value : %d \n",backlight); - returnResponse(true); + else + { + bool success= resetPQParamToDefault(parameters, "Backlight", PQ_PARAM_BACKLIGHT, SetBacklight); + returnResponse(success); } } @@ -904,79 +2297,99 @@ namespace Plugin { uint32_t AVOutputTV::getBrightness(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_brightnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int brightness = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int brightness = 0; - - if (parsingGetInputArgument(parameters, "Brightness",inputInfo) != 0) { - LOGERR("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } + if (parsingGetInputArgument(parameters, "Brightness",inputInfo) != 0) { + LOGERR("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - if (getParamIndex("Brightness", inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("Brightness", inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - int err = getLocalparam("Brightness",indexInfo,brightness, PQ_PARAM_BRIGHTNESS); - if( err == 0 ) { - response["brightness"] = brightness; - LOGINFO("Exit : Brightness Value: %d \n", brightness); - returnResponse(true); + int err = getLocalparam("Brightness",indexInfo,brightness, PQ_PARAM_BRIGHTNESS); + if( err == 0 ) { + response["brightness"] = brightness; + LOGINFO("Exit : Brightness Value: %d \n", brightness); + returnResponse(true); + } + else { + returnResponse(false); + } } - else { - returnResponse(false); + else + { + int brightness = 0; + bool success = getPQParamFromContext(parameters, + "Brightness", + PQ_PARAM_BRIGHTNESS, + brightness); + if (success) { + response["brightness"] = brightness; + } + returnResponse(success); } } uint32_t AVOutputTV::setBrightness(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_brightnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + std::string value; + capDetails_t inputInfo; + int brightness = 0; + tvError_t ret = tvERROR_NONE; - std::string value; - capDetails_t inputInfo; - int brightness = 0; - tvError_t ret = tvERROR_NONE; - - value = parameters.HasLabel("brightness") ? parameters["brightness"].String() : ""; - returnIfParamNotFound(parameters,"brightness"); - brightness = stoi(value); + value = parameters.HasLabel("brightness") ? parameters["brightness"].String() : ""; + returnIfParamNotFound(parameters,"brightness"); + brightness = stoi(value); - if (validateIntegerInputParameter("Brightness",brightness) != 0) { - LOGERR("Failed in Brightness range validation:%s", __FUNCTION__); - returnResponse(false); - } + if (validateIntegerInputParameter("Brightness",brightness) != 0) { + LOGERR("Failed in Brightness range validation:%s", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters, "Brightness",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Brightness",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Brightness",inputInfo )) { - LOGERR("%s: CapablityCheck failed for Brightness\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Brightness",inputInfo )) { + LOGERR("%s: CapablityCheck failed for Brightness\n", __FUNCTION__); + returnResponse(false); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s \n",__FUNCTION__); - ret = SetBrightness(brightness); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s \n",__FUNCTION__); + ret = SetBrightness(brightness); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set Brightness\n"); - returnResponse(false); - } - else { - int retval= updateAVoutputTVParam("set","Brightness",inputInfo,PQ_PARAM_BRIGHTNESS,brightness); - if(retval != 0 ) { - LOGERR("Failed to Save Brightness to ssm_data\n"); + if(ret != tvERROR_NONE) { + LOGERR("Failed to set Brightness\n"); returnResponse(false); } - LOGINFO("Exit : setBrightness successful to value: %d\n", brightness); - returnResponse(true); + else { + int retval= updateAVoutputTVParam("set","Brightness",inputInfo,PQ_PARAM_BRIGHTNESS,brightness); + if(retval != 0 ) { + LOGERR("Failed to Save Brightness to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setBrightness successful to value: %d\n", brightness); + returnResponse(true); + } + } + else + { + bool success = setIntPQParam(parameters, "Brightness", PQ_PARAM_BRIGHTNESS, SetBrightness, m_maxBrightness); + returnResponse(success); } - } @@ -984,54 +2397,60 @@ namespace Plugin { { LOGINFO("Entry\n"); + if(m_brightnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + std::string value; + capDetails_t inputInfo; + paramIndex_t indexInfo; + int brightness=0; + tvError_t ret = tvERROR_NONE; + + if (parsingSetInputArgument(parameters, "Brightness",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - std::string value; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int brightness=0; - tvError_t ret = tvERROR_NONE; - - if (parsingSetInputArgument(parameters, "Brightness",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } - - if( !isCapablityCheckPassed( "Brightness",inputInfo )) { - LOGERR("%s: CapablityCheck failed for Brightness\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Brightness",inputInfo )) { + LOGERR("%s: CapablityCheck failed for Brightness\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","Brightness",inputInfo,PQ_PARAM_BRIGHTNESS,brightness); - if(retval != 0 ) { - LOGWARN("Failed to reset Brightness\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("Brightness", inputInfo,indexInfo); - int err = getLocalparam("Brightness",indexInfo,brightness, PQ_PARAM_BRIGHTNESS); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,brightness); - ret = SetBrightness(brightness); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + int retval= updateAVoutputTVParam("reset","Brightness",inputInfo,PQ_PARAM_BRIGHTNESS,brightness); + if(retval != 0 ) { + LOGWARN("Failed to reset Brightness\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("Brightness", inputInfo,indexInfo); + int err = getLocalparam("Brightness",indexInfo,brightness, PQ_PARAM_BRIGHTNESS); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,brightness); + ret = SetBrightness(brightness); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetBrightness Successful to value : %d \n",brightness); + returnResponse(true); + } } - else { - LOGINFO("Exit : resetBrightness Successful to value : %d \n",brightness); - returnResponse(true); + else + { + bool success = resetPQParamToDefault(parameters, "Brightness", PQ_PARAM_BRIGHTNESS, SetBrightness); + returnResponse(success); } - } uint32_t AVOutputTV::getBrightnessCaps(const JsonObject& parameters, JsonObject& response) @@ -1082,133 +2501,161 @@ namespace Plugin { uint32_t AVOutputTV::getContrast(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_contrastStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int contrast = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int contrast = 0; + if (parsingGetInputArgument(parameters, "Contrast",inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - if (parsingGetInputArgument(parameters, "Contrast",inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("Contrast",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - if (getParamIndex("Contrast",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); + int err = getLocalparam("Contrast",indexInfo,contrast, PQ_PARAM_CONTRAST); + if( err == 0 ) { + response["contrast"] = contrast; + LOGINFO("Exit : Contrast Value: %d \n", contrast); + returnResponse(true); + } + else { + returnResponse(false); + } } + else + { + int contrast = 0; + bool success = getPQParamFromContext(parameters, + "Contrast", + PQ_PARAM_CONTRAST, + contrast); + if (success) { + response["contrast"] = contrast; + } + returnResponse(success); - int err = getLocalparam("Contrast",indexInfo,contrast, PQ_PARAM_CONTRAST); - if( err == 0 ) { - response["contrast"] = contrast; - LOGINFO("Exit : Contrast Value: %d \n", contrast); - returnResponse(true); - } - else { - returnResponse(false); } } uint32_t AVOutputTV::setContrast(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_contrastStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + int contrast = 0; + tvError_t ret = tvERROR_NONE; + std::string value; - capDetails_t inputInfo; - int contrast = 0; - tvError_t ret = tvERROR_NONE; - std::string value; - - value = parameters.HasLabel("contrast") ? parameters["contrast"].String() : ""; - returnIfParamNotFound(parameters,"contrast"); - contrast = std::stoi(value); + value = parameters.HasLabel("contrast") ? parameters["contrast"].String() : ""; + returnIfParamNotFound(parameters,"contrast"); + contrast = std::stoi(value); - if (validateIntegerInputParameter("Contrast", contrast) != 0) { - LOGERR("Failed in contrast range validation:%s", __FUNCTION__); - returnResponse(false); - } + if (validateIntegerInputParameter("Contrast", contrast) != 0) { + LOGERR("Failed in contrast range validation:%s", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters, "Contrast",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Contrast",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Contrast" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for Contrast\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Contrast" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for Contrast\n", __FUNCTION__); + returnResponse(false); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s \n",__FUNCTION__); - ret = SetContrast(contrast); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s \n",__FUNCTION__); + ret = SetContrast(contrast); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set Contrast\n"); - returnResponse(false); - } - else { - int retval= updateAVoutputTVParam("set","Contrast",inputInfo,PQ_PARAM_CONTRAST,contrast); - if(retval != 0 ) { - LOGERR("Failed to Save Contrast to ssm_data\n"); + if(ret != tvERROR_NONE) { + LOGERR("Failed to set Contrast\n"); returnResponse(false); } - LOGINFO("Exit : setContrast successful to value: %d\n", contrast); - returnResponse(true); + else { + int retval= updateAVoutputTVParam("set","Contrast",inputInfo,PQ_PARAM_CONTRAST,contrast); + if(retval != 0 ) { + LOGERR("Failed to Save Contrast to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setContrast successful to value: %d\n", contrast); + returnResponse(true); + } + } + else + { + bool success = setIntPQParam(parameters, "Contrast", PQ_PARAM_CONTRAST, SetContrast, m_maxContrast); + returnResponse(success); } - } uint32_t AVOutputTV::resetContrast(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_contrastStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int contrast=0; + tvError_t ret = tvERROR_NONE; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int contrast=0; - tvError_t ret = tvERROR_NONE; - - if (parsingSetInputArgument(parameters, "Contrast",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Contrast",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Contrast" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for Contrast\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Contrast" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for Contrast\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","Contrast",inputInfo,PQ_PARAM_CONTRAST,contrast); + int retval= updateAVoutputTVParam("reset","Contrast",inputInfo,PQ_PARAM_CONTRAST,contrast); - if(retval != 0 ) { - LOGWARN("Failed to reset Contrast\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("Contrast", inputInfo,indexInfo); - int err = getLocalparam("Contrast",indexInfo,contrast, PQ_PARAM_CONTRAST); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,contrast); - ret = SetContrast(contrast); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + if(retval != 0 ) { + LOGWARN("Failed to reset Contrast\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("Contrast", inputInfo,indexInfo); + int err = getLocalparam("Contrast",indexInfo,contrast, PQ_PARAM_CONTRAST); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,contrast); + ret = SetContrast(contrast); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); - } - else { - LOGINFO("Exit : resetContrast Successful to value : %d \n",contrast); - returnResponse(true); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetContrast Successful to value : %d \n",contrast); + returnResponse(true); + } } + else + { + bool success= resetPQParamToDefault(parameters, "Contrast", PQ_PARAM_CONTRAST, SetContrast); + returnResponse(success); + } } uint32_t AVOutputTV::getContrastCaps(const JsonObject& parameters, JsonObject& response) @@ -1260,133 +2707,160 @@ namespace Plugin { uint32_t AVOutputTV::getSaturation(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_saturationStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int saturation = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int saturation = 0; + if (parsingGetInputArgument(parameters, "Saturation",inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - if (parsingGetInputArgument(parameters, "Saturation",inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("Saturation", inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - if (getParamIndex("Saturation", inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); + int err = getLocalparam("Saturation",indexInfo,saturation, PQ_PARAM_SATURATION); + if( err == 0 ) { + response["saturation"] = saturation; + LOGINFO("Exit : Saturation Value: %d \n", saturation); + returnResponse(true); + } + else { + returnResponse(false); + } } + else + { + int saturation = 0; + bool success = getPQParamFromContext(parameters, + "Saturation", + PQ_PARAM_SATURATION, + saturation); + if (success) { + response["saturation"] = saturation; + } + returnResponse(success); - int err = getLocalparam("Saturation",indexInfo,saturation, PQ_PARAM_SATURATION); - if( err == 0 ) { - response["saturation"] = saturation; - LOGINFO("Exit : Saturation Value: %d \n", saturation); - returnResponse(true); - } - else { - returnResponse(false); } } uint32_t AVOutputTV::setSaturation(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_saturationStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + std::string value; + int saturation = 0; + tvError_t ret = tvERROR_NONE; - capDetails_t inputInfo; - std::string value; - int saturation = 0; - tvError_t ret = tvERROR_NONE; - - value = parameters.HasLabel("saturation") ? parameters["saturation"].String() : ""; - returnIfParamNotFound(parameters,"saturation"); - saturation = std::stoi(value); + value = parameters.HasLabel("saturation") ? parameters["saturation"].String() : ""; + returnIfParamNotFound(parameters,"saturation"); + saturation = std::stoi(value); - if (validateIntegerInputParameter("Saturation",saturation) != 0) { - LOGERR("Failed in saturation range validation:%s", __FUNCTION__); - returnResponse(false); - } + if (validateIntegerInputParameter("Saturation",saturation) != 0) { + LOGERR("Failed in saturation range validation:%s", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters, "Saturation",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Saturation",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Saturation" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for Saturation\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Saturation" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for Saturation\n", __FUNCTION__); + returnResponse(false); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - ret = SetSaturation(saturation); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + ret = SetSaturation(saturation); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set Saturation\n"); - returnResponse(false); - } - else { - int retval= updateAVoutputTVParam("set","Saturation",inputInfo,PQ_PARAM_SATURATION,saturation); - if(retval != 0 ) { - LOGERR("Failed to Save Saturation to ssm_data\n"); + if(ret != tvERROR_NONE) { + LOGERR("Failed to set Saturation\n"); returnResponse(false); } - LOGINFO("Exit : setSaturation successful to value: %d\n", saturation); - returnResponse(true); + else { + int retval= updateAVoutputTVParam("set","Saturation",inputInfo,PQ_PARAM_SATURATION,saturation); + if(retval != 0 ) { + LOGERR("Failed to Save Saturation to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setSaturation successful to value: %d\n", saturation); + returnResponse(true); + } + } + else + { + bool success = setIntPQParam(parameters, "Saturation", PQ_PARAM_SATURATION, SetSaturation, m_maxSaturation); + returnResponse(success); } - } uint32_t AVOutputTV::resetSaturation(const JsonObject& parameters, JsonObject& response) { - LOGINFO("Entry\n"); + if(m_saturationStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int saturation=0; + tvError_t ret = tvERROR_NONE; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int saturation=0; - tvError_t ret = tvERROR_NONE; - - if (parsingSetInputArgument(parameters, "Saturation", inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Saturation", inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Saturation", inputInfo )) { - LOGERR("%s: CapablityCheck failed for Saturation\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Saturation", inputInfo )) { + LOGERR("%s: CapablityCheck failed for Saturation\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","Saturation",inputInfo,PQ_PARAM_SATURATION,saturation); + int retval= updateAVoutputTVParam("reset","Saturation",inputInfo,PQ_PARAM_SATURATION,saturation); - if(retval != 0 ) { - LOGERR("Failed to reset Saturation\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("Saturation",inputInfo,indexInfo); - int err = getLocalparam("Saturation",indexInfo, saturation, PQ_PARAM_SATURATION); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,saturation); - ret = SetSaturation(saturation); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + if(retval != 0 ) { + LOGERR("Failed to reset Saturation\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("Saturation",inputInfo,indexInfo); + int err = getLocalparam("Saturation",indexInfo, saturation, PQ_PARAM_SATURATION); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,saturation); + ret = SetSaturation(saturation); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); - } - else { - LOGINFO("Exit : resetSaturation Successful to value : %d \n",saturation); - returnResponse(true); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetSaturation Successful to value : %d \n",saturation); + returnResponse(true); + } } + else + { + bool success= resetPQParamToDefault(parameters, "Saturation", PQ_PARAM_SATURATION, SetSaturation); + returnResponse(success); + } } uint32_t AVOutputTV::getSaturationCaps(const JsonObject& parameters, JsonObject& response) @@ -1439,131 +2913,160 @@ namespace Plugin { uint32_t AVOutputTV::getSharpness(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_sharpnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int sharpness = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int sharpness = 0; + if (parsingGetInputArgument(parameters, "Sharpness",inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - if (parsingGetInputArgument(parameters, "Sharpness",inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("Sharpness",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - if (getParamIndex("Sharpness",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); + int err = getLocalparam("Sharpness",indexInfo,sharpness, PQ_PARAM_SHARPNESS); + if( err == 0 ) { + response["sharpness"] = sharpness; + LOGINFO("Exit : Sharpness Value: %d \n", sharpness); + returnResponse(true); + } + else { + returnResponse(false); + } } + else + { + int sharpness = 0; + bool success = getPQParamFromContext(parameters, + "Sharpness", + PQ_PARAM_SHARPNESS, + sharpness); + if (success) { + response["sharpness"] = sharpness; + } + returnResponse(success); - int err = getLocalparam("Sharpness",indexInfo,sharpness, PQ_PARAM_SHARPNESS); - if( err == 0 ) { - response["sharpness"] = sharpness; - LOGINFO("Exit : Sharpness Value: %d \n", sharpness); - returnResponse(true); - } - else { - returnResponse(false); } } uint32_t AVOutputTV::setSharpness(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_sharpnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + int sharpness = 0; + tvError_t ret = tvERROR_NONE; + std::string value; - capDetails_t inputInfo; - int sharpness = 0; - tvError_t ret = tvERROR_NONE; - std::string value; - - value = parameters.HasLabel("sharpness") ? parameters["sharpness"].String() : ""; - returnIfParamNotFound(parameters,"sharpness"); - sharpness = std::stoi(value); - - if (validateIntegerInputParameter("Sharpness",sharpness) != 0) { - LOGERR("Failed in sharpness range validation:%s", __FUNCTION__); - returnResponse(false); - } + value = parameters.HasLabel("sharpness") ? parameters["sharpness"].String() : ""; + returnIfParamNotFound(parameters,"sharpness"); + sharpness = std::stoi(value); - if (parsingSetInputArgument(parameters, "Sharpness", inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (validateIntegerInputParameter("Sharpness",sharpness) != 0) { + LOGERR("Failed in sharpness range validation:%s", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Sharpness", inputInfo )) { - LOGERR("%s: CapablityCheck failed for Sharpness\n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Sharpness", inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - ret = SetSharpness(sharpness); - } + if( !isCapablityCheckPassed( "Sharpness", inputInfo )) { + LOGERR("%s: CapablityCheck failed for Sharpness\n", __FUNCTION__); + returnResponse(false); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set Sharpness\n"); - returnResponse(false); - } - else { - int retval= updateAVoutputTVParam("set","Sharpness",inputInfo,PQ_PARAM_SHARPNESS,sharpness); - if(retval != 0 ) { - LOGERR("Failed to Save Sharpness to ssm_data\n"); + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + ret = SetSharpness(sharpness); + } + + if(ret != tvERROR_NONE) { + LOGERR("Failed to set Sharpness\n"); returnResponse(false); } - LOGINFO("Exit : setSharpness successful to value: %d\n", sharpness); - returnResponse(true); + else { + int retval= updateAVoutputTVParam("set","Sharpness",inputInfo,PQ_PARAM_SHARPNESS,sharpness); + if(retval != 0 ) { + LOGERR("Failed to Save Sharpness to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setSharpness successful to value: %d\n", sharpness); + returnResponse(true); + } + } + else + { + bool success = setIntPQParam(parameters, "Sharpness", PQ_PARAM_SHARPNESS, SetSharpness, m_maxSharpness); + returnResponse(success); } - } uint32_t AVOutputTV::resetSharpness(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_sharpnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int sharpness=0; + tvError_t ret = tvERROR_NONE; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int sharpness=0; - tvError_t ret = tvERROR_NONE; - - if (parsingSetInputArgument(parameters, "Sharpness",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Sharpness",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Sharpness" , inputInfo)) { - LOGERR("%s: CapablityCheck failed for Sharpness\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Sharpness" , inputInfo)) { + LOGERR("%s: CapablityCheck failed for Sharpness\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","Sharpness", inputInfo,PQ_PARAM_SHARPNESS,sharpness); + int retval= updateAVoutputTVParam("reset","Sharpness", inputInfo,PQ_PARAM_SHARPNESS,sharpness); - if(retval != 0 ) { - LOGERR("Failed to reset Sharpness\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("Sharpness",inputInfo,indexInfo); - int err = getLocalparam("Sharpness",indexInfo, sharpness, PQ_PARAM_SHARPNESS); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,sharpness); - ret = SetSharpness(sharpness); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + if(retval != 0 ) { + LOGERR("Failed to reset Sharpness\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("Sharpness",inputInfo,indexInfo); + int err = getLocalparam("Sharpness",indexInfo, sharpness, PQ_PARAM_SHARPNESS); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,sharpness); + ret = SetSharpness(sharpness); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetSharpness Successful to value : %d \n",sharpness); + returnResponse(true); + } } - else { - LOGINFO("Exit : resetSharpness Successful to value : %d \n",sharpness); - returnResponse(true); + else + { + bool success= resetPQParamToDefault(parameters, "Sharpness", PQ_PARAM_SHARPNESS, SetSharpness); + returnResponse(success); + } } @@ -1617,131 +3120,160 @@ namespace Plugin { uint32_t AVOutputTV::getHue(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_hueStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int hue = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int hue = 0; + if (parsingGetInputArgument(parameters, "Hue", inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - if (parsingGetInputArgument(parameters, "Hue", inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("Hue",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - if (getParamIndex("Hue",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); + int err = getLocalparam("Hue",indexInfo,hue, PQ_PARAM_HUE); + if( err == 0 ) { + response["hue"] = hue; + LOGINFO("Exit : Hue Value: %d \n", hue); + returnResponse(true); + } + else { + returnResponse(false); + } } + else + { + int hue = 0; + bool success = getPQParamFromContext(parameters, + "Hue", + PQ_PARAM_HUE, + hue); + if (success) { + response["hue"] = hue; + } + returnResponse(success); - int err = getLocalparam("Hue",indexInfo,hue, PQ_PARAM_HUE); - if( err == 0 ) { - response["hue"] = hue; - LOGINFO("Exit : Hue Value: %d \n", hue); - returnResponse(true); - } - else { - returnResponse(false); } } uint32_t AVOutputTV::setHue(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_hueStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + int hue = 0; + tvError_t ret = tvERROR_NONE; + std::string value; - capDetails_t inputInfo; - int hue = 0; - tvError_t ret = tvERROR_NONE; - std::string value; - - value = parameters.HasLabel("hue") ? parameters["hue"].String() : ""; - returnIfParamNotFound(parameters,"hue"); - hue = std::stoi(value); + value = parameters.HasLabel("hue") ? parameters["hue"].String() : ""; + returnIfParamNotFound(parameters,"hue"); + hue = std::stoi(value); - if (validateIntegerInputParameter("Hue",hue) != 0) { - LOGERR("Failed in hue range validation:%s", __FUNCTION__); - returnResponse(false); - } + if (validateIntegerInputParameter("Hue",hue) != 0) { + LOGERR("Failed in hue range validation:%s", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters, "Hue",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Hue",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Hue", inputInfo )) { - LOGERR("%s: CapablityCheck failed for Hue\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Hue", inputInfo )) { + LOGERR("%s: CapablityCheck failed for Hue\n", __FUNCTION__); + returnResponse(false); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - ret = SetHue(hue); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + ret = SetHue(hue); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set Hue\n"); - returnResponse(false); - } - else { - int retval= updateAVoutputTVParam("set","Hue",inputInfo,PQ_PARAM_HUE,hue); - if(retval != 0 ) { - LOGERR("Failed to Save Hue to ssm_data\n"); + if(ret != tvERROR_NONE) { + LOGERR("Failed to set Hue\n"); returnResponse(false); } - LOGINFO("Exit : setHue successful to value: %d\n", hue); - returnResponse(true); + else { + int retval= updateAVoutputTVParam("set","Hue",inputInfo,PQ_PARAM_HUE,hue); + if(retval != 0 ) { + LOGERR("Failed to Save Hue to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setHue successful to value: %d\n", hue); + returnResponse(true); + } + } + else + { + bool success = setIntPQParam(parameters, "Hue", PQ_PARAM_HUE, SetHue, m_maxHue); + returnResponse(success); } - } uint32_t AVOutputTV::resetHue(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_hueStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int hue=0; + tvError_t ret = tvERROR_NONE; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int hue=0; - tvError_t ret = tvERROR_NONE; - - if (parsingSetInputArgument(parameters, "Hue",inputInfo)!= 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "Hue",inputInfo)!= 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "Hue" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for Hue\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "Hue" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for Hue\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","Hue", inputInfo,PQ_PARAM_HUE,hue); + int retval= updateAVoutputTVParam("reset","Hue", inputInfo,PQ_PARAM_HUE,hue); - if(retval != 0 ) { - LOGERR("Failed to reset Hue\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("Hue",inputInfo,indexInfo); - int err = getLocalparam("Hue",indexInfo, hue, PQ_PARAM_HUE); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,hue); - ret = SetHue(hue); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + if(retval != 0 ) { + LOGERR("Failed to reset Hue\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("Hue",inputInfo,indexInfo); + int err = getLocalparam("Hue",indexInfo, hue, PQ_PARAM_HUE); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex,hue); + ret = SetHue(hue); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetHue Successful to value : %d \n",hue); + returnResponse(true); + } } - else { - LOGINFO("Exit : resetHue Successful to value : %d \n",hue); - returnResponse(true); + else + { + bool success= resetPQParamToDefault(parameters, "Hue", PQ_PARAM_HUE, SetHue); + returnResponse(success); + } } @@ -1795,110 +3327,146 @@ namespace Plugin { uint32_t AVOutputTV::getColorTemperature(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_colorTempStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int colortemp = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int colortemp = 0; - - if (parsingGetInputArgument(parameters, "ColorTemperature", inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } - - if (getParamIndex("ColorTemperature",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); - } - - int err = getLocalparam("ColorTemp",indexInfo,colortemp,PQ_PARAM_COLOR_TEMPERATURE); - if( err == 0 ) { - switch(colortemp) { - case tvColorTemp_STANDARD: - LOGINFO("Color Temp Value: Standard\n"); - response["colorTemperature"] = "Standard"; - break; - - case tvColorTemp_WARM: - LOGINFO("Color Temp Value: Warm\n"); - response["colorTemperature"] = "Warm"; - break; - - case tvColorTemp_COLD: - LOGINFO("Color Temp Value: Cold\n"); - response["colorTemperature"] = "Cold"; - break; + if (parsingGetInputArgument(parameters, "ColorTemperature", inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - case tvColorTemp_USER: - LOGINFO("Color Temp Value: User Defined\n"); - response["colorTemperature"] = "UserDefined"; - break; + if (getParamIndex("ColorTemperature",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - default: - LOGINFO("Color Temp Value: Standard\n"); - response["colorTemperature"] = "Standard"; - break; + int err = getLocalparam("ColorTemp",indexInfo,colortemp,PQ_PARAM_COLOR_TEMPERATURE); + if( err == 0 ) { + switch(colortemp) { + case tvColorTemp_STANDARD: + LOGINFO("Color Temp Value: Standard\n"); + response["colorTemperature"] = "Standard"; + break; + + case tvColorTemp_WARM: + LOGINFO("Color Temp Value: Warm\n"); + response["colorTemperature"] = "Warm"; + break; + + case tvColorTemp_COLD: + LOGINFO("Color Temp Value: Cold\n"); + response["colorTemperature"] = "Cold"; + break; + + case tvColorTemp_USER: + LOGINFO("Color Temp Value: User Defined\n"); + response["colorTemperature"] = "UserDefined"; + break; + + default: + LOGINFO("Color Temp Value: Standard\n"); + response["colorTemperature"] = "Standard"; + break; + } + LOGINFO("Exit : ColorTemperature Value: %d \n", colortemp); + returnResponse(true); + } + else { + returnResponse(false); } - LOGINFO("Exit : ColorTemperature Value: %d \n", colortemp); - returnResponse(true); } - else { - returnResponse(false); + else + { + std::string outMode; + if (getEnumPQParamString(parameters, "ColorTemp", + PQ_PARAM_COLOR_TEMPERATURE, colorTempReverseMap, outMode)) { + response["colorTemperature"] = outMode; + returnResponse(true); + } else { + returnResponse(false); + } + } } uint32_t AVOutputTV::setColorTemperature(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_colorTempStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + std::string value; + tvColorTemp_t colortemp = tvColorTemp_MAX; + tvError_t ret = tvERROR_NONE; + + value = parameters.HasLabel("colorTemperature") ? parameters["colorTemperature"].String() : ""; + returnIfParamNotFound(parameters,"colorTemperature"); + if(!value.compare("Standard")) { + colortemp = tvColorTemp_STANDARD; + } + else if (!value.compare("Warm")) { + colortemp = tvColorTemp_WARM; + } + else if (!value.compare("Cold")) { + colortemp = tvColorTemp_COLD; + } + else if (!value.compare("UserDefined")) { + colortemp = tvColorTemp_USER; + } + else { + returnResponse(false); + } - capDetails_t inputInfo; - std::string value; - tvColorTemp_t colortemp = tvColorTemp_MAX; - tvError_t ret = tvERROR_NONE; - - value = parameters.HasLabel("colorTemperature") ? parameters["colorTemperature"].String() : ""; - returnIfParamNotFound(parameters,"colorTemperature"); - if(!value.compare("Standard")) { - colortemp = tvColorTemp_STANDARD; - } - else if (!value.compare("Warm")) { - colortemp = tvColorTemp_WARM; - } - else if (!value.compare("Cold")) { - colortemp = tvColorTemp_COLD; - } - else if (!value.compare("UserDefined")) { - colortemp = tvColorTemp_USER; - } - else { - returnResponse(false); - } - - if (parsingSetInputArgument(parameters, "ColorTemperature",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "ColorTemperature",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "ColorTemperature", inputInfo )) { - LOGERR("%s: CapablityCheck failed for colorTemperature\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "ColorTemperature", inputInfo )) { + LOGERR("%s: CapablityCheck failed for colorTemperature\n", __FUNCTION__); + returnResponse(false); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - ret = SetColorTemperature((tvColorTemp_t)colortemp); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + ret = SetColorTemperature((tvColorTemp_t)colortemp); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set ColorTemperature\n"); - returnResponse(false); + if(ret != tvERROR_NONE) { + LOGERR("Failed to set ColorTemperature\n"); + returnResponse(false); + } + else { + int retval= updateAVoutputTVParam("set","ColorTemp", inputInfo,PQ_PARAM_COLOR_TEMPERATURE,(int)colortemp); + if(retval != 0 ) { + LOGERR("Failed to Save ColorTemperature to ssm_data\n"); + returnResponse(false); + } + LOGINFO("Exit : setColorTemperature successful to value: %d\n", colortemp); + returnResponse(true); + } } - else { - int retval= updateAVoutputTVParam("set","ColorTemp", inputInfo,PQ_PARAM_COLOR_TEMPERATURE,(int)colortemp); - if(retval != 0 ) { - LOGERR("Failed to Save ColorTemperature to ssm_data\n"); + else + { + bool success = setEnumPQParam( + parameters, + "colorTemperature", + "ColorTemp", + colorTempMap, + PQ_PARAM_COLOR_TEMPERATURE, + [](int val) { + return SetColorTemperature(static_cast(val)); + }); + + if (!success) { + LOGERR("setColorTemperature failed"); returnResponse(false); } - LOGINFO("Exit : setColorTemperature successful to value: %d\n", colortemp); + + LOGINFO("setColorTemperature: Success"); returnResponse(true); } } @@ -1906,53 +3474,68 @@ namespace Plugin { uint32_t AVOutputTV::resetColorTemperature(const JsonObject& parameters, JsonObject& response) { - LOGINFO("Entry\n"); - - capDetails_t inputInfo; - paramIndex_t indexInfo; - int colortemp=0; - tvError_t ret = tvERROR_NONE; + LOGINFO("Entry\n"); + if(m_colorTempStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int colortemp=0; + tvError_t ret = tvERROR_NONE; - if (parsingSetInputArgument(parameters, "ColorTemperature", inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "ColorTemperature", inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "ColorTemperature", inputInfo )) { - LOGERR("%s: CapablityCheck failed for colorTemperature\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "ColorTemperature", inputInfo )) { + LOGERR("%s: CapablityCheck failed for colorTemperature\n", __FUNCTION__); + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","ColorTemp", inputInfo,PQ_PARAM_COLOR_TEMPERATURE,colortemp); + int retval= updateAVoutputTVParam("reset","ColorTemp", inputInfo,PQ_PARAM_COLOR_TEMPERATURE,colortemp); - if(retval != 0 ) { - LOGERR("Failed to reset ColorTemperature\n"); - returnResponse(false); - } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("ColorTemperature",inputInfo,indexInfo); - int err = getLocalparam("ColorTemp",indexInfo, colortemp, PQ_PARAM_COLOR_TEMPERATURE); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex, colortemp); - ret = SetColorTemperature((tvColorTemp_t)colortemp); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + if(retval != 0 ) { + LOGERR("Failed to reset ColorTemperature\n"); + returnResponse(false); + } + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("ColorTemperature",inputInfo,indexInfo); + int err = getLocalparam("ColorTemp",indexInfo, colortemp, PQ_PARAM_COLOR_TEMPERATURE); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex, colortemp); + ret = SetColorTemperature((tvColorTemp_t)colortemp); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetColorTemperature Successful to value : %d \n",colortemp); + returnResponse(true); + } } - else { - LOGINFO("Exit : resetColorTemperature Successful to value : %d \n",colortemp); - returnResponse(true); + else + { + bool success = resetEnumPQParamToDefault( + parameters, + "ColorTemp", + PQ_PARAM_COLOR_TEMPERATURE, + colorTempReverseMap, + [](int val, const std::unordered_map&) { + return SetColorTemperature(static_cast(val)); + }); + + returnResponse(success); } } @@ -2007,161 +3590,229 @@ namespace Plugin { { LOGINFO("Entry"); - capDetails_t inputInfo; - paramIndex_t indexInfo; - int dimmingMode = 0; - - if (parsingGetInputArgument(parameters, "DimmingMode", inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } - - if (isPlatformSupport("DimmingMode") != 0) { - returnResponse(false); - } + if(m_dimmingModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int dimmingMode = 0; + if (parsingGetInputArgument(parameters, "DimmingMode", inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } - if (getParamIndex("DimmingMode",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("DimmingMode",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - int err = getLocalparam("DimmingMode",indexInfo,dimmingMode, PQ_PARAM_DIMMINGMODE); - if( err == 0 ) { - switch(dimmingMode) { - case tvDimmingMode_Fixed: - LOGINFO("DimmingMode Value: Fixed\n"); - response["DimmingMode"] = "fixed"; - break; + int err = getLocalparam("DimmingMode",indexInfo,dimmingMode, PQ_PARAM_DIMMINGMODE); + if( err == 0 ) { + switch(dimmingMode) { + case tvDimmingMode_Fixed: + LOGINFO("DimmingMode Value: Fixed\n"); + response["dimmingMode"] = "Fixed"; + break; - case tvDimmingMode_Local: - LOGINFO("DimmingMode Value: Local\n"); - response["DimmingMode"] = "local"; - break; + case tvDimmingMode_Local: + LOGINFO("DimmingMode Value: Local\n"); + response["dimmingMode"] = "Local"; + break; - case tvDimmingMode_Global: - LOGINFO("DimmingMode Value: Global\n"); - response["DimmingMode"] = "global"; - break; + case tvDimmingMode_Global: + LOGINFO("DimmingMode Value: Global\n"); + response["dimmingMode"] = "Global"; + break; + } + LOGINFO("Exit : DimmingMode Value: %d \n", dimmingMode); + returnResponse(true); + } + else { + returnResponse(false); } - LOGINFO("Exit : DimmingMode Value: %d \n", dimmingMode); - returnResponse(true); } - else { - returnResponse(false); + else + { + std::string mode; + if (getEnumPQParamString(parameters, "DimmingMode", + PQ_PARAM_DIMMINGMODE, dimmingModeReverseMap, mode)) { + response["dimmingMode"] = mode; + returnResponse(true); + } else { + returnResponse(false); + } } } uint32_t AVOutputTV::setBacklightDimmingMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_dimmingModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { - capDetails_t inputInfo; - int dimmingMode = 0; - tvError_t ret = tvERROR_NONE; - std::string value; + capDetails_t inputInfo; + int dimmingMode = 0; + tvError_t ret = tvERROR_NONE; + std::string value; - value = parameters.HasLabel("DimmingMode") ? parameters["DimmingMode"].String() : ""; - returnIfParamNotFound(parameters,"DimmingMode"); + value = parameters.HasLabel("dimmingMode") ? parameters["dimmingMode"].String() : ""; + returnIfParamNotFound(parameters,"dimmingMode"); - if (validateInputParameter("DimmingMode",value) != 0) { - LOGERR("%s: Range validation failed for DimmingMode\n", __FUNCTION__); - returnResponse(false); - } - dimmingMode = getDimmingModeIndex(value); + if (validateInputParameter("DimmingMode",value) != 0) { + LOGERR("%s: Range validation failed for DimmingMode\n", __FUNCTION__); + returnResponse(false); + } + dimmingMode = getDimmingModeIndex(value); - if (parsingSetInputArgument(parameters, "DimmingMode",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "DimmingMode",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if (isPlatformSupport("DimmingMode") != 0) { - returnResponse(false); - } + if( !isCapablityCheckPassed( "DimmingMode" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for DimmingMode\n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "DimmingMode" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for DimmingMode\n", __FUNCTION__); - returnResponse(false); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + ret = SetTVDimmingMode(value.c_str()); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - ret = SetTVDimmingMode(value.c_str()); - } + if(ret != tvERROR_NONE) { + LOGERR("Failed to set DimmingMode\n"); + returnResponse(false); + } + else { + int retval= updateAVoutputTVParam("set","DimmingMode",inputInfo,PQ_PARAM_DIMMINGMODE,(int)dimmingMode); + if(retval != 0 ) { + LOGERR("Failed to Save DimmingMode to ssm_data\n"); + returnResponse(false); + } - if(ret != tvERROR_NONE) { - LOGERR("Failed to set DimmingMode\n"); - returnResponse(false); + LOGINFO("Exit : setDimmingMode successful to value: %d\n", dimmingMode); + returnResponse(true); + } } - else { - int retval= updateAVoutputTVParam("set","DimmingMode",inputInfo,PQ_PARAM_DIMMINGMODE,(int)dimmingMode); - if(retval != 0 ) { - LOGERR("Failed to Save DimmingMode to ssm_data\n"); + else + { + int dimmingMode = 0; + tvError_t ret = tvERROR_NONE; + std::string value; + + value = parameters.HasLabel("dimmingMode") ? parameters["dimmingMode"].String() : ""; + returnIfParamNotFound(parameters,"dimmingMode"); + + dimmingMode = getDimmingModeIndex(value); + if (dimmingMode < 0 || dimmingMode > tvDimmingMode_MAX) { + LOGERR("Input value %d is out of range (0 - %d) for DimmingMode", dimmingMode, tvDimmingMode_MAX); returnResponse(false); } - - LOGINFO("Exit : setDimmingMode successful to value: %d\n", dimmingMode); - returnResponse(true); + if( isSetRequiredForParam(parameters, "DimmingMode" ) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + ret = SetTVDimmingMode(value.c_str()); + } + if(ret != tvERROR_NONE) { + LOGERR("Failed to set DimmingMode\n"); + returnResponse(false); + } + else + { + // Update the TV parameter + int retval = updateAVoutputTVParamV2("set", "DimmingMode", parameters, PQ_PARAM_DIMMINGMODE, (int)dimmingMode); + if (retval != 0) { + LOGERR("Failed to Save DimmingMode to ssm_data. retval: %d \n", retval); + returnResponse(false); + } + LOGINFO("Exit : setDimmingMode successful to value: %d \n", dimmingMode); + returnResponse(true); + } } } uint32_t AVOutputTV::resetBacklightDimmingMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_dimmingModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { - capDetails_t inputInfo; - paramIndex_t indexInfo; - std::string dimmingMode; - int dMode=0; - tvError_t ret = tvERROR_NONE; + capDetails_t inputInfo; + paramIndex_t indexInfo; + std::string dimmingMode; + int dMode=0; + tvError_t ret = tvERROR_NONE; - if (parsingSetInputArgument(parameters, "DimmingMode", inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "DimmingMode", inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "DimmingMode" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for DimmingMode\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "DimmingMode" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for DimmingMode\n", __FUNCTION__); + returnResponse(false); + } - if (isPlatformSupport("DimmingMode") != 0) { - returnResponse(false); - } + if (isPlatformSupport("DimmingMode") != 0) { + returnResponse(false); + } - int retval= updateAVoutputTVParam("reset","DimmingMode", inputInfo,PQ_PARAM_DIMMINGMODE,dMode); + int retval= updateAVoutputTVParam("reset","DimmingMode", inputInfo,PQ_PARAM_DIMMINGMODE,dMode); - if(retval != 0 ) { - LOGERR("Failed to reset ldim\n"); - returnResponse(false); - } + if(retval != 0 ) { + LOGERR("Failed to reset ldim\n"); + returnResponse(false); + } - else { - if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { - inputInfo.pqmode = "Current"; - inputInfo.source = "Current"; - inputInfo.format = "Current"; - getParamIndex("DimmingMode",inputInfo,indexInfo); - int err = getLocalparam("DimmingMode",indexInfo, dMode, PQ_PARAM_DIMMINGMODE); - if( err == 0 ) { - LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex, dMode); - getDimmingModeStringFromEnum(dMode,dimmingMode); - ret = SetTVDimmingMode(dimmingMode.c_str()); - } - else { - LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); - ret = tvERROR_GENERAL; + else { + if (isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format)) { + inputInfo.pqmode = "Current"; + inputInfo.source = "Current"; + inputInfo.format = "Current"; + getParamIndex("DimmingMode",inputInfo,indexInfo); + int err = getLocalparam("DimmingMode",indexInfo, dMode, PQ_PARAM_DIMMINGMODE); + if( err == 0 ) { + LOGINFO("%s : getLocalparam success format :%d source : %d format : %d value : %d\n",__FUNCTION__,indexInfo.formatIndex, indexInfo.sourceIndex, indexInfo.pqmodeIndex, dMode); + getDimmingModeStringFromEnum(dMode,dimmingMode); + ret = SetTVDimmingMode(dimmingMode.c_str()); + } + else { + LOGERR("%s : GetLocalParam Failed \n",__FUNCTION__); + ret = tvERROR_GENERAL; + } } } - } - if(ret != tvERROR_NONE) { - returnResponse(false); + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + LOGINFO("Exit : resetBacklightDimmingMode Successful to value : %s \n",dimmingMode.c_str()); + returnResponse(true); + } } - else { - LOGINFO("Exit : resetBacklightDimmingMode Successful to value : %s \n",dimmingMode.c_str()); - returnResponse(true); + else + { + bool success = resetEnumPQParamToDefault( + parameters, + "DimmingMode", + PQ_PARAM_DIMMINGMODE, + dimmingModeReverseMap, + [](int val, const std::unordered_map& enumMap) -> tvError_t { + auto it = enumMap.find(val); + if (it != enumMap.end()) { + return SetTVDimmingMode(it->second.c_str()); + } else { + LOGERR("Invalid enum value: %d for DimmingMode\n", val); + return tvERROR_GENERAL; + } + }); + + returnResponse(success); + } } @@ -2574,199 +4225,529 @@ namespace Plugin { } } + bool AVOutputTV::getPictureModeV2(const JsonObject& parameters, std::string& outMode) + { + LOGINFO("Entry"); + + tvVideoSrcType_t source = VIDEO_SOURCE_IP; + tvVideoFormatType_t format = VIDEO_FORMAT_SDR; + + // Parse videoSource + if (!parameters.HasLabel("videoSource") || parameters["videoSource"].String() == "Current") { + GetCurrentVideoSource(&source); + } else { + std::string srcStr = parameters["videoSource"].String(); + if (videoSrcReverseMap.count(srcStr)) { + source = static_cast(videoSrcReverseMap.at(srcStr)); + } else { + LOGERR("Invalid videoSource: %s", srcStr.c_str()); + return false; + } + } + + // Parse videoFormat + if (!parameters.HasLabel("videoFormat") || parameters["videoFormat"].String() == "Current") { + GetCurrentVideoFormat(&format); + if (format == VIDEO_FORMAT_NONE) format = VIDEO_FORMAT_SDR; + } else { + std::string fmtStr = parameters["videoFormat"].String(); + if (videoFormatReverseMap.count(fmtStr)) { + format = static_cast(videoFormatReverseMap.at(fmtStr)); + } else { + LOGERR("Invalid videoFormat: %s", fmtStr.c_str()); + return false; + } + } + + // Directly use TR-181 to fetch active picture mode + std::string tr181_param_name = std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM) + + "." + convertSourceIndexToStringV2(source) + + ".Format." + convertVideoFormatToStringV2(format) + + ".PictureModeString"; + + LOGINFO("TR181 Param Name = %s", tr181_param_name.c_str()); + + TR181_ParamData_t param = {0}; + tr181ErrorCode_t err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); + if (err != tr181Success) { + LOGERR("getLocalParam failed: %d", err); + return false; + } + + outMode = param.value; + LOGINFO("Exit: PictureMode = %s", outMode.c_str()); + return true; + } + uint32_t AVOutputTV::getPictureMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - capDetails_t inputInfo; - paramIndex_t indexInfo; - std::string tr181_param_name; - TR181_ParamData_t param = {0}; - tr181ErrorCode_t err = tr181Success; + std::string pictureModeStr; + if (m_pictureModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + TR181_ParamData_t param = {0}; - if (parsingGetInputArgument(parameters, "PictureMode",inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); + if (parsingGetInputArgument(parameters, "PictureMode", inputInfo) != 0) { + LOGERR("%s: Failed to parse input argument", __FUNCTION__); + returnResponse(false); + } + + if (getParamIndex("PictureMode", inputInfo, indexInfo) == -1) { + LOGERR("%s: getParamIndex failed", __FUNCTION__); + returnResponse(false); + } + + std::string tr181_param_name = std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM) + + "." + convertSourceIndexToString(indexInfo.sourceIndex) + + ".Format." + convertVideoFormatToString(indexInfo.formatIndex) + + ".PictureModeString"; + + tr181ErrorCode_t err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); + if (err != tr181Success) { + returnResponse(false); + } + + pictureModeStr = param.value; + } + else + { + if (!getPictureModeV2(parameters, pictureModeStr)) { + returnResponse(false); + } + } + response["pictureMode"] = pictureModeStr; + LOGINFO("Exit: getPictureMode() : %s", pictureModeStr.c_str()); + returnResponse(true); + } + + bool AVOutputTV::setPictureModeV2(const JsonObject& parameters) + { + LOGINFO("Entry %s", __FUNCTION__); + + if (!parameters.HasLabel("pictureMode")) { + LOGERR("Missing 'pictureMode' in parameters."); + return false; } - if (getParamIndex("PictureMode",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); + std::string mode = parameters["pictureMode"].String(); + + // Validate against m_pictureModes + int modeIndex = -1; + for (size_t i = 0; i < m_numPictureModes; ++i) { + auto it = pqModeMap.find(m_pictureModes[i]); + if (it != pqModeMap.end()) { + if (it->second == mode) { + modeIndex = static_cast(i); + LOGINFO("Matched pictureMode '%s' at index %d", mode.c_str(), modeIndex); + break; + } + } else { + LOGERR("pqModeMap does not contain m_pictureModes[%zu] = %d", i, m_pictureModes[i]); + } + } + + if (modeIndex == -1) { + LOGERR("Invalid pictureMode: %s", mode.c_str()); + return false; + } + + // Extract videoSource + std::vector sources; + if (parameters.HasLabel("videoSource")) { + const JsonArray& sourceParam = parameters["videoSource"].Array(); + for (uint32_t i = 0; i < sourceParam.Length(); ++i) { + std::string source = sourceParam[i].Value(); + if (!source.empty()) { + sources.push_back(source); + } + } + } else { + sources.push_back("Global"); + LOGINFO("videoSource not provided, defaulting to 'Global'"); + } + + // Extract videoFormat + std::vector formats; + if (parameters.HasLabel("videoFormat")) { + const JsonArray& formatParam = parameters["videoFormat"].Array(); + for (uint32_t i = 0; i < formatParam.Length(); ++i) { + std::string format = formatParam[i].Value(); + if (!format.empty()) { + formats.push_back(format); + } + } + } else { + formats.push_back("Global"); + LOGINFO("videoFormat not provided, defaulting to 'Global'"); + } + + // Expand 'Global' sources + if (std::find(sources.begin(), sources.end(), "Global") != sources.end()) { + std::unordered_set sourceSet; + for (size_t j = 0; j < m_pictureModeCaps->num_contexts; ++j) { + if (m_pictureModeCaps->contexts[j].pq_mode == m_pictureModes[modeIndex]) { + std::string srcStr = convertSourceIndexToStringV2(m_pictureModeCaps->contexts[j].videoSrcType); + sourceSet.insert(srcStr); + } + } + sources.insert(sources.end(), sourceSet.begin(), sourceSet.end()); } - tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - tr181_param_name += "." + convertSourceIndexToString(indexInfo.sourceIndex) + "." + "Format."+convertVideoFormatToString(indexInfo.formatIndex)+"."+"PictureModeString"; - err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); + // Expand 'Global' formats + if (std::find(formats.begin(), formats.end(), "Global") != formats.end()) { + std::unordered_set formatSet; + for (size_t j = 0; j < m_pictureModeCaps->num_contexts; ++j) { + if (m_pictureModeCaps->contexts[j].pq_mode == m_pictureModes[modeIndex]) { + std::string fmtStr = convertVideoFormatToStringV2(m_pictureModeCaps->contexts[j].videoFormatType); + formatSet.insert(fmtStr); + } + } + formats.insert(formats.end(), formatSet.begin(), formatSet.end()); + } + + // Get current context + tvVideoSrcType_t currentSrc = VIDEO_SOURCE_IP; + tvVideoFormatType_t currentFmt = VIDEO_FORMAT_SDR; + GetCurrentVideoSource(¤tSrc); + GetCurrentVideoFormat(¤tFmt); + if (currentFmt == VIDEO_FORMAT_NONE) + currentFmt = VIDEO_FORMAT_SDR; + + LOGINFO("Current video source: %s, format: %s", + convertSourceIndexToStringV2(currentSrc).c_str(), + convertVideoFormatToStringV2(currentFmt).c_str()); + + bool contextHandled = false; + + // Iterate through contexts and apply mode + for (size_t i = 0; i < m_pictureModeCaps->num_contexts; ++i) { + const tvConfigContext_t& ctx = m_pictureModeCaps->contexts[i]; + + if (ctx.pq_mode != m_pictureModes[modeIndex]) + continue; + + if (!isValidFormat(formats, ctx.videoFormatType)) + continue; + + if (!isValidSource(sources, ctx.videoSrcType)) + continue; + + std::string srcStr = convertSourceIndexToStringV2(ctx.videoSrcType); + std::string fmtStr = convertVideoFormatToStringV2(ctx.videoFormatType); + + if (ctx.videoSrcType == currentSrc && ctx.videoFormatType == currentFmt) { + if (SetTVPictureMode(mode.c_str()) != tvERROR_NONE) { + LOGERR("SetTVPictureMode failed for mode: %s", mode.c_str()); + continue; + } + } +//TODO:: Revisit this logic. Have to revert if HAL call fails. + std::string tr181Param = std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM) + "." + + srcStr + ".Format." + fmtStr + ".PictureModeString"; + + tr181ErrorCode_t err = setLocalParam(rfc_caller_id, tr181Param.c_str(), mode.c_str()); + if (err != tr181Success) { + LOGERR("setLocalParam failed: %s => %s", tr181Param.c_str(), getTR181ErrorString(err)); + continue; + } + else { + LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM, mode.c_str()); + int pqmodeindex = (int)getPictureModeIndex(mode); + SaveSourcePictureMode(ctx.videoSrcType, ctx.videoFormatType, pqmodeindex); + } - if ( tr181Success != err ) { - returnResponse(false); + contextHandled = true; } - else { - std::string s; - s+=param.value; - response["pictureMode"] = s; - LOGINFO("Exit : getPictureMode() : %s\n",s.c_str()); - returnResponse(true); + + if (!contextHandled) { + LOGERR("No valid context found to apply pictureMode: %s", mode.c_str()); + return false; } + + LOGINFO("Exit %s: PictureMode '%s' applied successfully.", __FUNCTION__, mode.c_str()); + return true; } + uint32_t AVOutputTV::setPictureMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - capDetails_t inputInfo; - char prevmode[PIC_MODE_NAME_MAX]={0}; - std::string value; - GetTVPictureMode(prevmode); + if (m_pictureModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + char prevmode[PIC_MODE_NAME_MAX]={0}; + std::string value; + GetTVPictureMode(prevmode); + + tvError_t ret = tvERROR_NONE; + value = parameters.HasLabel("pictureMode") ? parameters["pictureMode"].String() : ""; + returnIfParamNotFound(parameters,"pictureMode"); + + // As only source need to validate, so pqmode and formate passing as currrent + if (parsingSetInputArgument(parameters, "PictureMode",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - tvError_t ret = tvERROR_NONE; - value = parameters.HasLabel("pictureMode") ? parameters["pictureMode"].String() : ""; - returnIfParamNotFound(parameters,"pictureMode"); + if (validateInputParameter("PictureMode",value) != 0) { + LOGERR("%s: Range validation failed for PictureMode\n", __FUNCTION__); + returnResponse(false); + } + if( !isCapablityCheckPassed( "PictureMode" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for PictureMode\n", __FUNCTION__); + returnResponse(false); + } - // As only source need to validate, so pqmode and formate passing as currrent - if (parsingSetInputArgument(parameters, "PictureMode",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if( isSetRequired("Current",inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with SetTVPictureMode\n"); + ret = SetTVPictureMode(value.c_str()); + } + if(ret != tvERROR_NONE) { + returnResponse(false); + } + else { + valueVectors_t values; + inputInfo.pqmode = "Current"; - if (validateInputParameter("PictureMode",value) != 0) { - LOGERR("%s: Range validation failed for PictureMode\n", __FUNCTION__); - returnResponse(false); - } - if( !isCapablityCheckPassed( "PictureMode" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for PictureMode\n", __FUNCTION__); - returnResponse(false); - } + getSaveConfig("PictureMode" ,inputInfo, values); + + for (int sourceType : values.sourceValues) { + tvVideoSrcType_t source = (tvVideoSrcType_t)sourceType; + for (int formatType : values.formatValues) { + tvVideoFormatType_t format = (tvVideoFormatType_t)formatType; + std::string tr181_param_name = ""; + tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); + // framing Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.AVOutput.Source.source_index[x].Format.format_index[x].PictureModeString.value + tr181_param_name += "."+convertSourceIndexToString(source)+"."+"Format."+ + convertVideoFormatToString(format)+"."+"PictureModeString"; + tr181ErrorCode_t err = setLocalParam(rfc_caller_id, tr181_param_name.c_str(), value.c_str()); + if ( err != tr181Success ) { + LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM, getTR181ErrorString(err)); + returnResponse(false); + } + else { + LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM, value.c_str()); + int pqmodeindex = (int)getPictureModeIndex(value); + SaveSourcePictureMode(source, format, pqmodeindex); + } + } + } - if( isSetRequired("Current",inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with SetTVPictureMode\n"); - ret = SetTVPictureMode(value.c_str()); - } - if(ret != tvERROR_NONE) { - returnResponse(false); + //Filmmaker mode telemetry + if(!strncmp(value.c_str(),"filmmaker",strlen(value.c_str())) && strncmp(prevmode,"filmmaker",strlen(prevmode))) { + LOGINFO("%s mode has been enabled",value.c_str()); + } + else if(!strncmp(prevmode,"filmmaker",strlen(prevmode)) && strncmp(value.c_str(),"filmmaker",strlen(value.c_str()))) { + LOGINFO("%s mode has been disabled",prevmode); + } + + LOGINFO("Broadcasting the low latency change event \n"); + + if(m_isDalsEnabled) { + //GameModebroadcast + if(!strncmp(value.c_str(),"game",strlen(value.c_str())) && strncmp(prevmode,"game",strlen(prevmode))) { + broadcastLowLatencyModeChangeEvent(1); + } + else if(!strncmp(prevmode,"game",strlen(prevmode)) && strncmp(value.c_str(),"game",strlen(value.c_str()))) { + broadcastLowLatencyModeChangeEvent(0); + } + } + + LOGINFO("Exit : Value : %s \n",value.c_str()); + returnResponse(true); + } } else { - valueVectors_t values; - inputInfo.pqmode = "Current"; + bool success = false; + try { + success = setPictureModeV2(parameters); + } catch (const std::exception& e) { + LOGERR("Exception in setPictureModeV2: %s", e.what()); + } catch (...) { + LOGERR("Unknown exception in setPictureModeV2"); + } + returnResponse(success); + } + } + bool AVOutputTV::resetPictureModeV2(const JsonObject& parameters) + { + LOGINFO("Entry %s\n", __FUNCTION__); + + auto extractList = [](const JsonObject& params, const std::string& key) -> std::vector { + std::vector result; + if (params.HasLabel(key.c_str())) { + const JsonArray& array = params[key.c_str()].Array(); + for (uint32_t i = 0; i < array.Length(); ++i) { + result.push_back(array[i].Value()); + } + } else { + result.push_back("Global"); + } + return result; + }; - getSaveConfig("PictureMode" ,inputInfo, values); + std::vector sources = extractList(parameters, "videoSource"); + std::vector formats = extractList(parameters, "videoFormat"); - for (int sourceType : values.sourceValues) { - tvVideoSrcType_t source = (tvVideoSrcType_t)sourceType; - for (int formatType : values.formatValues) { - tvVideoFormatType_t format = (tvVideoFormatType_t)formatType; - std::string tr181_param_name = ""; - tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - // framing Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.AVOutput.Source.source_index[x].Format.format_index[x].PictureModeString.value - tr181_param_name += "."+convertSourceIndexToString(source)+"."+"Format."+ - convertVideoFormatToString(format)+"."+"PictureModeString"; - tr181ErrorCode_t err = setLocalParam(rfc_caller_id, tr181_param_name.c_str(), value.c_str()); - if ( err != tr181Success ) { - LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM, getTR181ErrorString(err)); - returnResponse(false); - } - else { - LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM, value.c_str()); - int pqmodeindex = (int)getPictureModeIndex(value); - SaveSourcePictureMode(source, format, pqmodeindex); - } - } + auto expandGlobal = [](std::vector& vec, const std::unordered_set& fullSet) { + if (std::find(vec.begin(), vec.end(), "Global") != vec.end()) { + vec.erase(std::remove(vec.begin(), vec.end(), "Global"), vec.end()); + vec.insert(vec.end(), fullSet.begin(), fullSet.end()); + } + std::unordered_set unique(vec.begin(), vec.end()); + vec.assign(unique.begin(), unique.end()); + }; + + // Expand "Global" values + std::unordered_set allSources, allFormats; + for (size_t j = 0; j < m_pictureModeCaps->num_contexts; ++j) { + allSources.insert(convertSourceIndexToStringV2(m_pictureModeCaps->contexts[j].videoSrcType)); + allFormats.insert(convertVideoFormatToStringV2(m_pictureModeCaps->contexts[j].videoFormatType)); + } + expandGlobal(sources, allSources); + expandGlobal(formats, allFormats); + + // Get current source & format + tvVideoSrcType_t currentSrc = VIDEO_SOURCE_IP; + tvVideoFormatType_t currentFmt = VIDEO_FORMAT_SDR; + GetCurrentVideoSource(¤tSrc); + GetCurrentVideoFormat(¤tFmt); + if (currentFmt == VIDEO_FORMAT_NONE) + currentFmt = VIDEO_FORMAT_SDR; + + bool contextHandled = false; + + for (size_t i = 0; i < m_pictureModeCaps->num_contexts; ++i) { + const tvConfigContext_t& ctx = m_pictureModeCaps->contexts[i]; + + if (!isValidSource(sources, ctx.videoSrcType) || !isValidFormat(formats, ctx.videoFormatType)) + continue; + + std::string tr181Param = std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM) + "." + + convertSourceIndexToStringV2(ctx.videoSrcType) + ".Format." + + convertVideoFormatToStringV2(ctx.videoFormatType) + ".PictureModeString"; + + // Clear override + tr181ErrorCode_t err = clearLocalParam(rfc_caller_id, tr181Param.c_str()); + if (err != tr181Success) { + LOGERR("clearLocalParam failed for %s: %s", tr181Param.c_str(), getTR181ErrorString(err)); + continue; } - //Filmmaker mode telemetry - if(!strncmp(value.c_str(),"filmmaker",strlen(value.c_str())) && strncmp(prevmode,"filmmaker",strlen(prevmode))) { - LOGINFO("%s mode has been enabled",value.c_str()); - } - else if(!strncmp(prevmode,"filmmaker",strlen(prevmode)) && strncmp(value.c_str(),"filmmaker",strlen(value.c_str()))) { - LOGINFO("%s mode has been disabled",prevmode); - } + // Read saved TR-181 value + TR181_ParamData_t param = {0}; + err = getLocalParam(rfc_caller_id, tr181Param.c_str(), ¶m); + if (err != tr181Success || strlen(param.value) == 0) { + LOGWARN("getLocalParam failed or empty for %s", tr181Param.c_str()); + continue; + } - LOGINFO("Broadcasting the low latency change event \n"); + // Apply to hardware if current context matches + if (ctx.videoSrcType == currentSrc && ctx.videoFormatType == currentFmt) { - if(m_isDalsEnabled) { - //GameModebroadcast - if(!strncmp(value.c_str(),"game",strlen(value.c_str())) && strncmp(prevmode,"game",strlen(prevmode))) { - broadcastLowLatencyModeChangeEvent(1); - } - else if(!strncmp(prevmode,"game",strlen(prevmode)) && strncmp(value.c_str(),"game",strlen(value.c_str()))) { - broadcastLowLatencyModeChangeEvent(0); - } + tvError_t ret = SetTVPictureMode(param.value); + if (ret != tvERROR_NONE) { + LOGERR("SetTVPictureMode failed for %s", param.value); + continue; + } } - LOGINFO("Exit : Value : %s \n",value.c_str()); - returnResponse(true); + // Save to internal config + int pqmodeIndex = static_cast(getPictureModeIndex(param.value)); + SaveSourcePictureMode(ctx.videoSrcType, ctx.videoFormatType, pqmodeIndex); + contextHandled = true; + } + + if (!contextHandled) { + LOGERR("No valid pictureMode context matched to reset.\n"); + return false; } + + LOGINFO("resetPictureModeV2: Exit - PictureMode reset successfully.\n"); + return true; } uint32_t AVOutputTV::resetPictureMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - tr181ErrorCode_t err = tr181Success; - TR181_ParamData_t param = {0}; + if (m_pictureModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + tr181ErrorCode_t err = tr181Success; + TR181_ParamData_t param = {0}; - valueVectors_t values; - capDetails_t inputInfo; + valueVectors_t values; + capDetails_t inputInfo; - // As only source need to validate, so pqmode and formate passing as currrent - if (parsingSetInputArgument(parameters, "PictureMode",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + // As only source need to validate, so pqmode and formate passing as currrent + if (parsingSetInputArgument(parameters, "PictureMode",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "PictureMode",inputInfo )) { - LOGERR("%s: CapablityCheck failed for PictureMode\n", __FUNCTION__); - returnResponse(false); - } - inputInfo.pqmode = "Current"; - getSaveConfig("PictureMode", inputInfo, values); + if( !isCapablityCheckPassed( "PictureMode",inputInfo )) { + LOGERR("%s: CapablityCheck failed for PictureMode\n", __FUNCTION__); + returnResponse(false); + } + inputInfo.pqmode = "Current"; + getSaveConfig("PictureMode", inputInfo, values); - for (int source : values.sourceValues) { - tvVideoSrcType_t sourceType = (tvVideoSrcType_t)source; - for (int format : values.formatValues) { - tvVideoFormatType_t formatType = (tvVideoFormatType_t)format; - std::string tr181_param_name = ""; - tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - tr181_param_name += "."+convertSourceIndexToString(sourceType)+"."+"Format."+ - convertVideoFormatToString(formatType)+"."+"PictureModeString"; + for (int source : values.sourceValues) { + tvVideoSrcType_t sourceType = (tvVideoSrcType_t)source; + for (int format : values.formatValues) { + tvVideoFormatType_t formatType = (tvVideoFormatType_t)format; + std::string tr181_param_name = ""; + tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); + tr181_param_name += "."+convertSourceIndexToString(sourceType)+"."+"Format."+ + convertVideoFormatToString(formatType)+"."+"PictureModeString"; - err = clearLocalParam(rfc_caller_id, tr181_param_name.c_str()); - if ( err != tr181Success ) { - LOGWARN("clearLocalParam for %s Failed : %s\n", tr181_param_name.c_str(), getTR181ErrorString(err)); - returnResponse(false); - } - else { - err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); - if ( tr181Success == err ) { - //get curren source and if matches save for that alone - tvVideoSrcType_t current_source = VIDEO_SOURCE_IP; - GetCurrentVideoSource(¤t_source); - - tvVideoFormatType_t current_format = VIDEO_FORMAT_NONE; - GetCurrentVideoFormat(¤t_format); - if( current_format == VIDEO_FORMAT_NONE) { - current_format = VIDEO_FORMAT_SDR; - } + err = clearLocalParam(rfc_caller_id, tr181_param_name.c_str()); + if ( err != tr181Success ) { + LOGWARN("clearLocalParam for %s Failed : %s\n", tr181_param_name.c_str(), getTR181ErrorString(err)); + returnResponse(false); + } + else { + err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); + if ( tr181Success == err ) { + //get curren source and if matches save for that alone + tvVideoSrcType_t current_source = VIDEO_SOURCE_IP; + GetCurrentVideoSource(¤t_source); + + tvVideoFormatType_t current_format = VIDEO_FORMAT_NONE; + GetCurrentVideoFormat(¤t_format); + if( current_format == VIDEO_FORMAT_NONE) { + current_format = VIDEO_FORMAT_SDR; + } - if (current_source == sourceType && current_format == formatType) { + if (current_source == sourceType && current_format == formatType) { - tvError_t ret = SetTVPictureMode(param.value); - if(ret != tvERROR_NONE) { - LOGWARN("Picture Mode set failed: %s\n",getErrorString(ret).c_str()); - returnResponse(false); - } - else { - LOGINFO("Exit : Picture Mode reset successfully, value: %s\n", param.value); + tvError_t ret = SetTVPictureMode(param.value); + if(ret != tvERROR_NONE) { + LOGWARN("Picture Mode set failed: %s\n",getErrorString(ret).c_str()); + returnResponse(false); + } + else { + LOGINFO("Exit : Picture Mode reset successfully, value: %s\n", param.value); + } } + int pqmodeindex = (int)getPictureModeIndex(param.value); + SaveSourcePictureMode(sourceType, formatType, pqmodeindex); + } + else { + LOGWARN("getLocalParam for %s failed\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); + returnResponse(false); } - int pqmodeindex = (int)getPictureModeIndex(param.value); - SaveSourcePictureMode(sourceType, formatType, pqmodeindex); - } - else { - LOGWARN("getLocalParam for %s failed\n", AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - returnResponse(false); } } } + returnResponse(true); + } + else + { + bool success = resetPictureModeV2(parameters); + returnResponse(success); } - returnResponse(true) } uint32_t AVOutputTV::signalFilmMakerMode(const JsonObject& parameters, JsonObject& response) @@ -2793,87 +4774,148 @@ namespace Plugin { uint32_t AVOutputTV::setLowLatencyState(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_lowLatencyStateStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + std::string value; + capDetails_t inputInfo; + int lowLatencyIndex = 0,prevLowLatencyIndex = 0; + tvError_t ret = tvERROR_NONE; - std::string value; - capDetails_t inputInfo; - int lowLatencyIndex = 0,prevLowLatencyIndex = 0; - tvError_t ret = tvERROR_NONE; + ret = GetLowLatencyState(&prevLowLatencyIndex); + if(ret != tvERROR_NONE) { + LOGERR("Get previous low latency state failed\n"); + returnResponse(false); + } - ret = GetLowLatencyState(&prevLowLatencyIndex); - if(ret != tvERROR_NONE) { - LOGERR("Get previous low latency state failed\n"); - returnResponse(false); - } + value = parameters.HasLabel("LowLatencyState") ? parameters["LowLatencyState"].String() : ""; + returnIfParamNotFound(parameters,"LowLatencyState"); + lowLatencyIndex = std::stoi(value); - value = parameters.HasLabel("LowLatencyState") ? parameters["LowLatencyState"].String() : ""; - returnIfParamNotFound(parameters,"LowLatencyState"); - lowLatencyIndex = std::stoi(value); + if (validateIntegerInputParameter("LowLatencyState",lowLatencyIndex) != 0) { + LOGERR("Failed in Brightness range validation:%s", __FUNCTION__); + returnResponse(false); + } - if (validateIntegerInputParameter("LowLatencyState",lowLatencyIndex) != 0) { - LOGERR("Failed in Brightness range validation:%s", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters, "LowLatencyState",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters, "LowLatencyState",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "LowLatencyState" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for LowLatencyState\n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "LowLatencyState" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for LowLatencyState\n", __FUNCTION__); - returnResponse(false); - } + int retval= updateAVoutputTVParam("set","LowLatencyState",inputInfo,PQ_PARAM_LOWLATENCY_STATE,lowLatencyIndex); + if(retval != 0 ) { + LOGERR("Failed to SaveLowLatency to ssm_data\n"); + returnResponse(false); + } else { - int retval= updateAVoutputTVParam("set","LowLatencyState",inputInfo,PQ_PARAM_LOWLATENCY_STATE,lowLatencyIndex); - if(retval != 0 ) { - LOGERR("Failed to SaveLowLatency to ssm_data\n"); - returnResponse(false); - } else { + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with setLowLatencyState\n"); + ret = SetLowLatencyState( lowLatencyIndex ); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with setLowLatencyState\n"); - ret = SetLowLatencyState( lowLatencyIndex ); + if(ret != tvERROR_NONE) { + LOGERR("Failed to set low latency. Fallback to previous state %d\n", prevLowLatencyIndex); + retval=updateAVoutputTVParam("set","LowLatencyState",inputInfo,PQ_PARAM_LOWLATENCY_STATE,prevLowLatencyIndex); + if(retval != 0 ){ + LOGERR("Fallback to previous low latency state %d failed.\n", prevLowLatencyIndex); + } + returnResponse(false); + } + + LOGINFO("Exit : setLowLatency successful to value: %d\n", lowLatencyIndex); + returnResponse(true); } + } + else + { + std::string value; + int lowLatencyIndex = 0,prevLowLatencyIndex = 0; + tvError_t ret = tvERROR_NONE; + ret = GetLowLatencyState(&prevLowLatencyIndex); if(ret != tvERROR_NONE) { - LOGERR("Failed to set low latency. Fallback to previous state %d\n", prevLowLatencyIndex); - retval=updateAVoutputTVParam("set","LowLatencyState",inputInfo,PQ_PARAM_LOWLATENCY_STATE,prevLowLatencyIndex); - if(retval != 0 ){ - LOGERR("Fallback to previous low latency state %d failed.\n", prevLowLatencyIndex); - } + LOGERR("Get previous low latency state failed\n"); returnResponse(false); } - LOGINFO("Exit : setLowLatency successful to value: %d\n", lowLatencyIndex); - returnResponse(true); + value = parameters.HasLabel("LowLatencyState") ? parameters["LowLatencyState"].String() : ""; + returnIfParamNotFound(parameters,"LowLatencyState"); + lowLatencyIndex = std::stoi(value); + if (lowLatencyIndex < 0 || lowLatencyIndex > m_maxlowLatencyState) { + LOGERR("Input value %d is out of range (0 - %d) for LowLatencyState", lowLatencyIndex, m_maxlowLatencyState); + returnResponse(false); + } + + int retval= updateAVoutputTVParamV2("set","LowLatencyState",parameters,PQ_PARAM_LOWLATENCY_STATE,lowLatencyIndex); + if(retval != 0 ) { + LOGERR("Failed to SaveLowLatency to ssm_data\n"); + returnResponse(false); + } + else + { + if(isSetRequiredForParam(parameters, "LowLatencyState")) + { + LOGINFO("Proceed with setLowLatencyState\n"); + ret = SetLowLatencyState( lowLatencyIndex ); + } + if(ret != tvERROR_NONE) { + LOGERR("Failed to set low latency. Fallback to previous state %d\n", prevLowLatencyIndex); + retval=updateAVoutputTVParamV2("set","LowLatencyState",parameters,PQ_PARAM_LOWLATENCY_STATE, prevLowLatencyIndex); + if(retval != 0 ){ + LOGERR("Fallback to previous low latency state %d failed.\n", prevLowLatencyIndex); + } + returnResponse(false); + } + + LOGINFO("Exit : setLowLatency successful to value: %d\n", lowLatencyIndex); + returnResponse(true); + } } } uint32_t AVOutputTV::getLowLatencyState(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_lowLatencyStateStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int lowlatencystate = 0; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int lowlatencystate = 0; - - if (parsingGetInputArgument(parameters, "LowLatencyState",inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } - if (getParamIndex("LowLatencyState",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); - } + if (parsingGetInputArgument(parameters, "LowLatencyState",inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } + if (getParamIndex("LowLatencyState",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - int err = getLocalparam("LowLatencyState", indexInfo ,lowlatencystate, PQ_PARAM_LOWLATENCY_STATE); - if( err == 0 ) { - response["lowLatencyState"] = std::to_string(lowlatencystate); - LOGINFO("Exit : LowLatencyState Value: %d \n", lowlatencystate); - returnResponse(true); + int err = getLocalparam("LowLatencyState", indexInfo ,lowlatencystate, PQ_PARAM_LOWLATENCY_STATE); + if( err == 0 ) { + response["lowLatencyState"] = std::to_string(lowlatencystate); + LOGINFO("Exit : LowLatencyState Value: %d \n", lowlatencystate); + returnResponse(true); + } + else { + returnResponse(false); + } } - else { - returnResponse(false); + else + { + int lowlatencystate = 0; + if (getPQParamFromContext(parameters, "LowLatencyState", PQ_PARAM_LOWLATENCY_STATE, lowlatencystate)) { + response["lowLatencyState"] = std::to_string(lowlatencystate); + LOGINFO("Exit : LowLatencyState Value: %d", lowlatencystate); + returnResponse(true); + } else { + LOGERR("Failed to get LowLatencyState"); + returnResponse(false); + } } } @@ -2977,245 +5019,380 @@ namespace Plugin { uint32_t AVOutputTV::getCMS(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); + if(m_cmsStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + paramIndex_t indexInfo; + int level = 0; + tvPQParameterIndex_t tvPQEnum; - capDetails_t inputInfo; - paramIndex_t indexInfo; - int level = 0; - tvPQParameterIndex_t tvPQEnum; + inputInfo.color = parameters.HasLabel("color") ? parameters["color"].String() : ""; + inputInfo.component = parameters.HasLabel("component") ? parameters["component"].String() : ""; - inputInfo.color = parameters.HasLabel("color") ? parameters["color"].String() : ""; - inputInfo.component = parameters.HasLabel("component") ? parameters["component"].String() : ""; - - if( inputInfo.color.empty() || inputInfo.component.empty() ) { - LOGERR("%s : Color/Component param not found!!!\n",__FUNCTION__); - returnResponse(false); - } + if( inputInfo.color.empty() || inputInfo.component.empty() ) { + LOGERR("%s : Color/Component param not found!!!\n",__FUNCTION__); + returnResponse(false); + } - if (isPlatformSupport("CMS") != 0) { - returnResponse(false); - } + if (isPlatformSupport("CMS") != 0) { + returnResponse(false); + } - if (parsingGetInputArgument(parameters, "CMS", inputInfo) != 0) { - LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); - returnResponse(false); - } + if (parsingGetInputArgument(parameters, "CMS", inputInfo) != 0) { + LOGINFO("%s: Failed to parse argument\n", __FUNCTION__); + returnResponse(false); + } - if (getParamIndex("CMS",inputInfo,indexInfo) == -1) { - LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); - returnResponse(false); - } + if (getParamIndex("CMS",inputInfo,indexInfo) == -1) { + LOGERR("%s: getParamIndex failed to get \n", __FUNCTION__); + returnResponse(false); + } - if ( convertCMSParamToPQEnum(inputInfo.component,inputInfo.color,tvPQEnum) != 0 ) { - LOGINFO("%s: Component/Color Param Not Found \n",__FUNCTION__); - returnResponse(false); - } + if ( convertCMSParamToPQEnum(inputInfo.component,inputInfo.color,tvPQEnum) != 0 ) { + LOGINFO("%s: Component/Color Param Not Found \n",__FUNCTION__); + returnResponse(false); + } - int err = getLocalparam("CMS",indexInfo,level,tvPQEnum); - if( err == 0 ) { - response["level"] = level; - LOGINFO("Exit : params Value: %d \n", level); - returnResponse(true); + int err = getLocalparam("CMS",indexInfo,level,tvPQEnum); + if( err == 0 ) { + response["level"] = level; + LOGINFO("Exit : params Value: %d \n", level); + returnResponse(true); + } + else { + returnResponse(false); + } } - else { - returnResponse(false); + else + { + // Extract color and component from input parameters + std::string color = parameters.HasLabel("color") ? parameters["color"].String() : ""; + std::string component = parameters.HasLabel("component") ? parameters["component"].String() : ""; + + if (color.empty() || component.empty()) { + LOGERR("%s: Missing color/component parameter", __FUNCTION__); + returnResponse(false); + } + + tvPQParameterIndex_t pqEnum; + if (convertCMSParamToPQEnum(component, color, pqEnum) != 0) { + LOGERR("%s: Invalid color/component combination", __FUNCTION__); + returnResponse(false); + } + + // Get valid context from parameters using your existing context helper + tvConfigContext_t validContext = getValidContextFromGetParameters(parameters, "CMS"); + + if ((validContext.videoSrcType == VIDEO_SOURCE_ALL && + validContext.videoFormatType == VIDEO_FORMAT_NONE && + validContext.pq_mode == PQ_MODE_INVALID)) + { + LOGERR("No valid context found for CMS get"); + returnResponse(false); + } + + // Prepare paramIndex from context + paramIndex_t indexInfo = { + .sourceIndex = static_cast(validContext.videoSrcType), + .pqmodeIndex = static_cast(validContext.pq_mode), + .formatIndex = static_cast(validContext.videoFormatType) + }; + + int level = 0; + int err = getLocalparam("CMS", indexInfo, level, pqEnum); + if (err == 0) { + response["level"] = level; + LOGINFO("Exit: getCMS success, value: %d", level); + returnResponse(true); + } else { + LOGERR("Failed to get CMS param from local storage"); + returnResponse(false); + } } } uint32_t AVOutputTV::setCMS(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_cmsStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + int level = 0,retVal = 0; + tvPQParameterIndex_t tvPQEnum; + tvDataComponentColor_t colorEnum=tvDataColor_NONE; + std::string color,component; + tvError_t ret = tvERROR_NONE; + std::string value; + + inputInfo.color = parameters.HasLabel("color") ? parameters["color"].String() : ""; + inputInfo.component = parameters.HasLabel("component") ? parameters["component"].String() : ""; + if( inputInfo.color.empty() || inputInfo.component.empty() ) { + LOGERR("%s : Color/Component param not found!!!\n",__FUNCTION__); + returnResponse(false); + } - capDetails_t inputInfo; - int level = 0,retVal = 0; - tvPQParameterIndex_t tvPQEnum; - tvDataComponentColor_t colorEnum=tvDataColor_NONE; - std::string color,component; - tvError_t ret = tvERROR_NONE; - std::string value; - - inputInfo.color = parameters.HasLabel("color") ? parameters["color"].String() : ""; - inputInfo.component = parameters.HasLabel("component") ? parameters["component"].String() : ""; + if (isPlatformSupport("CMS") != 0) { + returnResponse(false); + } - if( inputInfo.color.empty() || inputInfo.component.empty() ) { - LOGERR("%s : Color/Component param not found!!!\n",__FUNCTION__); - returnResponse(false); - } + value = parameters.HasLabel("level") ? parameters["level"].String() : ""; + returnIfParamNotFound(parameters,"level"); + level = std::stoi(value); - if (isPlatformSupport("CMS") != 0) { - returnResponse(false); - } + if (validateCMSParameter(inputInfo.component,level) != 0) { + LOGERR("%s: CMS Failed in range validation", __FUNCTION__); + returnResponse(false); + } - value = parameters.HasLabel("level") ? parameters["level"].String() : ""; - returnIfParamNotFound(parameters,"level"); - level = std::stoi(value); + if (parsingSetInputArgument(parameters,"CMS",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if (validateCMSParameter(inputInfo.component,level) != 0) { - LOGERR("%s: CMS Failed in range validation", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "CMS",inputInfo )) { + LOGERR("%s: CapablityCheck failed for CMS\n", __FUNCTION__); + returnResponse(false); + } - if (parsingSetInputArgument(parameters,"CMS",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if ( convertCMSParamToPQEnum(inputInfo.component,inputInfo.color,tvPQEnum) != 0 ) { + LOGERR("%s: %s/%s Param Not Found \n",__FUNCTION__,inputInfo.component.c_str(),inputInfo.color.c_str()); + returnResponse(false); + } - if( !isCapablityCheckPassed( "CMS",inputInfo )) { - LOGERR("%s: CapablityCheck failed for CMS\n", __FUNCTION__); - returnResponse(false); - } + retVal = getCMSColorEnumFromString(inputInfo.color,colorEnum); + if( retVal == -1) { + LOGERR("%s: Invalid Color : %s\n",__FUNCTION__,inputInfo.color.c_str()); + returnResponse(false); + } - if ( convertCMSParamToPQEnum(inputInfo.component,inputInfo.color,tvPQEnum) != 0 ) { - LOGERR("%s: %s/%s Param Not Found \n",__FUNCTION__,inputInfo.component.c_str(),inputInfo.color.c_str()); - returnResponse(false); - } + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + tvError_t ret = SetCMSState(true); + if(ret != tvERROR_NONE) { + LOGWARN("CMS enable failed\n"); + returnResponse(false); + } - retVal = getCMSColorEnumFromString(inputInfo.color,colorEnum); - if( retVal == -1) { - LOGERR("%s: Invalid Color : %s\n",__FUNCTION__,inputInfo.color.c_str()); - returnResponse(false); - } + if(inputInfo.component.compare("Saturation") == 0) + ret = SetCurrentComponentSaturation(colorEnum, level); + else if(inputInfo.component.compare("Hue") == 0 ) + ret = SetCurrentComponentHue(colorEnum,level); + else if( inputInfo.component.compare("Luma") == 0 ) + ret = SetCurrentComponentLuma(colorEnum,level); + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - tvError_t ret = SetCMSState(true); if(ret != tvERROR_NONE) { - LOGWARN("CMS enable failed\n"); + LOGERR("Failed to set CMS\n"); returnResponse(false); } - - if(inputInfo.component.compare("Saturation") == 0) - ret = SetCurrentComponentSaturation(colorEnum, level); - else if(inputInfo.component.compare("Hue") == 0 ) - ret = SetCurrentComponentHue(colorEnum,level); - else if( inputInfo.component.compare("Luma") == 0 ) - ret = SetCurrentComponentLuma(colorEnum,level); - - } + else { + std::string cmsParam; + cmsParam = inputInfo.color+"."+inputInfo.component; - if(ret != tvERROR_NONE) { - LOGERR("Failed to set CMS\n"); - returnResponse(false); + retVal= updateAVoutputTVParam("set","CMS",inputInfo,tvPQEnum,level); + if(retVal != 0 ) { + LOGERR("%s : Failed to Save CMS %s/%s(%s) to ssm_data\n",__FUNCTION__,inputInfo.component.c_str(),inputInfo.color.c_str(),cmsParam.c_str()); + returnResponse(false); + } + LOGINFO("Exit : setCMS %s/%s successful to value: %d\n", inputInfo.component.c_str(),inputInfo.color.c_str(),level); + returnResponse(true); + } } - else { - std::string cmsParam; - cmsParam = inputInfo.color+"."+inputInfo.component; - - retVal= updateAVoutputTVParam("set","CMS",inputInfo,tvPQEnum,level); - if(retVal != 0 ) { - LOGERR("%s : Failed to Save CMS %s/%s(%s) to ssm_data\n",__FUNCTION__,inputInfo.component.c_str(),inputInfo.color.c_str(),cmsParam.c_str()); + else + { + bool status = setCMSParam(parameters); + if (status) { + LOGINFO("setCMS success"); + returnResponse(true); + } else { + LOGERR("setCMS failed"); returnResponse(false); } - LOGINFO("Exit : setCMS %s/%s successful to value: %d\n", inputInfo.component.c_str(),inputInfo.color.c_str(),level); - returnResponse(true); } } uint32_t AVOutputTV::resetCMS(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_cmsStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + int retVal = 0; + std::string color,component; + tvError_t ret = tvERROR_NONE; + JsonArray sourceArray; + JsonArray pqmodeArray; + JsonArray formatArray; + JsonArray colorArray; + JsonArray componentArray; + + if (isPlatformSupport("CMS") != 0) { + returnResponse(false); + } - capDetails_t inputInfo; - int retVal = 0; - std::string color,component; - tvError_t ret = tvERROR_NONE; - JsonArray sourceArray; - JsonArray pqmodeArray; - JsonArray formatArray; - JsonArray colorArray; - JsonArray componentArray; - - if (isPlatformSupport("CMS") != 0) { - returnResponse(false); - } - - pqmodeArray = parameters.HasLabel("pictureMode") ? parameters["pictureMode"].Array() : JsonArray(); - for (int i = 0; i < pqmodeArray.Length(); ++i) { - inputInfo.pqmode += pqmodeArray[i].String(); - if (i != (pqmodeArray.Length() - 1) ) { - inputInfo.pqmode += ","; + pqmodeArray = parameters.HasLabel("pictureMode") ? parameters["pictureMode"].Array() : JsonArray(); + for (int i = 0; i < pqmodeArray.Length(); ++i) { + inputInfo.pqmode += pqmodeArray[i].String(); + if (i != (pqmodeArray.Length() - 1) ) { + inputInfo.pqmode += ","; + } } - } - sourceArray = parameters.HasLabel("videoSource") ? parameters["videoSource"].Array() : JsonArray(); - for (int i = 0; i < sourceArray.Length(); ++i) { - inputInfo.source += sourceArray[i].String(); - if (i != (sourceArray.Length() - 1) ) { - inputInfo.source += ","; - } - } + sourceArray = parameters.HasLabel("videoSource") ? parameters["videoSource"].Array() : JsonArray(); + for (int i = 0; i < sourceArray.Length(); ++i) { + inputInfo.source += sourceArray[i].String(); + if (i != (sourceArray.Length() - 1) ) { + inputInfo.source += ","; + } + } - formatArray = parameters.HasLabel("videoFormat") ? parameters["videoFormat"].Array() : JsonArray(); - for (int i = 0; i < formatArray.Length(); ++i) { - inputInfo.format += formatArray[i].String(); - if (i != (formatArray.Length() - 1) ) { - inputInfo.format += ","; + formatArray = parameters.HasLabel("videoFormat") ? parameters["videoFormat"].Array() : JsonArray(); + for (int i = 0; i < formatArray.Length(); ++i) { + inputInfo.format += formatArray[i].String(); + if (i != (formatArray.Length() - 1) ) { + inputInfo.format += ","; + } } - } - colorArray = parameters.HasLabel("color") ? parameters["color"].Array() : JsonArray(); - for (int i = 0; i < colorArray.Length(); ++i) { - inputInfo.color += colorArray[i].String(); - if (i != (colorArray.Length() - 1) ) { - inputInfo.color += ","; + colorArray = parameters.HasLabel("color") ? parameters["color"].Array() : JsonArray(); + for (int i = 0; i < colorArray.Length(); ++i) { + inputInfo.color += colorArray[i].String(); + if (i != (colorArray.Length() - 1) ) { + inputInfo.color += ","; + } } - } - componentArray = parameters.HasLabel("component") ? parameters["component"].Array() : JsonArray(); - for (int i = 0; i < componentArray.Length(); ++i) { - inputInfo.component += componentArray[i].String(); - if (i != (componentArray.Length() - 1) ) { - inputInfo.component += ","; + componentArray = parameters.HasLabel("component") ? parameters["component"].Array() : JsonArray(); + for (int i = 0; i < componentArray.Length(); ++i) { + inputInfo.component += componentArray[i].String(); + if (i != (componentArray.Length() - 1) ) { + inputInfo.component += ","; + } + } + if (inputInfo.source.empty()) { + inputInfo.source = "Global"; + } + if (inputInfo.pqmode.empty()) { + inputInfo.pqmode = "Global"; + } + if (inputInfo.format.empty()) { + inputInfo.format = "Global"; + } + if (inputInfo.color.empty()) { + inputInfo.color = "Global"; + } + if (inputInfo.component.empty()) { + inputInfo.component = "Global"; } - } - if (inputInfo.source.empty()) { - inputInfo.source = "Global"; - } - if (inputInfo.pqmode.empty()) { - inputInfo.pqmode = "Global"; - } - if (inputInfo.format.empty()) { - inputInfo.format = "Global"; - } - if (inputInfo.color.empty()) { - inputInfo.color = "Global"; - } - if (inputInfo.component.empty()) { - inputInfo.component = "Global"; - } - if (convertToValidInputParameter("CMS", inputInfo) != 0) { - LOGERR("%s: Failed to convert the input paramters. \n", __FUNCTION__); - returnResponse(false); - } + if (convertToValidInputParameter("CMS", inputInfo) != 0) { + LOGERR("%s: Failed to convert the input paramters. \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "CMS" , inputInfo )) { - LOGERR("%s: CapablityCheck failed for CMS\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "CMS" , inputInfo )) { + LOGERR("%s: CapablityCheck failed for CMS\n", __FUNCTION__); + returnResponse(false); + } + + if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { + LOGINFO("Proceed with %s\n",__FUNCTION__); + tvError_t ret = SetCMSState(false); + if(ret != tvERROR_NONE) { + LOGWARN("CMS disable failed\n"); + returnResponse(false); + } + } - if( isSetRequired(inputInfo.pqmode,inputInfo.source,inputInfo.format) ) { - LOGINFO("Proceed with %s\n",__FUNCTION__); - tvError_t ret = SetCMSState(false); if(ret != tvERROR_NONE) { - LOGWARN("CMS disable failed\n"); + LOGERR("%s : Failed to setCMSState\n",__FUNCTION__); returnResponse(false); - } - } - - if(ret != tvERROR_NONE) { - LOGERR("%s : Failed to setCMSState\n",__FUNCTION__); - returnResponse(false); + } + else { + int cms = 0; + retVal= updateAVoutputTVParam("reset","CMS",inputInfo,PQ_PARAM_CMS_SATURATION_RED,cms); + if(retVal != 0 ) { + LOGERR("%s : Failed to Save CMS %s/%s to ssm_data\n",__FUNCTION__,inputInfo.component.c_str(),inputInfo.color.c_str() ); + returnResponse(false); + } + returnResponse(true); + } } - else { + else + { + if (isSetRequiredForParam(parameters, "CMS")) { + LOGINFO("Proceed with SetCMSState \n"); + tvError_t ret = SetCMSState(false); + if(ret != tvERROR_NONE) { + LOGWARN("CMS disable failed\n"); + returnResponse(false); + } + } int cms = 0; - retVal= updateAVoutputTVParam("reset","CMS",inputInfo,PQ_PARAM_CMS_SATURATION_RED,cms); + int retVal= updateAVoutputTVParamV2("reset","CMS",parameters,PQ_PARAM_CMS,cms); if(retVal != 0 ) { - LOGERR("%s : Failed to Save CMS %s/%s to ssm_data\n",__FUNCTION__,inputInfo.component.c_str(),inputInfo.color.c_str() ); + LOGERR("%s : Failed to Save CMS to ssm_data\n",__FUNCTION__); returnResponse(false); } returnResponse(true); } } + uint32_t AVOutputTV::getCMSCapsV2(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry: getCMSCapsV2"); + + int max_hue = 0, max_saturation = 0, max_luma = 0; + tvDataComponentColor_t* colorArray = nullptr; + tvComponentType_t* componentArray = nullptr; + size_t num_color = 0, num_component = 0; + tvContextCaps_t* context_caps = nullptr; + + tvError_t ret = GetCMSCaps(&max_hue, &max_saturation, &max_luma, + &colorArray, &componentArray, + &num_color, &num_component, &context_caps); + + if (ret != tvERROR_NONE) { + LOGERR("GetCMSCaps failed with error: %d", ret); + returnResponse(false); + } + response["platformSupport"] = true; + + // Range Info + JsonObject rangeHue, rangeSaturation, rangeLuma; + rangeHue["from"] = 0; + rangeHue["to"] = max_hue; + rangeSaturation["from"] = 0; + rangeSaturation["to"] = max_saturation; + rangeLuma["from"] = 0; + rangeLuma["to"] = max_luma; + + response["rangeHue"] = rangeHue; + response["rangeSaturation"] = rangeSaturation; + response["rangeLuma"] = rangeLuma; + + // Color Info + JsonArray colorJson; + for (size_t i = 0; i < num_color; ++i) { + colorJson.Add(getCMSColorStringFromEnum(colorArray[i])); + } + response["color"] = colorJson; + + // Component Info + JsonArray componentJson; + for (size_t i = 0; i < num_component; ++i) { + componentJson.Add(getCMSComponentStringFromEnum(componentArray[i])); + } + response["component"] = componentJson; + response["context"] = parseContextCaps(context_caps); +#if HAL_NOT_READY + // Clean up dynamic memory + delete[] colorArray; + delete[] componentArray; +#endif + LOGINFO("Exit: getCMSCapsV2"); + returnResponse(true); + } + uint32_t AVOutputTV::getCMSCaps(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry"); @@ -3334,7 +5511,7 @@ namespace Plugin { capDetails_t inputInfo; tvError_t ret = tvERROR_NONE; std::string value; - int retval = 0; + int retval = 0; value = parameters.HasLabel("HDRMode") ? parameters["HDRMode"].String() : ""; returnIfParamNotFound(parameters,"HDRMode"); @@ -3670,6 +5847,62 @@ namespace Plugin { } } + uint32_t AVOutputTV::get2PointWBCapsV2(const JsonObject& parameters, JsonObject& response) + { + LOGINFO("Entry: get2PointWBCapsV2"); + + int min_gain = 0, min_offset = 0, max_gain = 0, max_offset = 0; + tvWBColor_t* colorArray = nullptr; + tvWBControl_t* controlArray = nullptr; + size_t num_color = 0, num_control = 0; + tvContextCaps_t* context_caps = nullptr; + + tvError_t ret = GetCustom2PointWhiteBalanceCaps(&min_gain, &min_offset, &max_gain, &max_offset, + &colorArray, &controlArray, + &num_color, &num_control, &context_caps); + + if (ret != tvERROR_NONE) { + LOGERR("GetCustom2PointWhiteBalanceCaps failed with error: %d", ret); + returnResponse(false); + } + + response["platformSupport"] = true; + + // Range Info + JsonObject rangeGain, rangeOffset; + rangeGain["from"] = min_gain; + rangeGain["to"] = max_gain; + rangeOffset["from"] = min_offset; + rangeOffset["to"] = max_offset; + + response["rangeGain"] = rangeGain; + response["rangeOffset"] = rangeOffset; + + // Control Info + JsonArray controlJson; + for (size_t i = 0; i < num_control; ++i) { + controlJson.Add(getWBControlStringFromEnum(controlArray[i])); + } + response["control"] = controlJson; + + // Color Info + JsonArray colorJson; + for (size_t i = 0; i < num_color; ++i) { + colorJson.Add(getWBColorStringFromEnum(colorArray[i])); + } + response["color"] = colorJson; + response["context"] = parseContextCaps(context_caps); + +#if HAL_NOT_READY + delete[] colorArray; + delete[] controlArray; +#endif + + LOGINFO("Exit: get2PointWBCapsV2"); + returnResponse(true); + } + + uint32_t AVOutputTV::get2PointWBCaps(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); @@ -3796,83 +6029,113 @@ namespace Plugin { uint32_t AVOutputTV::setAutoBacklightMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); - std::string value; - tvBacklightMode_t mode = tvBacklightMode_AMBIENT; - capDetails_t inputInfo; - + if(m_backlightModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + std::string value; + tvBacklightMode_t mode = tvBacklightMode_AMBIENT; + capDetails_t inputInfo; - value = parameters.HasLabel("mode") ? parameters["mode"].String() : ""; - returnIfParamNotFound(parameters,"mode"); + value = parameters.HasLabel("mode") ? parameters["mode"].String() : ""; + returnIfParamNotFound(parameters,"mode"); - if (validateInputParameter("AutoBacklightMode",value) != 0) { - LOGERR("%s: Range validation failed for AutoBacklightMode\n", __FUNCTION__); - returnResponse(false); - } + if (validateInputParameter("AutoBacklightMode",value) != 0) { + LOGERR("%s: Range validation failed for AutoBacklightMode\n", __FUNCTION__); + returnResponse(false); + } - if (isPlatformSupport("AutoBacklightMode") != 0) { - returnResponse(false); - } + if (isPlatformSupport("AutoBacklightMode") != 0) { + returnResponse(false); + } - if (parsingSetInputArgument(parameters,"AutoBacklightMode",inputInfo) != 0) { - LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); - returnResponse(false); - } + if (parsingSetInputArgument(parameters,"AutoBacklightMode",inputInfo) != 0) { + LOGERR("%s: Failed to parse the input arguments \n", __FUNCTION__); + returnResponse(false); + } - if( !isCapablityCheckPassed( "AutoBacklightMode",inputInfo )) { - LOGERR("%s: CapablityCheck failed for AutoBacklightMode\n", __FUNCTION__); - returnResponse(false); - } + if( !isCapablityCheckPassed( "AutoBacklightMode",inputInfo )) { + LOGERR("%s: CapablityCheck failed for AutoBacklightMode\n", __FUNCTION__); + returnResponse(false); + } - if(!value.compare("Manual")) { - mode = tvBacklightMode_MANUAL; - } - else if (!value.compare("Ambient")) { - mode = tvBacklightMode_AMBIENT; - } - else { - returnResponse(false); - } - - tvError_t ret = SetCurrentBacklightMode (mode); + if(!value.compare("Manual")) { + mode = tvBacklightMode_MANUAL; + } + else if (!value.compare("Ambient")) { + mode = tvBacklightMode_AMBIENT; + } + else { + returnResponse(false); + } - if(ret != tvERROR_NONE) { - returnResponse(false); - } - else { - //Save AutoBacklightMode to localstore + tvError_t ret = SetCurrentBacklightMode (mode); - tr181ErrorCode_t err = setLocalParam(rfc_caller_id, AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, value.c_str()); - if ( err != tr181Success ) { - LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, getTR181ErrorString(err)); + if(ret != tvERROR_NONE) { returnResponse(false); } else { - LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, value.c_str()); + //Save AutoBacklightMode to localstore + + tr181ErrorCode_t err = setLocalParam(rfc_caller_id, AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, value.c_str()); + if ( err != tr181Success ) { + LOGERR("setLocalParam for %s Failed : %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, getTR181ErrorString(err)); + returnResponse(false); + } + else { + LOGINFO("setLocalParam for %s Successful, Value: %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, value.c_str()); + } + LOGINFO("Exit : SetAutoBacklightMode() value : %s\n",value.c_str()); + returnResponse(true); } - LOGINFO("Exit : SetAutoBacklightMode() value : %s\n",value.c_str()); - returnResponse(true); + } + else + { + bool success = false; + success = setEnumPQParam( + parameters, + "mode", + "BacklightMode", + backlightModeReverseMap, + PQ_PARAM_BACKLIGHT_MODE, + [](int val) { + return SetCurrentBacklightMode(static_cast(val)); + }); + + returnResponse(success); } } uint32_t AVOutputTV::getAutoBacklightMode(const JsonObject& parameters, JsonObject& response) { + if(m_backlightModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + TR181_ParamData_t param; - TR181_ParamData_t param; - - if (isPlatformSupport("AutoBacklightMode") != 0) { - returnResponse(false); - } + if (isPlatformSupport("AutoBacklightMode") != 0) { + returnResponse(false); + } - tr181ErrorCode_t err = getLocalParam(rfc_caller_id, AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, ¶m); - if (err!= tr181Success) { - returnResponse(false); + tr181ErrorCode_t err = getLocalParam(rfc_caller_id, AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, ¶m); + if (err!= tr181Success) { + returnResponse(false); + } + else { + std::string s; + s+=param.value; + response["mode"] = s; + LOGINFO("Exit getAutoBacklightMode(): %s\n",s.c_str()); + returnResponse(true); + } } - else { - std::string s; - s+=param.value; - response["mode"] = s; - LOGINFO("Exit getAutoBacklightMode(): %s\n",s.c_str()); - returnResponse(true); + else + { + std::string mode; + if (getEnumPQParamString(parameters, "BacklightMode", + PQ_PARAM_BACKLIGHT_MODE, backlightModeMap, mode)) { + response["mode"] = mode; + returnResponse(true); + } else { + returnResponse(false); + } } } @@ -3880,63 +6143,77 @@ namespace Plugin { uint32_t AVOutputTV::resetAutoBacklightMode(const JsonObject& parameters, JsonObject& response) { LOGINFO("Entry\n"); + if(m_backlightModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + tvError_t ret = tvERROR_NONE; - tvError_t ret = tvERROR_NONE; - - if (isPlatformSupport("AutoBacklightMode") != 0) { - returnResponse(false); - } - - tr181ErrorCode_t err = clearLocalParam(rfc_caller_id,AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM); - if ( err != tr181Success ) { - LOGWARN("clearLocalParam for %s Failed : %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, getTR181ErrorString(err)); - ret = tvERROR_GENERAL; - } - else { - LOGINFO("clearLocalParam for %s Successful\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM); - - TR181_ParamData_t param; - memset(¶m, 0, sizeof(param)); + if (isPlatformSupport("AutoBacklightMode") != 0) { + returnResponse(false); + } - tr181ErrorCode_t err = getLocalParam(rfc_caller_id, AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM,¶m); + tr181ErrorCode_t err = clearLocalParam(rfc_caller_id,AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM); if ( err != tr181Success ) { - LOGWARN("getLocalParam for %s Failed : %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, getTR181ErrorString(err)); + LOGWARN("clearLocalParam for %s Failed : %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, getTR181ErrorString(err)); ret = tvERROR_GENERAL; } else { - tvBacklightMode_t blMode = tvBacklightMode_NONE; + LOGINFO("clearLocalParam for %s Successful\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM); - if(!std::string(param.value).compare("none")) { - blMode = tvBacklightMode_NONE; - } - else if (!std::string(param.value).compare("Manual")){ - blMode = tvBacklightMode_MANUAL; - } - else if (!std::string(param.value).compare("Ambient")){ - blMode = tvBacklightMode_AMBIENT; - } - else if (!std::string(param.value).compare("Eco")){ - blMode = tvBacklightMode_ECO; - } - else { - blMode = tvBacklightMode_NONE; - } - ret = SetCurrentBacklightMode(blMode); - if(ret != tvERROR_NONE) { - LOGWARN("Autobacklight Mode set failed: %s\n",getErrorString(ret).c_str()); + TR181_ParamData_t param; + memset(¶m, 0, sizeof(param)); + + tr181ErrorCode_t err = getLocalParam(rfc_caller_id, AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM,¶m); + if ( err != tr181Success ) { + LOGWARN("getLocalParam for %s Failed : %s\n", AVOUTPUT_AUTO_BACKLIGHT_MODE_RFC_PARAM, getTR181ErrorString(err)); + ret = tvERROR_GENERAL; } else { - LOGINFO("Exit : Autobacklight Mode set successfully, value: %s\n", param.value); + tvBacklightMode_t blMode = tvBacklightMode_NONE; + + if(!std::string(param.value).compare("none")) { + blMode = tvBacklightMode_NONE; + } + else if (!std::string(param.value).compare("Manual")){ + blMode = tvBacklightMode_MANUAL; + } + else if (!std::string(param.value).compare("Ambient")){ + blMode = tvBacklightMode_AMBIENT; + } + else if (!std::string(param.value).compare("Eco")){ + blMode = tvBacklightMode_ECO; + } + else { + blMode = tvBacklightMode_NONE; + } + ret = SetCurrentBacklightMode(blMode); + if(ret != tvERROR_NONE) { + LOGWARN("Autobacklight Mode set failed: %s\n",getErrorString(ret).c_str()); + } + else { + LOGINFO("Exit : Autobacklight Mode set successfully, value: %s\n", param.value); + } } - } - } - if(ret != tvERROR_NONE) - { - returnResponse(false); + } + if(ret != tvERROR_NONE) + { + returnResponse(false); + } + else + { + returnResponse(true); + } } else { - returnResponse(true); + bool success = resetEnumPQParamToDefault( + parameters, + "BacklightMode", + PQ_PARAM_BACKLIGHT_MODE, + backlightModeMap, + [](int value, const std::unordered_map&) -> tvError_t { + return SetCurrentBacklightMode(static_cast(value)); + }); + returnResponse(success); } } @@ -3951,7 +6228,7 @@ namespace Plugin { returnResponse(false); } else { - response["currentVideoSource"] = convertSourceIndexToString(currentSource); + response["currentVideoSource"] = convertSourceIndexToStringV2(currentSource); LOGINFO("Exit: getVideoSource :%d success \n", currentSource); returnResponse(true); } diff --git a/AVOutput/AVOutputTV.h b/AVOutput/AVOutputTV.h index 612aebf8..84c89526 100644 --- a/AVOutput/AVOutputTV.h +++ b/AVOutput/AVOutputTV.h @@ -204,6 +204,13 @@ class AVOutputTV : public AVOutputBase { DECLARE_JSON_RPC_METHOD(getHDRMode) DECLARE_JSON_RPC_METHOD(get2PointWB) DECLARE_JSON_RPC_METHOD(getAutoBacklightMode) + DECLARE_JSON_RPC_METHOD(getAISuperResolution) + DECLARE_JSON_RPC_METHOD(getPrecisionDetail) + DECLARE_JSON_RPC_METHOD(getLocalContrastEnhancement) + DECLARE_JSON_RPC_METHOD(getMPEGNoiseReduction) + DECLARE_JSON_RPC_METHOD(getDigitalNoiseReduction) + DECLARE_JSON_RPC_METHOD(getMEMC) + /*Get Capability API's*/ @@ -227,6 +234,29 @@ class AVOutputTV : public AVOutputBase { DECLARE_JSON_RPC_METHOD(get2PointWBCaps) DECLARE_JSON_RPC_METHOD(getHDRModeCaps) DECLARE_JSON_RPC_METHOD(getAutoBacklightModeCaps) + DECLARE_JSON_RPC_METHOD(getBacklightCapsV2) + DECLARE_JSON_RPC_METHOD(getBrightnessCapsV2) + DECLARE_JSON_RPC_METHOD(getContrastCapsV2) + DECLARE_JSON_RPC_METHOD(getSharpnessCapsV2) + DECLARE_JSON_RPC_METHOD(getSaturationCapsV2) + DECLARE_JSON_RPC_METHOD(getHueCapsV2) + DECLARE_JSON_RPC_METHOD(getPrecisionDetailCaps) + DECLARE_JSON_RPC_METHOD(getLowLatencyStateCapsV2) + DECLARE_JSON_RPC_METHOD(getColorTemperatureCapsV2) + DECLARE_JSON_RPC_METHOD(getSDRGammaCaps) + DECLARE_JSON_RPC_METHOD(getBacklightDimmingModeCapsV2) + DECLARE_JSON_RPC_METHOD(getZoomModeCapsV2) + DECLARE_JSON_RPC_METHOD(getCMSCapsV2) + DECLARE_JSON_RPC_METHOD(get2PointWBCapsV2) + DECLARE_JSON_RPC_METHOD(getDolbyVisionCalibrationCaps) + DECLARE_JSON_RPC_METHOD(getPictureModeCapsV2) + DECLARE_JSON_RPC_METHOD(getAutoBacklightModeCapsV2) + DECLARE_JSON_RPC_METHOD(getLocalContrastEnhancementCaps) + DECLARE_JSON_RPC_METHOD(getMPEGNoiseReductionCaps) + DECLARE_JSON_RPC_METHOD(getDigitalNoiseReductionCaps) + DECLARE_JSON_RPC_METHOD(getAISuperResolutionCaps) + DECLARE_JSON_RPC_METHOD(getMEMCCaps) + DECLARE_JSON_RPC_METHOD(getMultiPointWBCaps) /*Set API's*/ DECLARE_JSON_RPC_METHOD(setBacklight) @@ -247,6 +277,12 @@ class AVOutputTV : public AVOutputBase { DECLARE_JSON_RPC_METHOD(set2PointWB ) DECLARE_JSON_RPC_METHOD(signalFilmMakerMode) DECLARE_JSON_RPC_METHOD(setAutoBacklightMode) + DECLARE_JSON_RPC_METHOD(setAISuperResolution) + DECLARE_JSON_RPC_METHOD(setPrecisionDetail) + DECLARE_JSON_RPC_METHOD(setLocalContrastEnhancement) + DECLARE_JSON_RPC_METHOD(setMPEGNoiseReduction) + DECLARE_JSON_RPC_METHOD(setDigitalNoiseReduction) + DECLARE_JSON_RPC_METHOD(setMEMC) /*Reset API's*/ DECLARE_JSON_RPC_METHOD(resetBacklight) @@ -265,6 +301,14 @@ class AVOutputTV : public AVOutputBase { DECLARE_JSON_RPC_METHOD(resetCMS) DECLARE_JSON_RPC_METHOD(reset2PointWB) DECLARE_JSON_RPC_METHOD(resetAutoBacklightMode) + DECLARE_JSON_RPC_METHOD(resetAISuperResolution) + DECLARE_JSON_RPC_METHOD(resetPrecisionDetail) + DECLARE_JSON_RPC_METHOD(resetLocalContrastEnhancement) + DECLARE_JSON_RPC_METHOD(resetMPEGNoiseReduction) + DECLARE_JSON_RPC_METHOD(resetDigitalNoiseReduction) + DECLARE_JSON_RPC_METHOD(resetMEMC) + + private: @@ -340,8 +384,12 @@ class AVOutputTV : public AVOutputBase { tvError_t getParamsCaps(std::string param, capVectors_t &vecInfo); int GetPanelID(char *panelid); int ReadCapablitiesFromConf(std::string param, capDetails_t& info); + void getDimmingModeStringFromEnum(int value, std::string &toStore); void getColorTempStringFromEnum(int value, std::string &toStore); + void getDisplayModeStringFromEnum(int value, std::string &toStore); + void getBacklightModeStringFromEnum(int value, std::string &toStore); + int getCurrentPictureMode(char *picMode); int getDolbyParamToSync(int sourceIndex, int formatIndex, int& value); tvDolbyMode_t GetDolbyVisionEnumFromModeString(const char* modeString); @@ -372,6 +420,145 @@ class AVOutputTV : public AVOutputBase { void broadcastLowLatencyModeChangeEvent(bool lowLatencyMode); tvError_t setAspectRatioZoomSettings(tvDisplayMode_t mode); tvError_t setDefaultAspectRatio(std::string pqmode="none",std::string format="none",std::string source="none"); + template + static int getEnumFromString(const std::map& reverseMap, const std::string& key, T defaultVal) { + auto it = reverseMap.find(key); + return (it != reverseMap.end()) ? it->second : defaultVal; + } + + static const std::map pqModeMap; + static const std::map videoFormatMap; + static const std::map videoSrcMap; + static const std::unordered_map backlightModeMap; + + static std::unordered_map pqModeReverseMap; + static std::unordered_map videoFormatReverseMap; + static std::unordered_map videoSrcReverseMap; + static bool reverseMapsInitialized; + static void initializeReverseMaps(); + static const std::unordered_map backlightModeReverseMap; + + tvError_t ReadJsonFile(JsonObject& root); + tvError_t ExtractContextCaps(const JsonObject& data, tvContextCaps_t** context_caps); + tvError_t ExtractRangeInfo(const JsonObject& data, int* max_value); + std::vector ParseContextCaps(const JsonObject& context); + tvContextCaps_t* AllocateContextCaps(const std::vector& contexts); + tvError_t GetCaps(const std::string& key, int* max_value, tvContextCaps_t** context_caps); + + tvError_t GetDVCalibrationCaps(tvDVCalibrationSettings_t **min_values, tvDVCalibrationSettings_t **max_values, tvContextCaps_t **context_caps); + tvError_t GetBacklightModeCaps(tvBacklightMode_t** backlight_mode, size_t* num_backlight_mode, tvContextCaps_t** context_caps); + tvError_t GetLocalContrastEnhancementCaps(int* maxLocalContrastEnhancement, tvContextCaps_t** context_caps); + tvError_t GetMPEGNoiseReductionCaps(int* maxMPEGNoiseReduction, tvContextCaps_t** context_caps); + tvError_t GetDigitalNoiseReductionCaps(int* maxDigitalNoiseReduction, tvContextCaps_t** context_caps); + tvError_t GetMultiPointWBCaps(int* num_hal_matrix_points, + int* rgb_min, + int* rgb_max, + int* num_ui_matrix_points, + double** ui_matrix_positions, + tvContextCaps_t** context_caps); + tvError_t GetCMSCaps(int* max_hue, + int* max_saturation, + int* max_luma, + tvDataComponentColor_t** color, + tvComponentType_t** component, + size_t* num_color, + size_t* num_component, + tvContextCaps_t** context_caps); + tvError_t GetCustom2PointWhiteBalanceCaps( int *min_gain, + int *min_offset, int *max_gain, + int *max_offset, tvWBColor_t **color, + tvWBControl_t **control, size_t* num_color, + size_t* num_control, tvContextCaps_t ** context_caps); +#define HAL_NOT_READY 0 +#if HAL_NOT_READY +#define CAPABLITY_FILE_NAMEV2 "/opt/panel/pq_capabilities.json" + tvError_t GetBacklightCaps(int *max_backlight, tvContextCaps_t **context_caps); + tvError_t GetBrightnessCaps(int *max_brightness, tvContextCaps_t **context_caps); + tvError_t GetContrastCaps(int* max_contrast, tvContextCaps_t** context_caps); + tvError_t GetSharpnessCaps(int *max_sharpness, tvContextCaps_t **context_caps); + tvError_t GetSaturationCaps(int* max_saturation, tvContextCaps_t** context_caps); + tvError_t GetHueCaps(int* max_hue, tvContextCaps_t** context_caps); + tvError_t GetPrecisionDetailCaps(int* max_precision, tvContextCaps_t** context_caps); + tvError_t GetLowLatencyStateCaps(int* max_latency, tvContextCaps_t ** context_caps); + tvError_t GetColorTemperatureCaps(tvColorTemp_t** color_temp, size_t* num_color_temp, tvContextCaps_t** context_caps); + tvError_t GetSdrGammaCaps(tvSdrGamma_t** sdr_gamma, size_t* num_sdr_gamma, tvContextCaps_t** context_caps); + tvError_t GetTVDimmingModeCaps(tvDimmingMode_t** dimming_mode, size_t* num_dimming_mode, tvContextCaps_t** context_caps); + tvError_t GetAspectRatioCaps(tvDisplayMode_t** aspect_ratio, size_t* num_aspect_ratio, tvContextCaps_t** context_caps); + tvError_t GetTVPictureModeCaps(tvPQModeIndex_t** mode, size_t* num_pic_modes, tvContextCaps_t** context_caps); + tvError_t GetAISuperResolutionCaps(int* maxAISuperResolution, tvContextCaps_t** context_caps); + tvError_t GetMEMCCaps(int* maxMEMC, tvContextCaps_t** context_caps); +#else +#define CAPABLITY_FILE_NAMEV2 "/etc/pq_capabilities.json" +#endif + uint32_t getPQCapabilityWithContext( + const std::function& getCapsFunc, + const JsonObject& parameters, + JsonObject& response); + JsonObject parseContextCaps(tvContextCaps_t* context_caps); + // Helper functions to extract modes/sources/formats from parameters + std::vector extractPQModes(const JsonObject& parameters); + std::vector extractVideoSources(const JsonObject& parameters); + std::vector extractVideoFormats(const JsonObject& parameters); + static bool isGlobalParam(const JsonArray& arr); + JsonArray getJsonArrayIfArray(const JsonObject& obj, const std::string& key); + int updateAVoutputTVParamV2(std::string action, std::string tr181ParamName, + const JsonObject& parameters, tvPQParameterIndex_t pqParamIndex, int level); + std::vector getValidContextsFromParameters(const JsonObject& parameters,const std::string& tr181ParamName ); + typedef tvError_t (*tvSetFunction)(int); + bool resetPQParamToDefault(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqIndex, + tvSetFunction halSetter); + typedef tvError_t (*tvSetFunctionV2)(tvVideoSrcType_t, tvPQModeIndex_t,tvVideoFormatType_t,int); + bool resetPQParamToDefault(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqIndex, + tvSetFunctionV2 halSetter); + bool resetEnumPQParamToDefault(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqIndex, + const std::unordered_map& valueMap, + std::function&)> halSetter); + tvConfigContext_t getValidContextFromGetParameters(const JsonObject& parameters, const std::string& paramName); + bool getPQParamFromContext(const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t paramType, + int& outValue); + bool getEnumPQParamString( + const JsonObject& parameters, + const std::string& paramName, + tvPQParameterIndex_t pqType, + const std::unordered_map& enumToStrMap, + std::string& outStr); + bool setIntPQParam(const JsonObject& parameters, const std::string& paramName, + tvPQParameterIndex_t pqType, tvSetFunction halSetter, int maxCap); + bool setEnumPQParam(const JsonObject& parameters, + const std::string& inputKey, + const std::string& paramName, + const std::unordered_map& valueMap, + tvPQParameterIndex_t paramType, + std::function halSetter); + uint32_t setContextPQParam(const JsonObject& parameters, JsonObject& response, + const std::string& inputParamName, + const std::string& tr181ParamName, + int maxAllowedValue, + tvPQParameterIndex_t pqParamType, + std::function halSetter); + bool setPictureModeV2(const JsonObject& parameters); + bool getPictureModeV2(const JsonObject& parameters, std::string& outMode); + std::string getCurrentPictureModeAsString(); + std::string getCurrentVideoFormatAsString(); + std::string getCurrentVideoSourceAsString(); + bool isSetRequiredForParam(const JsonObject& parameters, const std::string& paramName); + tvContextCaps_t* getCapsForParam(const std::string& paramName); + bool isValidSource(const std::vector& sourceArray, tvVideoSrcType_t sourceIndex); + bool isValidFormat(const std::vector& formatArray, tvVideoFormatType_t formatIndex); + tvError_t updateAVoutputTVParamToHALV2(std::string forParam, paramIndex_t indexInfo, int value, bool setNotDelete); + bool resetPictureModeV2(const JsonObject& parameters); + int syncAvoutputTVPQModeParamsToHALV2(std::string pqmode, std::string source, std::string format); + std::string getCMSNameFromEnum(tvDataComponentColor_t colorEnum); + void syncCMSParamsV2(); + public: int m_currentHdmiInResoluton; @@ -380,6 +567,125 @@ class AVOutputTV : public AVOutputBase { char rfc_caller_id[RFC_BUFF_MAX]; bool appUsesGlobalBackLightFactor; int pic_mode_index[PIC_MODES_SUPPORTED_MAX]; + + + int m_maxBacklight = 0; + tvContextCaps_t* m_backlightCaps = nullptr; + tvError_t m_backlightStatus = tvERROR_NONE; + + int m_maxBrightness = 0; + tvContextCaps_t* m_brightnessCaps = nullptr; + tvError_t m_brightnessStatus = tvERROR_NONE; + + int m_maxContrast = 0; + tvContextCaps_t* m_contrastCaps = nullptr; + tvError_t m_contrastStatus = tvERROR_NONE; + + int m_maxSharpness = 0; + tvContextCaps_t* m_sharpnessCaps = nullptr; + tvError_t m_sharpnessStatus = tvERROR_NONE; + + int m_maxSaturation = 0; + tvContextCaps_t* m_saturationCaps = nullptr; + tvError_t m_saturationStatus = tvERROR_NONE; + + int m_maxHue = 0; + tvContextCaps_t* m_hueCaps = nullptr; + tvError_t m_hueStatus = tvERROR_NONE; + + int m_maxlowLatencyState = 0; + tvContextCaps_t* m_lowLatencyStateCaps = nullptr; + tvError_t m_lowLatencyStateStatus = tvERROR_NONE; + + int m_maxPrecisionDetail = 0; + tvContextCaps_t* m_precisionDetailCaps = nullptr; + tvError_t m_precisionDetailStatus = tvERROR_NONE; + + int m_maxLocalContrastEnhancement = 0; + tvContextCaps_t* m_localContrastEnhancementCaps = nullptr; + tvError_t m_localContrastEnhancementStatus = tvERROR_NONE; + + int m_maxMPEGNoiseReduction = 0; + tvContextCaps_t* m_MPEGNoiseReductionCaps = nullptr; + tvError_t m_MPEGNoiseReductionStatus = tvERROR_NONE; + + int m_maxDigitalNoiseReduction = 0; + tvContextCaps_t* m_digitalNoiseReductionCaps = nullptr; + tvError_t m_digitalNoiseReductionStatus = tvERROR_NONE; + + int m_maxAISuperResolution = 0; + tvContextCaps_t* m_AISuperResolutionCaps = nullptr; + tvError_t m_AISuperResolutionStatus = tvERROR_NONE; + + int m_maxMEMC = 0; + tvContextCaps_t* m_MEMCCaps = nullptr; + tvError_t m_MEMCStatus = tvERROR_NONE; + + tvColorTemp_t* m_colortemp = nullptr; + size_t m_numColortemp = 0; + tvContextCaps_t* m_colortempCaps = nullptr; + tvError_t m_colorTempStatus = tvERROR_NONE; + + tvDisplayMode_t* m_aspectRatio = nullptr; + size_t m_numAspectRatio = 0; + tvContextCaps_t* m_aspectRatioCaps = nullptr; + tvError_t m_aspectRatioStatus = tvERROR_NONE; + + tvDimmingMode_t* m_dimmingModes = nullptr; + size_t m_numdimmingModes = 0; + tvContextCaps_t* m_dimmingModeCaps = nullptr; + tvError_t m_dimmingModeStatus = tvERROR_NONE; + + tvPQModeIndex_t* m_pictureModes = nullptr; + size_t m_numPictureModes = 0; + tvContextCaps_t* m_pictureModeCaps = nullptr; + tvError_t m_pictureModeStatus = tvERROR_NONE; + + tvBacklightMode_t* m_backlightModes = nullptr; + size_t m_numBacklightModes = 0; + tvContextCaps_t* m_backlightModeCaps = nullptr; + tvError_t m_backlightModeStatus = tvERROR_NONE; + + tvSdrGamma_t* m_sdrGammaModes = nullptr; + size_t m_numsdrGammaModes = 0; + tvContextCaps_t* m_sdrGammaModeCaps = nullptr; + tvError_t m_sdrGammaModeStatus = tvERROR_NONE; + + int m_numHalMatrixPoints = 0; + int m_rgbMin = 0; + int m_rgbMax = 0; + int m_numUiMatrixPoints = 0; + double* m_uiMatrixPositions = nullptr; + tvContextCaps_t* m_multiPointWBCaps = nullptr; + tvError_t m_multiPointWBStatus = tvERROR_NONE; + + tvDVCalibrationSettings_t* m_minValues; + tvDVCalibrationSettings_t* m_maxValues; + tvContextCaps_t* m_DVCalibrationCaps = nullptr; + tvError_t m_DVCalibrationStatus = tvERROR_NONE; + + int m_maxCmsHue = 0; + int m_maxCmsSaturation = 0; + int m_maxCmsLuma = 0; + size_t m_numColor = 0; + size_t m_numComponent = 0; + tvDataComponentColor_t* m_cmsColorArr; + tvComponentType_t* m_cmsComponentArr; + std::vector m_cmsColorList; + std::vector m_cmsComponentList; + std::unordered_map m_cmsIndexMap; + tvContextCaps_t* m_cmsCaps = nullptr; + tvError_t m_cmsStatus = tvERROR_NONE; + + bool setCMSParam(const JsonObject& parameters); + + std::string convertPictureIndexToStringV2(int pqmode); + std::string convertVideoFormatToStringV2(int format); + std::string convertSourceIndexToStringV2(int source); + + uint32_t generateStorageIdentifierV2(std::string &key, std::string forParam, paramIndex_t info); + void generateStorageIdentifierCMSV2(std::string &key, std::string forParam, paramIndex_t info); + void generateStorageIdentifierWBV2(std::string &key, std::string forParam, paramIndex_t info); AVOutputTV(); ~AVOutputTV(); @@ -391,7 +697,6 @@ class AVOutputTV : public AVOutputBase { void NotifyFilmMakerModeChange(tvContentType_t mode); void NotifyVideoResolutionChange(tvResolutionParam_t resolution); void NotifyVideoFrameRateChange(tvVideoFrameRate_t frameRate); - //override API static void dsHdmiVideoModeEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); static void dsHdmiStatusEventHandler(const char *owner, IARM_EventId_t eventId, void *data, size_t len); diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 6fbcbab0..c93340d0 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -296,13 +296,13 @@ namespace Plugin { { tvDimmingMode_t index = tvDimmingMode_MAX; - if(mode.compare("Local") == 0 ) { + if(mode.compare("local") == 0 ) { index=tvDimmingMode_Local; } - else if(mode.compare("Fixed") == 0 ) { + else if(mode.compare("fixed") == 0 ) { index=tvDimmingMode_Fixed; } - else if(mode.compare("Global") == 0 ) { + else if(mode.compare("global") == 0 ) { index=tvDimmingMode_Global; } else { @@ -737,7 +737,7 @@ namespace Plugin { GetCurrentVideoSource(¤t_source); tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - tr181_param_name += "."+convertSourceIndexToString(current_source)+"."+"Format."+convertVideoFormatToString(current_format)+"."+"PictureModeString"; + tr181_param_name += "."+convertSourceIndexToStringV2(current_source)+"."+"Format."+convertVideoFormatToStringV2(current_format)+"."+"PictureModeString"; tr181ErrorCode_t err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); if ( tr181Success == err ) { ret = SetTVPictureMode(param.value); @@ -900,6 +900,59 @@ namespace Plugin { return ret; } + tvError_t AVOutputTV::updateAVoutputTVParamToHALV2(std::string forParam, paramIndex_t indexInfo, int value, bool setNotDelete) + { + tvError_t ret = tvERROR_NONE; + std::string key; + + // Generate storage key based on parameter type + if (forParam == "CMS") + generateStorageIdentifierCMS(key, forParam, indexInfo); + else if (forParam == "WhiteBalance") + generateStorageIdentifierWB(key, forParam, indexInfo); + else + generateStorageIdentifierV2(key, forParam, indexInfo); + + if (key.empty()) { + LOGERR("%s generateStorageIdentifier failed\n", __FUNCTION__); + return tvERROR_GENERAL; + } + + tr181ErrorCode_t err = tr181Success; + + if (setNotDelete) { + std::string toStore = std::to_string(value); + + // Map parameters to their string transformation logic (if applicable) + std::map> fnMap = { + {"ColorTemp", [this](int v, std::string& s) { getColorTempStringFromEnum(v, s); }}, + {"DimmingMode", [this](int v, std::string& s) { getDimmingModeStringFromEnum(v, s); }}, + {"AspectRatio", [this](int v, std::string& s) { getDisplayModeStringFromEnum(v, s); }}, + {"BacklightMode", [this](int v, std::string& s) { getBacklightModeStringFromEnum(v, s); }} + }; + + // If there's a custom string conversion for this parameter, apply it + auto it = fnMap.find(forParam); + if (it != fnMap.end()) { + it->second(value, toStore); + } + // Set the value using TR-181 + err = setLocalParam(rfc_caller_id, key.c_str(), toStore.c_str()); + } + else + { + // Delete the value using TR-181 + err = clearLocalParam(rfc_caller_id, key.c_str()); + } + + if (err != tr181Success) { + LOGERR("%s: %s for %s Failed : %s\n",__FUNCTION__, setNotDelete ? "Set" : "Delete", key.c_str(), getTR181ErrorString(err)); + ret = tvERROR_GENERAL; + } + + return ret; + } + tvError_t AVOutputTV::updateAVoutputTVParamToHAL(std::string forParam, paramIndex_t indexInfo, int value,bool setNotDelete) { tvError_t ret = tvERROR_NONE; @@ -913,7 +966,7 @@ namespace Plugin { generateStorageIdentifier(key,forParam,indexInfo); if(key.empty()) { - LOGERR("generateStorageIdentifierDirty failed\n"); + LOGERR("%s generateStorageIdentifierDirty failed\n", __FUNCTION__); ret = tvERROR_GENERAL; } else { @@ -932,7 +985,8 @@ namespace Plugin { err = setLocalParam(rfc_caller_id, key.c_str(),toStore.c_str()); } - else { + else + { err = clearLocalParam(rfc_caller_id, key.c_str()); } @@ -1136,139 +1190,344 @@ namespace Plugin { } return ret; } + void AVOutputTV::syncCMSParamsV2() { + JsonObject parameters; + + // Set default values to "none" to indicate all contexts (global sync) + parameters["pictureMode"] = "none"; + parameters["videoSource"] = "none"; + parameters["videoFormat"] = "none"; + + // Use "Global" to trigger syncing for all CMS components and colors + parameters["color"] = "Global"; + parameters["component"] = "Global"; + + // Dummy PQ index; unused for CMS sync but required by function signature + tvPQParameterIndex_t dummyPQIndex = PQ_PARAM_CMS_SATURATION_RED; + + int result = updateAVoutputTVParamV2("sync", "CMS", parameters, dummyPQIndex, 0); + if (result == 0) { + LOGINFO("%s: CMS sync completed successfully", __FUNCTION__); + } else { + LOGERR("%s: CMS sync encountered errors", __FUNCTION__); + } + } - tvError_t AVOutputTV::syncAvoutputTVParamsToHAL(std::string pqmode,std::string source,std::string format) + tvError_t AVOutputTV::syncAvoutputTVParamsToHAL(std::string pqmode, std::string source, std::string format) { - int level={0}; + int level = {0}; capDetails_t info; info.pqmode = pqmode; info.source = source; info.format = format; - LOGINFO("Entry %s : pqmode : %s source : %s format : %s\n",__FUNCTION__,pqmode.c_str(),source.c_str(),format.c_str()); - - if( !updateAVoutputTVParam("sync","Brightness",info,PQ_PARAM_BRIGHTNESS,level)) { - LOGINFO("Brightness Successfully sync to Drive Cache\n"); - } - else { - LOGERR("Brightness Sync to cache Failed !!!\n"); + JsonObject paramJson; + paramJson["pictureMode"] = info.pqmode; + paramJson["videoSource"] = info.source; + paramJson["videoFormat"] = info.format; + LOGINFO("Entry %s : pqmode : %s source : %s format : %s\n", __FUNCTION__, pqmode.c_str(), source.c_str(), format.c_str()); + + // Brightness + m_brightnessStatus = GetBrightnessCaps(&m_maxBrightness, &m_brightnessCaps); + LOGINFO("GetBrightnessCaps returned status: %d, max: %d", m_brightnessStatus, m_maxBrightness); + if (m_brightnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "Brightness", info, PQ_PARAM_BRIGHTNESS, level); + } else { + updateAVoutputTVParamV2("sync", "Brightness", paramJson, PQ_PARAM_BRIGHTNESS,level); } - if( !updateAVoutputTVParam("sync","Contrast",info,PQ_PARAM_CONTRAST,level)) { - LOGINFO("Contrast Successfully Synced to Drive Cache\n"); + // Contrast + m_contrastStatus = GetContrastCaps(&m_maxContrast, &m_contrastCaps); + LOGINFO("GetContrastCaps returned status: %d, max: %d", m_contrastStatus, m_maxContrast); + if (m_contrastStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "Contrast", info, PQ_PARAM_CONTRAST, level); + } else { + updateAVoutputTVParamV2("sync", "Contrast", paramJson, PQ_PARAM_CONTRAST,level); } - else { - LOGERR("Contrast Sync to cache Failed !!!\n"); + + // Sharpness + m_sharpnessStatus = GetSharpnessCaps(&m_maxSharpness, &m_sharpnessCaps); + LOGINFO("GetSharpnessCaps returned status: %d, max: %d", m_sharpnessStatus, m_maxSharpness); + if (m_sharpnessStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "Sharpness", info, PQ_PARAM_SHARPNESS, level); + } else { + updateAVoutputTVParamV2("sync", "Sharpness", paramJson, PQ_PARAM_SHARPNESS, level); } - if( !updateAVoutputTVParam("sync","Sharpness",info,PQ_PARAM_SHARPNESS,level)) { - LOGINFO("Sharpness Successfully Synced to Drive Cache\n"); + // Saturation + m_saturationStatus = GetSaturationCaps(&m_maxSaturation, &m_saturationCaps); + LOGINFO("GetSaturationCaps returned status: %d, max: %d", m_saturationStatus, m_maxSaturation); + if (m_saturationStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "Saturation", info, PQ_PARAM_SATURATION, level); + } else { + updateAVoutputTVParamV2("sync", "Saturation", paramJson, PQ_PARAM_SATURATION,level); } - else { - LOGERR("Sharpness Sync to cache Failed !!!\n"); + + // Hue + m_hueStatus = GetHueCaps(&m_maxHue, &m_hueCaps); + LOGINFO("GetHueCaps returned status: %d, max: %d", m_hueStatus, m_maxHue); + if (m_hueStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "Hue", info, PQ_PARAM_HUE, level); + } else { + updateAVoutputTVParamV2("sync", "Hue", paramJson, PQ_PARAM_HUE, level); } - if( !updateAVoutputTVParam("sync","Saturation",info,PQ_PARAM_SATURATION,level)) { - LOGINFO("Saturation Successfully Synced to Drive Cache\n"); + // ColorTemperature + m_colorTempStatus = GetColorTemperatureCaps(&m_colortemp, &m_numColortemp, &m_colortempCaps); + LOGINFO("GetColorTemperatureCaps returned status: %d, numColortemp: %d", m_colorTempStatus, m_numColortemp); + if (m_colorTempStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "ColorTemp", info, PQ_PARAM_COLOR_TEMPERATURE, level); + } else { + updateAVoutputTVParamV2("sync", "ColorTemp", paramJson, PQ_PARAM_COLOR_TEMPERATURE,level); } - else { - LOGERR("Saturation Sync to cache Failed !!!\n"); + + // HDRMode + updateAVoutputTVParam("sync", "HDRMode", info, PQ_PARAM_DOLBY_MODE, level); + + // DimmingMode + m_dimmingModeStatus = GetTVDimmingModeCaps(&m_dimmingModes, &m_numdimmingModes, &m_dimmingModeCaps); + LOGINFO("GetTVDimmingModeCaps returned status: %d, numdimmingModes: %d", m_dimmingModeStatus, m_numdimmingModes); + if (m_dimmingModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "DimmingMode", info, PQ_PARAM_DIMMINGMODE, level); + } else { +#if !HAL_NOT_READY + updateAVoutputTVParamV2("sync", "DimmingMode", paramJson, PQ_PARAM_DIMMINGMODE,level); +#endif } - if( !updateAVoutputTVParam("sync","Hue",info,PQ_PARAM_HUE,level)) { - LOGINFO("Hue Successfully Synced to Drive Cache\n"); + // Backlight + LOGINFO("Calling GetBacklightCaps..."); + m_backlightStatus = GetBacklightCaps(&m_maxBacklight, &m_backlightCaps); + LOGINFO("GetBacklightCaps returned status: %d, maxBacklight: %d", m_backlightStatus, m_maxBacklight); +#if DEBUG + if (m_backlightCaps) + { + LOGINFO("Backlight caps pointer is valid. Num contexts: %zu", m_backlightCaps->num_contexts); + for (size_t i = 0; i < m_backlightCaps->num_contexts; ++i) { + const auto& context = m_backlightCaps->contexts[i]; + std::string pqModeStr = AVOutputTV::pqModeMap.count(context.pq_mode) ? + AVOutputTV::pqModeMap.at(context.pq_mode) : "Unknown"; + std::string formatStr = AVOutputTV::videoFormatMap.count(context.videoFormatType) ? + AVOutputTV::videoFormatMap.at(context.videoFormatType) : "Unknown"; + std::string srcStr = AVOutputTV::videoSrcMap.count(context.videoSrcType) ? + AVOutputTV::videoSrcMap.at(context.videoSrcType) : "Unknown"; + LOGINFO("Context[%zu]: PQMode = %s (%d), Format = %s (%d), Source = %s (%d)", + i, pqModeStr.c_str(), context.pq_mode, + formatStr.c_str(), context.videoFormatType, + srcStr.c_str(), context.videoSrcType); + } + } else { + LOGWARN("Backlight caps pointer is null."); } - else { - LOGERR("Hue Sync to cache Failed !!!\n"); +#endif + if (m_backlightStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "Backlight", info, PQ_PARAM_BACKLIGHT, level); + } else { + updateAVoutputTVParamV2("sync", "Backlight", paramJson, PQ_PARAM_BACKLIGHT, level); } - if( !updateAVoutputTVParam("sync","ColorTemp",info,PQ_PARAM_COLOR_TEMPERATURE,level)) { - LOGINFO("ColorTemp Successfully Synced to Drive Cache\n"); + //Ambient Bakclight Mode + m_backlightModeStatus = GetBacklightModeCaps(&m_backlightModes, &m_numBacklightModes, &m_backlightModeCaps); + if (m_backlightModeStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "BacklightMode", paramJson, PQ_PARAM_BACKLIGHT_MODE, level); } - else { - LOGERR("ColorTemp Sync to cache Failed !!!\n"); + + //AspectRatio + m_aspectRatioStatus = GetAspectRatioCaps(&m_aspectRatio, &m_numAspectRatio, &m_aspectRatioCaps); + //LowLatencyState + m_lowLatencyStateStatus = GetLowLatencyStateCaps(&m_maxlowLatencyState, &m_lowLatencyStateCaps); + // PrecisionDetail + m_precisionDetailStatus = GetPrecisionDetailCaps(&m_maxPrecisionDetail, &m_precisionDetailCaps); + //PictureMode + m_pictureModeStatus = GetTVPictureModeCaps(&m_pictureModes, &m_numPictureModes, &m_pictureModeCaps); + + // LocalContrastEnhancement + m_localContrastEnhancementStatus = GetLocalContrastEnhancementCaps(&m_maxLocalContrastEnhancement, &m_localContrastEnhancementCaps); + if (m_localContrastEnhancementStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "LocalContrastEnhancement", paramJson, PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT, level); } - if( !updateAVoutputTVParam("sync","HDRMode",info,PQ_PARAM_DOLBY_MODE,level)) { - LOGINFO("HDRmode Successfully Synced to Drive Cache\n"); + + // MPEGNoiseReduction + m_MPEGNoiseReductionStatus = GetMPEGNoiseReductionCaps(&m_maxMPEGNoiseReduction, &m_MPEGNoiseReductionCaps); + if (m_MPEGNoiseReductionStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "MPEGNoiseReduction", paramJson, PQ_PARAM_MPEG_NOISE_REDUCTION, level); } - else { - LOGERR("HDRmode Sync to cache Failed !!!\n"); + + // DigitalNoiseReduction + m_digitalNoiseReductionStatus = GetDigitalNoiseReductionCaps(&m_maxDigitalNoiseReduction, &m_digitalNoiseReductionCaps); + if (m_digitalNoiseReductionStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "DigitalNoiseReduction", paramJson, PQ_PARAM_DIGITAL_NOISE_REDUCTION, level); } - if( !updateAVoutputTVParam("sync","DimmingMode",info,PQ_PARAM_DIMMINGMODE,level)) { - LOGINFO("dimmingmode Successfully Synced to Drive Cache\n"); + // AISuperResolution + m_AISuperResolutionStatus = GetAISuperResolutionCaps(&m_maxAISuperResolution, &m_AISuperResolutionCaps); + if (m_AISuperResolutionStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "AISuperResolution", paramJson, PQ_PARAM_AI_SUPER_RESOLUTION,level); } - else { - LOGERR("dimmingmode Sync to cache Failed !!!\n"); + + // MEMC + m_MEMCStatus = GetMEMCCaps(&m_maxMEMC, &m_MEMCCaps); + if (m_MEMCStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "MEMC", paramJson, PQ_PARAM_MEMC, level); } - if( !updateAVoutputTVParam("sync","Backlight",info,PQ_PARAM_BACKLIGHT,level) ) { - LOGINFO("Backlight Successfully Synced to Drive Cache\n"); + m_cmsStatus = GetCMSCaps(&m_maxCmsHue, &m_maxCmsSaturation, &m_maxCmsLuma, + &m_cmsColorArr, &m_cmsComponentArr, + &m_numColor, &m_numComponent, &m_cmsCaps); + if (m_cmsStatus == tvERROR_NONE) { + for (size_t i = 0; i < m_numColor; i++) { + std::string colorStr = getCMSColorStringFromEnum(m_cmsColorArr[i]); + m_cmsColorList.push_back(colorStr); + } + for (size_t i = 0; i < m_numComponent; i++) { + std::string componentStr = getCMSComponentStringFromEnum(m_cmsComponentArr[i]); + m_cmsComponentList.push_back(componentStr); + } + syncCMSParamsV2(); } - else { - LOGERR("Backlight Sync to cache Failed !!!\n"); + if(m_cmsStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + syncCMSParams(); } - syncCMSParams(); //sync CMS - syncWBParams(); - info.format = "DV";//Sync only for Dolby - - if( !updateAVoutputTVParam("sync","DolbyVisionMode",info,PQ_PARAM_DOLBY_MODE,level)) { - LOGINFO("dvmode Successfully Synced to Drive Cache\n"); - } - else { - LOGERR("dvmode Sync to cache Failed !!!\n"); - } + // Dolby Vision Mode + info.format = "DV"; // Sync only for Dolby + updateAVoutputTVParam("sync", "DolbyVisionMode", info, PQ_PARAM_DOLBY_MODE, level); - LOGINFO("Exit %s : pqmode : %s source : %s format : %s\n",__FUNCTION__,pqmode.c_str(),source.c_str(),format.c_str()); + LOGINFO("Exit %s : pqmode : %s source : %s format : %s\n", __FUNCTION__, pqmode.c_str(), source.c_str(), format.c_str()); return tvERROR_NONE; } - - int AVOutputTV::syncAvoutputTVPQModeParamsToHAL(std::string pqmode, std::string source, std::string format) + int AVOutputTV::syncAvoutputTVPQModeParamsToHALV2(std::string pqmode, std::string source, std::string format) { - capDetails_t inputInfo; - valueVectors_t valueVectors; tr181ErrorCode_t err = tr181Success; TR181_ParamData_t param = {0}; - int ret = 0; + bool contextSynced = false; + + // Treat "none" as "Global" + if (source == "none") + source = "Global"; + if (format == "none") + format = "Global"; + + // Handle "Current" source/format substitution + if (source == "Current" || format == "Current") { + tvVideoSrcType_t currentSrc = VIDEO_SOURCE_IP; + tvVideoFormatType_t currentFmt = VIDEO_FORMAT_SDR; + GetCurrentVideoSource(¤tSrc); + GetCurrentVideoFormat(¤tFmt); + if (currentFmt == VIDEO_FORMAT_NONE) + currentFmt = VIDEO_FORMAT_SDR; + + if (source == "Current") + source = convertSourceIndexToStringV2(currentSrc); + if (format == "Current") + format = convertVideoFormatToStringV2(currentFmt); + } + if (m_pictureModeStatus == tvERROR_NONE) + { + for (size_t i = 0; i < m_pictureModeCaps->num_contexts; ++i) { + const tvConfigContext_t& ctx = m_pictureModeCaps->contexts[i]; - inputInfo.pqmode = pqmode; - inputInfo.source = source; - inputInfo.format = format; + std::string sourceStr = convertSourceIndexToStringV2(ctx.videoSrcType); + std::string formatStr = convertVideoFormatToStringV2(ctx.videoFormatType); + + // Filter by provided source/format + if (source != "Global" && source != sourceStr) + continue; + if (format != "Global" && format != formatStr) + continue; + + std::string tr181Param = std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM) + + "." + sourceStr + ".Format." + formatStr + ".PictureModeString"; + + err = getLocalParam(rfc_caller_id, tr181Param.c_str(), ¶m); + if (err != tr181Success) { + LOGWARN("Failed to getLocalParam for %s\n", tr181Param.c_str()); + continue; + } + + std::string modeStr = param.value; + int modeIndex = -1; + for (size_t i = 0; i < m_numPictureModes; ++i) { + if (pqModeMap.at(m_pictureModes[i]) == modeStr) { + modeIndex = static_cast(i); + break; + } + } +#if DEBUG + LOGINFO("Got mode string from TR181: %s -> index=%d", modeStr.c_str(), modeIndex); +#endif + tvError_t tv_err = SaveSourcePictureMode(ctx.videoSrcType, ctx.videoFormatType, modeIndex); + if (tv_err != tvERROR_NONE) { + LOGWARN("Failed SaveSourcePictureMode for %s / %s\n", sourceStr.c_str(), formatStr.c_str()); + continue; + } + + contextSynced = true; + } - ret = getSaveConfig("PictureMode", inputInfo, valueVectors); - - if (ret == 0 ) { - for (int source : valueVectors.sourceValues ) { - tvVideoSrcType_t sourceType = (tvVideoSrcType_t)source; - for (int format : valueVectors.formatValues ) { - tvVideoFormatType_t formatType = (tvVideoFormatType_t)format; - std::string tr181_param_name = ""; - tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - tr181_param_name += "."+convertSourceIndexToString(sourceType)+"."+"Format."+ - convertVideoFormatToString(formatType)+"."+"PictureModeString"; - - err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); - if ( tr181Success == err ) { - std::string local = param.value; - int pqmodeindex = (int)getPictureModeIndex(local); - - tvError_t tv_err = SaveSourcePictureMode(sourceType, formatType, pqmodeindex); - if (tv_err != tvERROR_NONE) { - LOGWARN("failed to SaveSourcePictureMode \n"); + if (!contextSynced) { + LOGWARN("No matching context synced for pqmode=%s source=%s format=%s\n", + pqmode.c_str(), source.c_str(), format.c_str()); + return -1; + } + return 0; + } + return -1; + } + + int AVOutputTV::syncAvoutputTVPQModeParamsToHAL(std::string pqmode, std::string source, std::string format) + { + if (m_pictureModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { + capDetails_t inputInfo; + valueVectors_t valueVectors; + tr181ErrorCode_t err = tr181Success; + TR181_ParamData_t param = {0}; + int ret = 0; + + inputInfo.pqmode = pqmode; + inputInfo.source = source; + inputInfo.format = format; + + ret = getSaveConfig("PictureMode", inputInfo, valueVectors); + + if (ret == 0 ) { + for (int source : valueVectors.sourceValues ) { + tvVideoSrcType_t sourceType = (tvVideoSrcType_t)source; + for (int format : valueVectors.formatValues ) { + tvVideoFormatType_t formatType = (tvVideoFormatType_t)format; + std::string tr181_param_name = ""; + tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); + tr181_param_name += "."+convertSourceIndexToString(sourceType)+"."+"Format."+ + convertVideoFormatToString(formatType)+"."+"PictureModeString"; + + err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); + if ( tr181Success == err ) { + std::string local = param.value; + int pqmodeindex = (int)getPictureModeIndex(local); + + tvError_t tv_err = SaveSourcePictureMode(sourceType, formatType, pqmodeindex); + if (tv_err != tvERROR_NONE) { + LOGWARN("failed to SaveSourcePictureMode \n"); + return -1; + } + } + else { + LOGWARN("Failed to get the getLocalParam \n"); return -1; } } - else { - LOGWARN("Failed to get the getLocalParam \n"); - return -1; - } } } + return ret; + } + else + { + return syncAvoutputTVPQModeParamsToHALV2(pqmode,source,format); } - return ret; } uint32_t AVOutputTV::generateStorageIdentifier(std::string &key, std::string forParam, paramIndex_t info) @@ -1439,7 +1698,7 @@ namespace Plugin { } else if( forParam.compare("WhiteBalance") == 0 ) { generateStorageIdentifierWB(key,forParam,indexInfo); } else { - generateStorageIdentifier(key,forParam,indexInfo); + generateStorageIdentifierV2(key,forParam,indexInfo); } if(key.empty()) { @@ -1480,6 +1739,21 @@ namespace Plugin { } return 0; } + else if ( forParam.compare("BacklightMode") == 0 ) { + if (strncmp(param.value, "Manual", strlen(param.value)) == 0) { + value = tvBacklightMode_MANUAL; + } + else if (strncmp(param.value, "Ambient", strlen(param.value)) == 0) { + value = tvBacklightMode_AMBIENT; + } + else if (strncmp(param.value, "Eco", strlen(param.value)) == 0) { + value = tvBacklightMode_ECO; + } + else { + value = tvBacklightMode_MANUAL; // Default fallback + } + return 0; + } else if ( forParam.compare("DolbyVisionMode") == 0) { if (strncmp(param.value, "Dark", strlen(param.value)) == 0) { value = tvDolbyMode_Dark; @@ -1611,13 +1885,13 @@ namespace Plugin { void AVOutputTV::getDimmingModeStringFromEnum(int value, std::string &toStore) { - const char *color_temp_string[] = { + const char *dimmingmode_string[] = { [tvDimmingMode_Fixed] = "Fixed", [tvDimmingMode_Local] = "Local", [tvDimmingMode_Global] = "Global", }; toStore.clear(); - toStore+=color_temp_string[value]; + toStore+=dimmingmode_string[value]; } void AVOutputTV::getColorTempStringFromEnum(int value, std::string &toStore) @@ -1631,6 +1905,44 @@ namespace Plugin { toStore.clear(); toStore+=color_temp_string[value]; } + void AVOutputTV::getDisplayModeStringFromEnum(int value, std::string &toStore) + { + static const char* display_mode_string[] = { + [tvDisplayMode_4x3] = "TV 4X3 PILLARBOX", + [tvDisplayMode_16x9] = "TV 16X9 STRETCH", + [tvDisplayMode_FULL] = "TV FULL", + [tvDisplayMode_NORMAL] = "TV NORMAL", + [tvDisplayMode_AUTO] = "TV AUTO", + [tvDisplayMode_DIRECT] = "TV DIRECT", + [tvDisplayMode_ZOOM] = "TV ZOOM" + }; + + toStore.clear(); + if (value >= 0 && value < tvDisplayMode_MAX && display_mode_string[value]) { + toStore += display_mode_string[value]; + } else { + toStore += "TV AUTO"; + } + } + + void AVOutputTV::getBacklightModeStringFromEnum(int value, std::string& toStore) + { + toStore.clear(); + switch (static_cast(value)) { + case tvBacklightMode_MANUAL: + toStore = "Manual"; + break; + case tvBacklightMode_AMBIENT: + toStore = "Ambient"; + break; + case tvBacklightMode_ECO: + toStore = "Eco"; + break; + default: + toStore = "Unknown"; + break; + } + } int AVOutputTV::getCurrentPictureMode(char *picMode) { @@ -1652,15 +1964,14 @@ namespace Plugin { } tr181_param_name += std::string(AVOUTPUT_SOURCE_PICTUREMODE_STRING_RFC_PARAM); - tr181_param_name += "." + convertSourceIndexToString(currentSource) + "." + "Format."+convertVideoFormatToString(current_format)+"."+"PictureModeString"; + tr181_param_name += "." + convertSourceIndexToStringV2(currentSource) + "." + "Format."+convertVideoFormatToStringV2(current_format)+"."+"PictureModeString"; memset(¶m, 0, sizeof(param)); tr181ErrorCode_t err = getLocalParam(rfc_caller_id, tr181_param_name.c_str(), ¶m); if ( err == tr181Success ) { strncpy(picMode, param.value, strlen(param.value)+1); - picMode[strlen(param.value)] = '\0'; - LOGINFO("getLocalParam success, mode = %s\n", picMode); + //LOGINFO("getLocalParam success, mode = %s\n", picMode); return 1; } else { @@ -1804,7 +2115,7 @@ namespace Plugin { { tvError_t ret = tvERROR_GENERAL; #if !defined (HDMIIN_4K_ZOOM) - LOGERR("%s:mode selected is: %d", __FUNCTION__, m_videoZoomMode); + LOGINFO("%s:mode selected is: %d", __FUNCTION__, m_videoZoomMode); if (AVOutputTV::instance->m_isDisabledHdmiIn4KZoom) { if (!(AVOutputTV::instance->m_currentHdmiInResolutonm_currentHdmiInResoluton))) { @@ -2207,7 +2518,7 @@ namespace Plugin { case tvColorTemp_WARM: return "Warm"; case tvColorTemp_COLD: return "Cold"; case tvColorTemp_USER : return "UserDefined"; - default : return "Max"; + default : return "Standard"; } } @@ -2265,92 +2576,1694 @@ namespace Plugin { } return 0; } +//JSON Based V2 Helpers + const std::map AVOutputTV::pqModeMap = { + {PQ_MODE_SPORTS, "Sports"}, + {PQ_MODE_THEATER, "Theater"}, + {PQ_MODE_GAME, "Game"}, + {PQ_MODE_IQ, "IQ"}, + {PQ_MODE_DARK, "Dark"}, + {PQ_MODE_BRIGHT, "Bright"}, + {PQ_MODE_AIPQ, "AI PQ"}, + {PQ_MODE_STANDARD, "Standard"}, + {PQ_MODE_VIVID, "Vivid"}, + {PQ_MODE_ENERGY_SAVING, "EnergySaving"}, + {PQ_MODE_CUSTOM, "Custom"} + }; + + const std::map AVOutputTV::videoFormatMap = { + {VIDEO_FORMAT_NONE, "None"}, + {VIDEO_FORMAT_SDR, "SDR"}, + {VIDEO_FORMAT_HDR10, "HDR10"}, + {VIDEO_FORMAT_HDR10PLUS, "HDR10Plus"}, + {VIDEO_FORMAT_DV, "DV"}, + {VIDEO_FORMAT_HLG, "HLG"} + }; + + const std::map AVOutputTV::videoSrcMap = { + {VIDEO_SOURCE_COMPOSITE1, "Composite1"}, + {VIDEO_SOURCE_HDMI1, "HDMI1"}, + {VIDEO_SOURCE_HDMI2, "HDMI2"}, + {VIDEO_SOURCE_HDMI3, "HDMI3"}, + {VIDEO_SOURCE_HDMI4, "HDMI4"}, + {VIDEO_SOURCE_IP, "IP"}, + {VIDEO_SOURCE_TUNER, "Tuner"} + }; + const std::unordered_map AVOutputTV::backlightModeMap = { + {tvBacklightMode_MANUAL, "Manual"}, + {tvBacklightMode_AMBIENT, "Ambient"}, + {tvBacklightMode_ECO, "Eco"} + }; + + std::unordered_map AVOutputTV::pqModeReverseMap; + std::unordered_map AVOutputTV::videoFormatReverseMap; + std::unordered_map AVOutputTV::videoSrcReverseMap; + bool AVOutputTV::reverseMapsInitialized = false; + + void AVOutputTV::initializeReverseMaps() { + if (reverseMapsInitialized) return; + + for (const auto& entry : pqModeMap) { + pqModeReverseMap[entry.second] = static_cast(entry.first); + } + for (const auto& entry : videoFormatMap) { + videoFormatReverseMap[entry.second] = static_cast(entry.first); + } + for (const auto& entry : videoSrcMap) { + videoSrcReverseMap[entry.second] = static_cast(entry.first); + } + reverseMapsInitialized = true; + } - int AVOutputTV::ReadCapablitiesFromConf(std::string param, capDetails_t& info) - { - int ret = 0; + const std::unordered_map AVOutputTV::backlightModeReverseMap = []{ + std::unordered_map m; + for (const auto& pair : AVOutputTV::backlightModeMap) m[pair.second] = pair.first; + return m; + }(); - /*Consider User WhiteBalance as CustomWhiteBalance - To avoid clash with Factory WhiteBalance Calibration capablities*/ + std::string AVOutputTV::convertSourceIndexToStringV2(int source) { + auto it = videoSrcMap.find(source); + return (it != videoSrcMap.end()) ? it->second : ""; + } - if ( param == "WhiteBalance") { - param = "CustomWhiteBalance"; - } else if ( param == "AutoBacklightMode") { - param = "BacklightControl"; + std::string AVOutputTV::convertVideoFormatToStringV2(int format) { + auto it = videoFormatMap.find(format); + return (it != videoFormatMap.end()) ? it->second : ""; + } + + std::string AVOutputTV::convertPictureIndexToStringV2(int pqmode) { + auto it = pqModeMap.find(pqmode); + return (it != pqModeMap.end()) ? it->second : ""; + } + uint32_t AVOutputTV::generateStorageIdentifierV2(std::string &key, std::string forParam, paramIndex_t info) + { + key += AVOUTPUT_GENERIC_STRING_RFC_PARAM; + key += STRING_SOURCE + convertSourceIndexToStringV2(info.sourceIndex) + "." + + STRING_PICMODE + convertPictureIndexToStringV2(info.pqmodeIndex) + "." + + STRING_FORMAT + convertVideoFormatToStringV2(info.formatIndex) + "." + + forParam; + return tvERROR_NONE; + } + + bool AVOutputTV::isValidSource(const std::vector& sourceArray, tvVideoSrcType_t sourceIndex) + { + // If "Current" is passed, match the current source + if (std::find(sourceArray.begin(), sourceArray.end(), "Current") != sourceArray.end()) { + tvVideoSrcType_t currentSource = VIDEO_SOURCE_IP; + GetCurrentVideoSource(¤tSource); + return (sourceIndex == currentSource); } - try { - CIniFile inFile(CAPABLITY_FILE_NAME); - std::string configString; + // Match against specific source strings + const std::string srcStr = convertSourceIndexToStringV2(sourceIndex); + return std::find(sourceArray.begin(), sourceArray.end(), srcStr) != sourceArray.end(); + } - if(param == "CMS") - { - configString = param + ".color"; - info.color = inFile.Get(configString); + bool AVOutputTV::isValidFormat(const std::vector& formatArray, tvVideoFormatType_t formatIndex) + { + // If "Current" is passed, match the current format + if (std::find(formatArray.begin(), formatArray.end(), "Current") != formatArray.end()) { + tvVideoFormatType_t currentFormat = VIDEO_FORMAT_NONE; + GetCurrentVideoFormat(¤tFormat); + return (formatIndex == currentFormat); + } - configString = param + ".component"; - info.component = inFile.Get(configString); + // Match against specific format strings + const std::string fmtStr = convertVideoFormatToStringV2(formatIndex); + return std::find(formatArray.begin(), formatArray.end(), fmtStr) != formatArray.end(); + } + + tvConfigContext_t AVOutputTV::getValidContextFromGetParameters(const JsonObject& parameters, const std::string& paramName) + { + tvConfigContext_t validContext = {PQ_MODE_INVALID, VIDEO_FORMAT_NONE, VIDEO_SOURCE_ALL}; + // Picture Mode + std::string pictureModeStr; + //"Current", empty string, or missing key as a cue to fetch system values + if (!parameters.HasLabel("pictureMode") || + (pictureModeStr = parameters["pictureMode"].String()).empty() || + pictureModeStr == "Current") + { + char picMode[PIC_MODE_NAME_MAX] = {0}; + getCurrentPictureMode(picMode); + std::string pictureModeStr(picMode); + LOGINFO("Current Picture Mode: %s", picMode); + validContext.pq_mode = static_cast( + pqModeReverseMap.count(pictureModeStr) ? pqModeReverseMap.at(pictureModeStr) : PQ_MODE_INVALID + ); + } + else + { + validContext.pq_mode = static_cast( + pqModeReverseMap.count(pictureModeStr) ? pqModeReverseMap.at(pictureModeStr) : PQ_MODE_INVALID + ); + } + // Video Format + std::string videoFormatStr; + if (!parameters.HasLabel("videoFormat") || + (videoFormatStr = parameters["videoFormat"].String()).empty() || + videoFormatStr == "Current") + { + GetCurrentVideoFormat(&validContext.videoFormatType); + } + else + { + validContext.videoFormatType = static_cast( + videoFormatReverseMap.count(videoFormatStr) ? videoFormatReverseMap.at(videoFormatStr) : VIDEO_FORMAT_NONE + ); + } + // Video Source + std::string videoSourceStr; + if (!parameters.HasLabel("videoSource") || + (videoSourceStr = parameters["videoSource"].String()).empty() || + videoSourceStr == "Current") + { + GetCurrentVideoSource(&validContext.videoSrcType); + } + else + { + validContext.videoSrcType = static_cast( + videoSrcReverseMap.count(videoSourceStr) ? videoSrcReverseMap.at(videoSourceStr) : VIDEO_SOURCE_ALL + ); + } + tvContextCaps_t* caps = getCapsForParam(paramName); + LOGINFO("Looking for context: PQMode=%d, Format=%d, Source=%d", + validContext.pq_mode, validContext.videoFormatType, validContext.videoSrcType); + // Match context if caps exist + if (caps && caps->num_contexts > 0) { + for (size_t i = 0; i < caps->num_contexts; ++i) { + const tvConfigContext_t& available = caps->contexts[i]; +#if DEBUG + LOGINFO("Context[%zu]: PQMode=%d, Format=%d, Source=%d", i, + available.pq_mode, available.videoFormatType, available.videoSrcType); +#endif + if (available.videoSrcType == validContext.videoSrcType && + available.videoFormatType == validContext.videoFormatType && + available.pq_mode == validContext.pq_mode) { + return available; // valid context found + } } + } + LOGWARN("No valid context found for %s with provided parameters", paramName.c_str()); + validContext = {PQ_MODE_INVALID, VIDEO_FORMAT_NONE, VIDEO_SOURCE_ALL}; + return validContext; + } - if(param == "CustomWhiteBalance") - { - configString = param + ".color"; - info.color = inFile.Get(configString); + bool AVOutputTV::isGlobalParam(const JsonArray& arr) { + return (arr.Length() == 0) || + (arr.Length() == 1 && ( + arr[0].String() == "Global" || arr[0].String() == "none")); + } - configString = param + ".control"; - info.control = inFile.Get(configString); + std::vector AVOutputTV::extractPQModes(const JsonObject& parameters) { + initializeReverseMaps(); - } + std::vector pqModes; + if (!parameters.HasLabel("pictureMode")) { + return pqModes; + } - if ((param == "DolbyVisionMode") || (param == "Backlight") || (param == "CMS") || (param == "CustomWhiteBalance") || (param == "HDRMode") || (param == "BacklightControl") || (param == "DimmingMode")) { - configString = param + ".platformsupport"; - info.isPlatformSupport = inFile.Get(configString); - printf(" platformsupport : %s\n",info.isPlatformSupport.c_str() ); + JsonArray pqmodeArray = parameters["pictureMode"].Array(); + pqModes.reserve(pqmodeArray.Length()); // Pre-allocate + + for (uint32_t i = 0; i < pqmodeArray.Length(); ++i) { + std::string modeStr = pqmodeArray[i].String(); + + if (modeStr == "Current") { + char picMode[PIC_MODE_NAME_MAX] = {0}; + if (getCurrentPictureMode(picMode)) { + auto it = pqModeReverseMap.find(std::string(picMode)); + if (it != pqModeReverseMap.end()) { + pqModes.push_back(it->second); + } + } + } else { + auto it = pqModeReverseMap.find(modeStr); + if (it != pqModeReverseMap.end()) { + pqModes.push_back(it->second); + } } + } + return pqModes; + } - if ( (param == "ColorTemperature") || (param == "DimmingMode") || - ( param == "BacklightControl") || (param == "DolbyVisionMode") || - (param == "HDR10Mode") || (param == "HLGMode") || (param == "AspectRatio") || - (param == "PictureMode") || (param == "VideoSource") || (param == "VideoFormat") || - (param == "VideoFrameRate") || (param == "HDRMode") ) { - configString = param + ".range"; - info.range = inFile.Get(configString); - printf(" String Range info : %s\n",info.range.c_str() ); - } else if ( (param == "CMS" )) { - configString.clear(); - configString = param + ".range_Saturation_from"; - info.range = inFile.Get(configString); - configString = param + ".range_Saturation_to"; - info.range += ","+inFile.Get(configString); + std::vector AVOutputTV::extractVideoSources(const JsonObject& parameters) { + initializeReverseMaps(); - configString = param + ".range_Hue_from"; - info.range += ","+inFile.Get(configString); - configString = param + ".range_Hue_to"; - info.range += ","+inFile.Get(configString); + std::vector sources; + if (!parameters.HasLabel("videoSource")) { + return sources; + } - configString = param + ".range_Luma_from"; - info.range += ","+inFile.Get(configString); - configString = param + ".range_Luma_to"; - info.range += ","+inFile.Get(configString); - } else if ( (param == "CustomWhiteBalance")) { - configString = param + ".range_Gain_from"; - info.range = inFile.Get(configString); - configString = param + ".range_Gain_to"; - info.range += ","+inFile.Get(configString); + JsonArray sourceArray = parameters["videoSource"].Array(); + sources.reserve(sourceArray.Length()); // Pre-allocate - configString = param + ".range_Offset_from"; - info.range += ","+inFile.Get(configString); - configString = param + ".range_Offset_to"; - info.range += ","+inFile.Get(configString); + for (uint32_t i = 0; i < sourceArray.Length(); ++i) { + std::string srcStr = sourceArray[i].String(); + + if (srcStr == "Current") { + tvVideoSrcType_t sourceIndex = VIDEO_SOURCE_IP; + if (GetCurrentVideoSource(&sourceIndex) == tvERROR_NONE) { + sources.push_back(sourceIndex); + } } else { - configString = param + ".range_from"; - info.range = inFile.Get(configString); - configString = param + ".range_to"; - info.range += ","+inFile.Get(configString); - printf(" Integer Range Info : %s\n",info.range.c_str() ); + auto it = videoSrcReverseMap.find(srcStr); + if (it != videoSrcReverseMap.end()) { + sources.push_back(it->second); + } } + } + return sources; + } - if ((param == "VideoSource") || (param == "PictureMode") || (param == "VideoFormat") ) { + std::vector AVOutputTV::extractVideoFormats(const JsonObject& parameters) { + initializeReverseMaps(); + + std::vector formats; + if (!parameters.HasLabel("videoFormat")) { + return formats; + } + + JsonArray formatArray = parameters["videoFormat"].Array(); + formats.reserve(formatArray.Length()); // Pre-allocate + + for (uint32_t i = 0; i < formatArray.Length(); ++i) { + std::string fmtStr = formatArray[i].String(); + + if (fmtStr == "Current") { + tvVideoFormatType_t formatIndex = VIDEO_FORMAT_NONE; + GetCurrentVideoFormat(&formatIndex); + if (formatIndex == VIDEO_FORMAT_NONE) { + formatIndex = VIDEO_FORMAT_SDR; + } + formats.push_back(formatIndex); + } else { + auto it = videoFormatReverseMap.find(fmtStr); + if (it != videoFormatReverseMap.end()) { + formats.push_back(it->second); + } + } + } + return formats; + } + + JsonArray AVOutputTV::getJsonArrayIfArray(const JsonObject& obj, const std::string& key) { + return (obj.HasLabel(key.c_str()) && obj[key.c_str()].Content() == JsonValue::type::ARRAY) + ? obj[key.c_str()].Array() + : JsonArray(); // returns empty array + } + + tvContextCaps_t* AVOutputTV::getCapsForParam(const std::string& paramName) + { + tvContextCaps_t* caps = nullptr; + if (paramName == "Backlight") caps = m_backlightCaps; + else if (paramName == "Brightness") caps = m_brightnessCaps; + else if (paramName == "Contrast") caps = m_contrastCaps; + else if (paramName == "Sharpness") caps = m_sharpnessCaps; + else if (paramName == "Saturation") caps = m_saturationCaps; + else if (paramName == "Hue") caps = m_hueCaps; + else if (paramName == "ColorTemp") caps = m_colortempCaps; + else if (paramName == "DimmingMode") caps = m_dimmingModeCaps; + else if (paramName == "PictureMode") caps = m_pictureModeCaps; + else if (paramName == "AspectRatio") caps = m_aspectRatioCaps; + else if (paramName == "LowLatencyState") caps = m_lowLatencyStateCaps; + else if (paramName == "PrecisionDetail") caps = m_precisionDetailCaps; + else if (paramName == "LocalContrastEnhancement") caps = m_localContrastEnhancementCaps; + else if (paramName == "MPEGNoiseReduction") caps = m_MPEGNoiseReductionCaps; + else if (paramName == "DigitalNoiseReduction") caps = m_digitalNoiseReductionCaps; + else if (paramName == "AISuperResolution") caps = m_AISuperResolutionCaps; + else if (paramName == "MEMC") caps = m_MEMCCaps; + else if (paramName == "BacklightMode") caps = m_backlightModeCaps; + else if (paramName == "CMS") caps = m_cmsCaps; + else { + LOGERR("Unknown ParamName: %s", paramName.c_str()); + return nullptr; + } + // Fallback to global pictureModeCaps if cap is empty + if (!caps || caps->num_contexts == 0) + caps = m_pictureModeCaps; + + return caps; + } + std::string AVOutputTV::getCurrentPictureModeAsString() { + char picMode[PIC_MODE_NAME_MAX] = {0}; + if (!getCurrentPictureMode(picMode)) { + LOGERR("Failed to get current picture mode"); + return ""; + } + return picMode; + } + + std::string AVOutputTV::getCurrentVideoSourceAsString() { + tvVideoSrcType_t sourceIndex = VIDEO_SOURCE_IP; + if (GetCurrentVideoSource(&sourceIndex) != tvERROR_NONE) { + LOGERR("GetCurrentVideoSource failed"); + return ""; + } + return convertSourceIndexToStringV2(sourceIndex); + } + + std::string AVOutputTV::getCurrentVideoFormatAsString() { + tvVideoFormatType_t formatIndex = VIDEO_FORMAT_NONE; + if (GetCurrentVideoFormat(&formatIndex) != tvERROR_NONE || formatIndex == VIDEO_FORMAT_NONE) { + formatIndex = VIDEO_FORMAT_SDR; + } + return convertVideoFormatToStringV2(formatIndex); + } + + bool AVOutputTV::isSetRequiredForParam(const JsonObject& parameters, const std::string& paramName) + { + // Get current state once + const std::string curPicMode = getCurrentPictureModeAsString(); + const std::string curSource = getCurrentVideoSourceAsString(); + const std::string curFormat = getCurrentVideoFormatAsString(); + + // Helper to resolve a parameter to a list of effective values + auto resolveParam = [&](const std::string& label, const std::string& currentValue) -> std::vector { + std::vector result; + + if (!parameters.HasLabel(label.c_str())){ + result.push_back(currentValue); + return result; + } + + const auto& array = parameters[label.c_str()].Array(); + if (array.Length() == 0){ + result.push_back(currentValue); + return result; + } + + for (uint16_t i = 0; i < array.Length(); ++i) { + const std::string val = array[i].String(); + if (val == "Current" || val == "Global" || val == "none") { + result.push_back(currentValue); + } else { + result.push_back(val); + } + } + return result; + }; + + // Resolve all + const auto resolvedPicModes = resolveParam("pictureMode", curPicMode); + const auto resolvedFormats = resolveParam("videoFormat", curFormat); + const auto resolvedSources = resolveParam("videoSource", curSource); +#if DEBUG + // Helper function to log vector content + auto logResolvedValues = [&](const std::string& label, const std::vector& values) { + std::string joined; + for (const auto& val : values) { + if (!joined.empty()) joined += ", "; + joined += val; + } + LOGINFO("Resolved %s: [%s]", label.c_str(), joined.c_str()); + }; + + // Debug logs + logResolvedValues("pictureMode", resolvedPicModes); + logResolvedValues("videoSource", resolvedSources); + logResolvedValues("videoFormat", resolvedFormats); +#endif + + // Check if current combination exists in resolved sets + for (const auto& pm : resolvedPicModes) { + if (pm != curPicMode) continue; + + for (const auto& fmt : resolvedFormats) { + if (fmt != curFormat) continue; + + for (const auto& src : resolvedSources) { + if (src == curSource) { + tvContextCaps_t* caps = getCapsForParam(paramName); + if (!caps) { + LOGERR("No caps found for param: %s", paramName.c_str()); + return false; + } + for (size_t i = 0; i < caps->num_contexts; ++i) { + const tvConfigContext_t& ctx = caps->contexts[i]; + std::string capPicMode = convertPictureIndexToStringV2(ctx.pq_mode); + std::string capSource = convertSourceIndexToStringV2(ctx.videoSrcType); + std::string capFormat = convertVideoFormatToStringV2(ctx.videoFormatType); + if ((capPicMode == curPicMode) && + (capSource == curSource) && + (capFormat == curFormat)) + { + // Log the matched combination + LOGINFO("isSetRequiredForParam: matched combination - pictureMode: %s, videoFormat: %s, videoSource: %s", + pm.c_str(), fmt.c_str(), src.c_str()); + return true; + } + } + } + } + } + } + + return false; + } + std::string AVOutputTV::getCMSNameFromEnum(tvDataComponentColor_t colorEnum) + { + switch (colorEnum) { + case tvDataColor_RED: return "Red"; + case tvDataColor_GREEN: return "Green"; + case tvDataColor_BLUE: return "Blue"; + case tvDataColor_CYAN: return "Cyan"; + case tvDataColor_YELLOW: return "Yellow"; + case tvDataColor_MAGENTA: return "Magenta"; + default: return "Unknown"; + } + } + std::vector AVOutputTV::getValidContextsFromParameters(const JsonObject& parameters, const std::string& tr181ParamName) + { + std::vector validContexts; + tvContextCaps_t* caps = getCapsForParam(tr181ParamName); + + if (caps == nullptr || caps->contexts == nullptr) { + LOGWARN("Caps or contexts is null for parameter: %s", tr181ParamName.c_str()); + return validContexts; + } + + // Create a hash set of available contexts for O(1) lookup instead of O(n) linear search + std::unordered_set availableContextsSet; + for (size_t i = 0; i < caps->num_contexts; ++i) { + const auto& ctx = caps->contexts[i]; + std::string key = std::to_string(ctx.pq_mode) + "_" + + std::to_string(ctx.videoFormatType) + "_" + + std::to_string(ctx.videoSrcType); + availableContextsSet.insert(key); + } + + JsonArray pqmodeArray = getJsonArrayIfArray(parameters, "pictureMode"); + JsonArray sourceArray = getJsonArrayIfArray(parameters, "videoSource"); + JsonArray formatArray = getJsonArrayIfArray(parameters, "videoFormat"); + + std::vector pqModes = extractPQModes(parameters); + std::vector sources = extractVideoSources(parameters); + std::vector formats = extractVideoFormats(parameters); + + // Handle global parameters - collect unique values to avoid duplicates + std::unordered_set pqModeSet(pqModes.begin(), pqModes.end()); + std::unordered_set sourceSet(sources.begin(), sources.end()); + std::unordered_set formatSet(formats.begin(), formats.end()); + + if (isGlobalParam(pqmodeArray)) { + for (size_t i = 0; i < caps->num_contexts; ++i) { + pqModeSet.insert(caps->contexts[i].pq_mode); + } + } + if (isGlobalParam(sourceArray)) { + for (size_t i = 0; i < caps->num_contexts; ++i) { + sourceSet.insert(caps->contexts[i].videoSrcType); + } + } + if (isGlobalParam(formatArray)) { + for (size_t i = 0; i < caps->num_contexts; ++i) { + formatSet.insert(caps->contexts[i].videoFormatType); + } + } + + if (pqModeSet.empty() || sourceSet.empty() || formatSet.empty()) { + LOGWARN("One or more parameter sets are empty: PQModes[%zu], Sources[%zu], Formats[%zu]", + pqModeSet.size(), sourceSet.size(), formatSet.size()); + return validContexts; + } + + std::unordered_set seenContexts; + validContexts.reserve(pqModeSet.size() * sourceSet.size() * formatSet.size()); // Pre-allocate memory + + // Generate contexts and check validity in single pass + for (const auto& pq : pqModeSet) { + for (const auto& fmt : formatSet) { + for (const auto& src : sourceSet) { + std::string contextKey = std::to_string(pq) + "_" + + std::to_string(fmt) + "_" + + std::to_string(src); + + if (seenContexts.find(contextKey) != seenContexts.end()) { + continue; + } + + if (availableContextsSet.find(contextKey) != availableContextsSet.end()) { + tvConfigContext_t testCtx = { pq, fmt, src }; + validContexts.push_back(testCtx); + seenContexts.insert(contextKey); + } + } + } + } + + // Sort only if we have results to sort + if (!validContexts.empty()) { + std::sort(validContexts.begin(), validContexts.end(), + [](const tvConfigContext_t& a, const tvConfigContext_t& b) { + return std::tie(a.pq_mode, a.videoFormatType, a.videoSrcType) < + std::tie(b.pq_mode, b.videoFormatType, b.videoSrcType); + }); + } + + return validContexts; + } + + int AVOutputTV::updateAVoutputTVParamV2(std::string action, std::string tr181ParamName, + const JsonObject& parameters, + tvPQParameterIndex_t pqParamIndex,int level) + { +#if DEBUG + LOGINFO("Entry %s: Action: %s, Param: %s, Level: %d", __FUNCTION__, action.c_str(), tr181ParamName.c_str(), level); +#endif + int ret = 0; + const bool isSet = (action == "set"); + const bool isReset = (action == "reset"); + const bool isSync = (action == "sync"); + + std::vector validContexts = getValidContextsFromParameters(parameters, tr181ParamName); + LOGINFO("%s: Number of validContexts = %zu", __FUNCTION__, validContexts.size()); +#if DEBUG + for (const auto& ctx : validContexts) { + + std::string pqStr = pqModeMap.count(ctx.pq_mode) ? pqModeMap.at(ctx.pq_mode) : std::to_string(ctx.pq_mode); + std::string fmtStr = videoFormatMap.count(ctx.videoFormatType) ? videoFormatMap.at(ctx.videoFormatType) : std::to_string(ctx.videoFormatType); + std::string srcStr = videoSrcMap.count(ctx.videoSrcType) ? videoSrcMap.at(ctx.videoSrcType) : std::to_string(ctx.videoSrcType); + LOGINFO("Valid Context - PQMode: %s, Format: %s, Source: %s", pqStr.c_str(), fmtStr.c_str(), srcStr.c_str()); + } +#endif + if (validContexts.empty()) { + LOGWARN("%s: No valid contexts found for parameters", __FUNCTION__); + return (int)tvERROR_GENERAL; + } + if (tr181ParamName == "CMS") { + JsonArray colorArray = getJsonArrayIfArray(parameters, "color"); + JsonArray componentArray = getJsonArrayIfArray(parameters, "component"); + + std::vector colors, components; + + for (size_t i = 0; i < colorArray.Length(); ++i) + colors.emplace_back(colorArray[i].String()); + + for (size_t i = 0; i < componentArray.Length(); ++i) + components.emplace_back(componentArray[i].String()); + + if (colors.empty()) colors.push_back("Global"); + if (components.empty()) components.push_back("Global"); + + if (colors.size() == 1 && colors[0] == "Global") + colors = m_cmsColorList; + + if (components.size() == 1 && components[0] == "Global") + components = m_cmsComponentList; + + for (const auto& ctx : validContexts) { + for (const auto& colorStr : colors) { + for (const auto& componentStr : components) { +#if DEBUG + LOGINFO("%s: Processing Color: %s, Component: %s", __FUNCTION__, colorStr.c_str(), componentStr.c_str()); +#endif + tvPQParameterIndex_t pqIndex; + if (convertCMSParamToPQEnum(componentStr, colorStr, pqIndex) != 0) { + LOGERR("%s: convertCMSParamToPQEnum failed for color: %s, component: %s", + __FUNCTION__, colorStr.c_str(), componentStr.c_str()); + ret |= 1; + continue; + } + tvDataComponentColor_t colorValue = tvDataColor_NONE; + if ( getCMSColorEnumFromString(colorStr, colorValue ) == -1 ) { + LOGERR("%s : getCMSColorEnumFromString failed for color: %s", __FUNCTION__, colorStr.c_str()); + ret |= 2; + continue; + } + tvComponentType_t componentValue; + if ( getCMSComponentEnumFromString(componentStr, componentValue ) == -1 ) { + LOGERR("%s : getCMSComponentEnumFromString failed for component: %s", __FUNCTION__, componentStr.c_str()); + ret |= 4; + continue; + } + if (std::find(m_cmsColorList.begin(), m_cmsColorList.end(), colorStr) == m_cmsColorList.end()) { + LOGERR("%s: Color '%s' is not supported as per capabilities", __FUNCTION__, colorStr.c_str()); + ret |= 8; + continue; + } + if (std::find(m_cmsComponentList.begin(), m_cmsComponentList.end(), componentStr) == m_cmsComponentList.end()) { + LOGERR("%s: Component '%s' is not supported as per capabilities", __FUNCTION__, componentStr.c_str()); + ret |= 16; + continue; + } + paramIndex_t paramIndex; + paramIndex.sourceIndex = static_cast(ctx.videoSrcType); + paramIndex.pqmodeIndex = static_cast(ctx.pq_mode); + paramIndex.formatIndex = static_cast(ctx.videoFormatType); + paramIndex.componentIndex = static_cast(componentValue); + paramIndex.colorIndex = static_cast(colorValue); + paramIndex.colorTempIndex = 0; + paramIndex.controlIndex = 0; + + int value = 0; + if (isReset) { + ret |= updateAVoutputTVParamToHAL(tr181ParamName, paramIndex, 0, false); + level = 0; + } + + if (isSync || isReset) { + if (getLocalparam(tr181ParamName, paramIndex, value, pqIndex, isSync) == 0) { + level = value; + } else { + LOGWARN("%s: Skipping sync for color: %s, component: %s", + __FUNCTION__, colorStr.c_str(), componentStr.c_str()); + continue; + } + } + ret |= SaveCMS(static_cast(paramIndex.sourceIndex), + paramIndex.pqmodeIndex, + static_cast(paramIndex.formatIndex), + static_cast(paramIndex.componentIndex), + static_cast(paramIndex.colorIndex), + level); + + if (isSet) { + ret |= updateAVoutputTVParamToHAL(tr181ParamName, paramIndex, level, true); + } + } + } + } + LOGINFO("Exit: %s, Return Value: %d", __FUNCTION__, ret); + return (ret < 0) ? -1 : 0; + } + for (const auto& ctx : validContexts) + { + paramIndex_t paramIndex { + .sourceIndex = static_cast(ctx.videoSrcType), + .pqmodeIndex = static_cast(ctx.pq_mode), + .formatIndex = static_cast(ctx.videoFormatType) + }; + std::string pqStr = pqModeMap.count(ctx.pq_mode) ? pqModeMap.at(ctx.pq_mode) : std::to_string(ctx.pq_mode); + std::string fmtStr = videoFormatMap.count(ctx.videoFormatType) ? videoFormatMap.at(ctx.videoFormatType) : std::to_string(ctx.videoFormatType); + std::string srcStr = videoSrcMap.count(ctx.videoSrcType) ? videoSrcMap.at(ctx.videoSrcType) : std::to_string(ctx.videoSrcType); + + if (isSet) + { + ret |= updateAVoutputTVParamToHALV2(tr181ParamName, paramIndex, level, true); + } + else + { + if (isReset) + { + ret |= updateAVoutputTVParamToHALV2(tr181ParamName, paramIndex, level, false); + } + if(getLocalparam(tr181ParamName,paramIndex,level,pqParamIndex,isSync)) + { + continue; + } + } + switch (pqParamIndex) + { + case PQ_PARAM_BRIGHTNESS: + ret |= SaveBrightness((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_CONTRAST: + ret |= SaveContrast((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_SHARPNESS: + ret |= SaveSharpness((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_HUE: + ret |= SaveHue((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_SATURATION: + ret |= SaveSaturation((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_COLOR_TEMPERATURE: + ret |= SaveColorTemperature((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,(tvColorTemp_t)level); + break; + case PQ_PARAM_BACKLIGHT: + ret |= SaveBacklight((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_DIMMINGMODE: + ret |= SaveTVDimmingMode((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,(tvDimmingMode_t)level); + break; + case PQ_PARAM_LOWLATENCY_STATE: + ret |= SaveLowLatencyState((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,level); + break; + case PQ_PARAM_DOLBY_MODE: + ret |= SaveTVDolbyVisionMode((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,(tvDolbyMode_t)level); + break; + case PQ_PARAM_ASPECT_RATIO: + ret |= SaveAspectRatio((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,(tvDisplayMode_t)level); + break; + case PQ_PARAM_PRECISION_DETAIL: + #if HAL_NOT_READY + #else + ret |= SetPrecisionDetail((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + level); + #endif + break; + + case PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT: + #if HAL_NOT_READY + #else + #if ENABLE_PQ_PARAM + ret |= SetLocalContrastEnhancement((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + level); + #endif + #endif + break; + + case PQ_PARAM_MPEG_NOISE_REDUCTION: + #if HAL_NOT_READY + #else + #if ENABLE_PQ_PARAM + ret |= SetMPEGNoiseReduction((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + level); + #endif + #endif + break; + + case PQ_PARAM_DIGITAL_NOISE_REDUCTION: + #if HAL_NOT_READY + #else + #if ENABLE_PQ_PARAM + ret |= SetDigitalNoiseReduction((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + level); + #endif + #endif + break; + + case PQ_PARAM_AI_SUPER_RESOLUTION: + #if HAL_NOT_READY + #else + ret |= SetAISuperResolution((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + level); + #endif + break; + + case PQ_PARAM_MEMC: + #if HAL_NOT_READY + #else + ret |= SetMEMC((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + level); + #endif + break; + #if HAL_NOT_READY + #else + case PQ_PARAM_BACKLIGHT_MODE: + ret |= SaveBacklightMode((tvVideoSrcType_t)paramIndex.sourceIndex, + (tvPQModeIndex_t)paramIndex.pqmodeIndex, + (tvVideoFormatType_t)paramIndex.formatIndex, + static_cast(level)); + #endif + break; + case PQ_PARAM_HDR10_MODE: + case PQ_PARAM_HLG_MODE: + case PQ_PARAM_LDIM: + case PQ_PARAM_LOCALDIMMING_LEVEL: + + case PQ_PARAM_WB_GAIN_RED: + case PQ_PARAM_WB_GAIN_GREEN: + case PQ_PARAM_WB_GAIN_BLUE: + case PQ_PARAM_WB_OFFSET_RED: + case PQ_PARAM_WB_OFFSET_GREEN: + case PQ_PARAM_WB_OFFSET_BLUE: + // TODO: Add implementation + break; + + default: + // Prevent compiler warning for unhandled enums + LOGWARN("Unhandled PQ parameter index: %d", pqParamIndex); + break; + } + } + LOGINFO("Exit: %s, Return Value: %d", __FUNCTION__, ret); + return ret; + } + +tvError_t AVOutputTV::ReadJsonFile(JsonObject& root) { + std::ifstream file(CAPABLITY_FILE_NAMEV2); + if (!file.is_open()) { + LOGWARN("AVOutputPlugins: %s: Unable to open file", __FUNCTION__); + return tvERROR_GENERAL; + } + + std::string jsonStr((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + file.close(); + + if (!root.FromString(jsonStr)) { + LOGWARN("AVOutputPlugins: %s: JSON parsing failed", __FUNCTION__); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +tvError_t AVOutputTV::ExtractRangeInfo(const JsonObject& data, int* max_value) { + if (!data.HasLabel("rangeInfo")) { + LOGWARN("AVOutputPlugins: %s: 'rangeInfo' not available", __FUNCTION__); + return tvERROR_NONE; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + if (rangeInfo.HasLabel("to")) { + if (!max_value) { + LOGWARN("AVOutputPlugins: %s: NULL input param max_value", __FUNCTION__); + return tvERROR_INVALID_PARAM; + } + *max_value = rangeInfo["to"].Number(); + return tvERROR_NONE; + } + + LOGWARN("AVOutputPlugins: %s: Invalid 'rangeInfo' format", __FUNCTION__); + return tvERROR_GENERAL; +} + +tvError_t AVOutputTV::ExtractContextCaps(const JsonObject& data, tvContextCaps_t** context_caps) { + if (!context_caps) { + LOGWARN("AVOutputPlugins: %s: NULL input param", __FUNCTION__); + return tvERROR_INVALID_PARAM; + } + + if (!data.HasLabel("context")) { + LOGWARN("AVOutputPlugins: %s: 'context' missing", __FUNCTION__); + return tvERROR_GENERAL; + } + + JsonObject context = data["context"].Object(); + if (!context.IsSet()) { + LOGWARN("AVOutputPlugins: %s: Context is not set", __FUNCTION__); + return tvERROR_GENERAL; + } + + std::vector contexts = ParseContextCaps(context); + *context_caps = AllocateContextCaps(contexts); + if (!*context_caps) { + LOGWARN("AVOutputPlugins: %s: Memory allocation failed", __FUNCTION__); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} +template +bool LookupEnum(const std::string& str, const std::map& map, EnumType& outEnum) { + for (const auto& entry : map) { + if (entry.second == str) { + outEnum = static_cast(entry.first); + return true; + } + } + return false; +} + +std::vector AVOutputTV::ParseContextCaps(const JsonObject& context) +{ + std::vector contexts; + std::set> seen; + + WPEFramework::Core::JSON::VariantContainer::Iterator modeIterator = context.Variants(); + while (modeIterator.Next()) { + std::string modeStr = modeIterator.Label(); + + tvPQModeIndex_t modeEnum; + if (!LookupEnum(modeStr, pqModeMap, modeEnum)) continue; + + const auto& modeValue = context[modeStr.c_str()]; + if (!modeValue.IsSet() || modeValue.Content() != WPEFramework::Core::JSON::Variant::type::OBJECT) continue; + + JsonObject formatMap = modeValue.Object(); + WPEFramework::Core::JSON::VariantContainer::Iterator formatIterator = formatMap.Variants(); + while (formatIterator.Next()) { + std::string formatStr = formatIterator.Label(); + + tvVideoFormatType_t fmtEnum; + if (!LookupEnum(formatStr, videoFormatMap, fmtEnum)) continue; + + const auto& formatValue = formatMap[formatStr.c_str()]; + if (!formatValue.IsSet() || formatValue.Content() != WPEFramework::Core::JSON::Variant::type::ARRAY) continue; + + JsonArray sources = formatValue.Array(); + for (uint32_t i = 0; i < sources.Length(); ++i) { + std::string srcStr = sources[i].String(); + + tvVideoSrcType_t srcEnum; + if (!LookupEnum(srcStr, videoSrcMap, srcEnum)) continue; + + auto triplet = std::make_tuple(modeEnum, fmtEnum, srcEnum); + if (seen.find(triplet) == seen.end()) { + contexts.push_back({modeEnum, fmtEnum, srcEnum}); + seen.insert(triplet); + } + } + } + } + + return contexts; +} + +tvContextCaps_t* AVOutputTV::AllocateContextCaps(const std::vector& contexts) { + tvContextCaps_t* context_caps = new (std::nothrow) tvContextCaps_t; + if (!context_caps) { + return nullptr; + } + + context_caps->num_contexts = contexts.size(); + context_caps->contexts = contexts.empty() ? nullptr : new (std::nothrow) tvConfigContext_t[contexts.size()]; + + if (!contexts.empty() && !context_caps->contexts) { + delete context_caps; + return nullptr; + } + + if (!contexts.empty()) { + std::copy(contexts.begin(), contexts.end(), context_caps->contexts); + } + return context_caps; +} + +tvError_t AVOutputTV::GetCaps(const std::string& key, int* max_value, tvContextCaps_t** context_caps) { + LOGINFO("Entry\n"); + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + if (ExtractRangeInfo(data, max_value) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +tvError_t AVOutputTV::GetDVCalibrationCaps(tvDVCalibrationSettings_t **min_values, tvDVCalibrationSettings_t **max_values, tvContextCaps_t **context_caps) { + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + if (!root.HasLabel("DolbyVisionCalibration")) { + LOGWARN("AVOutputPlugins: %s: Missing 'DolbyVisionCalibration' label", __FUNCTION__); + return tvERROR_GENERAL; + } + + JsonObject data = root["DolbyVisionCalibration"].Object(); + *min_values = new tvDVCalibrationSettings_t(); + *max_values = new tvDVCalibrationSettings_t(); + + std::map keyMap = { + {"Tmax", &tvDVCalibrationSettings_t::Tmax}, + {"Tmin", &tvDVCalibrationSettings_t::Tmin}, + {"Tgamma", &tvDVCalibrationSettings_t::Tgamma}, + {"Rx", &tvDVCalibrationSettings_t::Rx}, + {"Ry", &tvDVCalibrationSettings_t::Ry}, + {"Gx", &tvDVCalibrationSettings_t::Gx}, + {"Gy", &tvDVCalibrationSettings_t::Gy}, + {"Bx", &tvDVCalibrationSettings_t::Bx}, + {"By", &tvDVCalibrationSettings_t::By}, + {"Wx", &tvDVCalibrationSettings_t::Wx}, + {"Wy", &tvDVCalibrationSettings_t::Wy} + }; + + for (auto it = keyMap.begin(); it != keyMap.end(); ++it) { + const std::string& key = it->first; + double tvDVCalibrationSettings_t::*member = it->second; + std::string minKey = "range" + key; + if (data.HasLabel(minKey.c_str())) { + JsonObject range = data[minKey.c_str()].Object(); + (*min_values)->*member = range["from"].Number(); + (*max_values)->*member = range["to"].Number(); + } + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + return tvERROR_NONE; +} + +tvError_t AVOutputTV::GetBacklightModeCaps(tvBacklightMode_t** backlight_mode, size_t* num_backlight_mode, tvContextCaps_t** context_caps) +{ + LOGINFO("Entry\n"); + + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + std::string key = "BacklightMode"; + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + JsonArray optionsArray = rangeInfo["options"].Array(); + + *num_backlight_mode = optionsArray.Length(); + *backlight_mode = static_cast(malloc(*num_backlight_mode * sizeof(tvBacklightMode_t))); + if (!(*backlight_mode)) { + return tvERROR_GENERAL; + } + + for (size_t i = 0; i < *num_backlight_mode; ++i) { + std::string modeStr = optionsArray[i].String(); + auto it = backlightModeReverseMap.find(modeStr); + if (it != backlightModeReverseMap.end()) { + (*backlight_mode)[i] = static_cast (it->second); + } else { + (*backlight_mode)[i] = tvBacklightMode_INVALID; + } + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + free(*backlight_mode); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +// LocalContrastEnhancement +tvError_t AVOutputTV::GetLocalContrastEnhancementCaps(int * maxLocalContrastEnhancement, tvContextCaps_t ** context_caps) { + return GetCaps("LocalContrastEnhancement", maxLocalContrastEnhancement, context_caps); +} + +// MPEGNoiseReduction +tvError_t AVOutputTV::GetMPEGNoiseReductionCaps(int * maxMPEGNoiseReduction, tvContextCaps_t ** context_caps) { + return GetCaps("MPEGNoiseReduction", maxMPEGNoiseReduction, context_caps); +} + +// DigitalNoiseReduction +tvError_t AVOutputTV::GetDigitalNoiseReductionCaps(int * maxDigitalNoiseReduction, tvContextCaps_t ** context_caps) { + return GetCaps("DigitalNoiseReduction", maxDigitalNoiseReduction, context_caps); +} + +tvError_t AVOutputTV::GetMultiPointWBCaps(int* num_hal_matrix_points, + int* rgb_min, + int* rgb_max, + int* num_ui_matrix_points, + double** ui_matrix_positions, + tvContextCaps_t** context_caps) +{ + if (!num_hal_matrix_points || !rgb_min || !rgb_max || + !num_ui_matrix_points || !ui_matrix_positions || !context_caps) + return tvERROR_INVALID_PARAM; + + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) + return tvERROR_GENERAL; + + const std::string key = "MultiPointWB"; + if (!root.HasLabel(key.c_str())) + return tvERROR_OPERATION_NOT_SUPPORTED; + + JsonObject data = root[key.c_str()].Object(); + + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) + return tvERROR_OPERATION_NOT_SUPPORTED; + + // Extract matrix points + if (!data.HasLabel("points")) + return tvERROR_INVALID_PARAM; + *num_hal_matrix_points = data["points"].Number(); + + // Extract range info + if (!data.HasLabel("rangeInfo")) + return tvERROR_INVALID_PARAM; + + JsonObject range = data["rangeInfo"].Object(); + if (!range.HasLabel("from") || !range.HasLabel("to")) + return tvERROR_INVALID_PARAM; + + *rgb_min = range["from"].Number(); + *rgb_max = range["to"].Number(); + + // Allocate UI matrix points (same count for now) + *num_ui_matrix_points = *num_hal_matrix_points; + *ui_matrix_positions = new double[*num_ui_matrix_points]; + if (!(*ui_matrix_positions)) + return tvERROR_GENERAL; + + for (int i = 0; i < *num_ui_matrix_points; ++i) + (*ui_matrix_positions)[i] = static_cast(i) / (*num_ui_matrix_points - 1); + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) + return tvERROR_GENERAL; + + return tvERROR_NONE; +} + +tvError_t AVOutputTV::GetCMSCaps(int* max_hue, + int* max_saturation, + int* max_luma, + tvDataComponentColor_t** color, + tvComponentType_t** component, + size_t* num_color, + size_t* num_component, + tvContextCaps_t** context_caps) +{ + if (!max_hue || !max_saturation || !max_luma || !color || !component || !num_color || !num_component || !context_caps) { + return tvERROR_INVALID_PARAM; + } + + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + const char* key = "CMS"; + if (!root.HasLabel(key)) { + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject cms = root[key].Object(); + + if (!cms.HasLabel("platformSupport") || !cms["platformSupport"].Boolean()) { + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + // Extract ranges + *max_hue = cms.HasLabel("rangeHue") ? cms["rangeHue"].Object()["to"].Number() : 0; + *max_saturation = cms.HasLabel("rangeSaturation") ? cms["rangeSaturation"].Object()["to"].Number() : 0; + *max_luma = cms.HasLabel("rangeLuma") ? cms["rangeLuma"].Object()["to"].Number() : 0; + + // Extract colors + const JsonArray& colorArray = cms["color"].Array(); + *num_color = colorArray.Length(); + *color = new tvDataComponentColor_t[*num_color]; + for (size_t i = 0; i < *num_color; ++i) { + std::string colorStr = colorArray[i].String(); + if (getCMSColorEnumFromString(colorStr, (*color)[i]) != 0) { + delete[] *color; + *color = nullptr; + return tvERROR_INVALID_PARAM; + } + } + + // Extract components + const JsonArray& compArray = cms["component"].Array(); + *num_component = compArray.Length(); + *component = new tvComponentType_t[*num_component]; + for (size_t i = 0; i < *num_component; ++i) { + std::string compStr = compArray[i].String(); + if (getCMSComponentEnumFromString(compStr, (*component)[i]) != 0) { + delete[] *color; + delete[] *component; + *color = nullptr; + *component = nullptr; + return tvERROR_INVALID_PARAM; + } + } + + // Extract context capabilities + if (ExtractContextCaps(cms, context_caps) != tvERROR_NONE) { + delete[] *color; + delete[] *component; + *color = nullptr; + *component = nullptr; + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +tvError_t AVOutputTV::GetCustom2PointWhiteBalanceCaps(int* min_gain, int* min_offset, + int* max_gain, int* max_offset, + tvWBColor_t** color, + tvWBControl_t** control, + size_t* num_color, size_t* num_control, + tvContextCaps_t** context_caps) +{ + if (!min_gain || !min_offset || !max_gain || !max_offset || + !color || !control || !num_color || !num_control || !context_caps) + { + LOGERR("Invalid input pointers"); + return tvERROR_INVALID_PARAM; + } + + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + LOGERR("Failed to read JSON capabilities"); + return tvERROR_GENERAL; + } + + const char* key = "Custom2PointWhiteBalance"; + if (!root.HasLabel(key)) { + LOGERR("Missing key: %s", key); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject section = root[key].Object(); + + if (!section.HasLabel("platformSupport") || !section["platformSupport"].Boolean()) { + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + // Parse rangeGain and rangeOffset + *min_gain = section["rangeGain"].Object()["from"].Number(); + *max_gain = section["rangeGain"].Object()["to"].Number(); + *min_offset = section["rangeOffset"].Object()["from"].Number(); + *max_offset = section["rangeOffset"].Object()["to"].Number(); + + // Parse control array + JsonArray controlArray = section["control"].Array(); + *num_control = controlArray.Length(); + *control = new tvWBControl_t[*num_control]; + for (size_t i = 0; i < *num_control; ++i) { + std::string ctrlStr = controlArray[i].String(); + if (getWBControlEnumFromString(ctrlStr, (*control)[i]) != 0) { + LOGERR("Invalid control: %s", ctrlStr.c_str()); + delete[] *control; + *control = nullptr; + return tvERROR_INVALID_PARAM; + } + } + + // Parse color array + JsonArray colorArray = section["color"].Array(); + *num_color = colorArray.Length(); + *color = new tvWBColor_t[*num_color]; + for (size_t i = 0; i < *num_color; ++i) { + std::string colStr = colorArray[i].String(); + if (getWBColorEnumFromString(colStr, (*color)[i]) != 0) { + LOGERR("Invalid color: %s", colStr.c_str()); + delete[] *color; + delete[] *control; + *color = nullptr; + *control = nullptr; + return tvERROR_INVALID_PARAM; + } + } + + // Parse contextCaps + if (ExtractContextCaps(section, context_caps) != tvERROR_NONE) { + delete[] *color; + delete[] *control; + *color = nullptr; + *control = nullptr; + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +#if HAL_NOT_READY +tvError_t AVOutputTV::GetBacklightCaps(int* max_backlight, tvContextCaps_t** context_caps) { + return GetCaps("Backlight", max_backlight, context_caps); +} + +tvError_t AVOutputTV::GetBrightnessCaps(int* max_brightness, tvContextCaps_t** context_caps) { + return GetCaps("Brightness", max_brightness, context_caps); +} + +tvError_t AVOutputTV::GetContrastCaps(int* max_contrast, tvContextCaps_t** context_caps) { + return GetCaps("Contrast", max_contrast, context_caps); +} + +tvError_t AVOutputTV::GetSharpnessCaps(int* max_sharpness, tvContextCaps_t** context_caps) { + return GetCaps("Sharpness", max_sharpness, context_caps); +} + +tvError_t AVOutputTV::GetSaturationCaps(int* max_saturation, tvContextCaps_t** context_caps) { + return GetCaps("Saturation", max_saturation, context_caps); +} + +tvError_t AVOutputTV::GetHueCaps(int* max_hue, tvContextCaps_t** context_caps) { + return GetCaps("Hue", max_hue, context_caps); +} + +tvError_t AVOutputTV::GetLowLatencyStateCaps(int* max_latency, tvContextCaps_t ** context_caps){ + return GetCaps("LowLatencyState", max_latency, context_caps); +} + +// PrecisionDetail +tvError_t AVOutputTV::GetPrecisionDetailCaps(int * maxPrecision, tvContextCaps_t ** context_caps) { + return GetCaps("PrecisionDetail", maxPrecision, context_caps); +} + +// AISuperResolution +tvError_t AVOutputTV::GetAISuperResolutionCaps(int * maxAISuperResolution, tvContextCaps_t ** context_caps) { + return GetCaps("AISuperResolution", maxAISuperResolution, context_caps); +} + +// MEMC +tvError_t AVOutputTV::GetMEMCCaps(int * maxMEMC, tvContextCaps_t ** context_caps) { + return GetCaps("MEMC", maxMEMC, context_caps); +} + +tvError_t AVOutputTV::GetColorTemperatureCaps(tvColorTemp_t** color_temp, size_t* num_color_temp, tvContextCaps_t** context_caps) { + LOGINFO("Entry\n"); + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + std::string key = "ColorTemperature"; + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + JsonArray optionsArray = rangeInfo["options"].Array(); + + *num_color_temp = optionsArray.Length(); + *color_temp = static_cast(malloc(*num_color_temp * sizeof(tvColorTemp_t))); + if (!(*color_temp)) { + return tvERROR_GENERAL; + } + + for (size_t i = 0; i < *num_color_temp; ++i) { + std::string tempStr = optionsArray[i].String(); + if (tempStr == "Standard") (*color_temp)[i] = tvColorTemp_STANDARD; + else if (tempStr == "Warm") (*color_temp)[i] = tvColorTemp_WARM; + else if (tempStr == "Cold") (*color_temp)[i] = tvColorTemp_COLD; + else if (tempStr == "UserDefined") (*color_temp)[i] = tvColorTemp_USER; + else if (tempStr == "Supercold") (*color_temp)[i] = tvColorTemp_SUPERCOLD; + else if (tempStr == "BoostStandard") (*color_temp)[i] = tvColorTemp_BOOST_STANDARD; + else if (tempStr == "BoostWarm") (*color_temp)[i] = tvColorTemp_BOOST_WARM; + else if (tempStr == "BoostCold") (*color_temp)[i] = tvColorTemp_BOOST_COLD; + else if (tempStr == "BoostUserDefined") (*color_temp)[i] = tvColorTemp_BOOST_USER; + else if (tempStr == "BoostSupercold") (*color_temp)[i] = tvColorTemp_BOOST_SUPERCOLD; + else (*color_temp)[i] = tvColorTemp_STANDARD; + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + free(*color_temp); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + + +tvError_t AVOutputTV::GetSdrGammaCaps(tvSdrGamma_t** sdr_gamma, size_t* num_sdr_gamma, tvContextCaps_t** context_caps) { + LOGINFO("Entry\n"); + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + std::string key = "SDRGamma"; + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + JsonArray optionsArray = rangeInfo["options"].Array(); + + *num_sdr_gamma = optionsArray.Length(); + *sdr_gamma = static_cast(malloc(*num_sdr_gamma * sizeof(tvSdrGamma_t))); + if (!(*sdr_gamma)) { + return tvERROR_GENERAL; + } + + for (size_t i = 0; i < *num_sdr_gamma; ++i) { + std::string gammaStr = optionsArray[i].String(); + if (gammaStr == "1.8") (*sdr_gamma)[i] = tvSdrGamma_1_8; + else if (gammaStr == "1.9") (*sdr_gamma)[i] = tvSdrGamma_1_9; + else if (gammaStr == "2.0") (*sdr_gamma)[i] = tvSdrGamma_2_0; + else if (gammaStr == "2.1") (*sdr_gamma)[i] = tvSdrGamma_2_1; + else if (gammaStr == "2.2") (*sdr_gamma)[i] = tvSdrGamma_2_2; + else if (gammaStr == "2.3") (*sdr_gamma)[i] = tvSdrGamma_2_3; + else if (gammaStr == "2.4") (*sdr_gamma)[i] = tvSdrGamma_2_4; + else if (gammaStr == "BT.1886") (*sdr_gamma)[i] = tvSdrGamma_BT_1886; + else (*sdr_gamma)[i] = tvSdrGamma_INVALID; + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + free(*sdr_gamma); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} +tvError_t AVOutputTV::GetTVDimmingModeCaps(tvDimmingMode_t** dimming_mode, size_t* num_dimming_mode, tvContextCaps_t** context_caps){ + LOGINFO("Entry\n"); + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + std::string key = "DimmingMode"; + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + JsonArray optionsArray = rangeInfo["options"].Array(); + *num_dimming_mode = optionsArray.Length(); + *dimming_mode = static_cast(malloc(*num_dimming_mode * sizeof(tvDimmingMode_t))); + if (!(*dimming_mode)) { + return tvERROR_GENERAL; + } + + for (size_t i = 0; i < *num_dimming_mode; ++i) { + std::string modeStr = optionsArray[i].String(); + if (modeStr == "Fixed") (*dimming_mode)[i] = tvDimmingMode_Fixed; + else if (modeStr == "Local") (*dimming_mode)[i] = tvDimmingMode_Local; + else if (modeStr == "Global") (*dimming_mode)[i] = tvDimmingMode_Global; + else (*dimming_mode)[i] = tvDimmingMode_MAX; + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + free(*dimming_mode); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; + +} + +tvError_t AVOutputTV::GetAspectRatioCaps(tvDisplayMode_t** aspect_ratio, size_t* num_aspect_ratio, tvContextCaps_t** context_caps) { + LOGINFO("Entry\n"); + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + std::string key = "AspectRatio"; + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + JsonArray optionsArray = rangeInfo["options"].Array(); + + *num_aspect_ratio = optionsArray.Length(); + *aspect_ratio = static_cast(malloc(*num_aspect_ratio * sizeof(tvDisplayMode_t))); + if (!(*aspect_ratio)) { + return tvERROR_GENERAL; + } + + for (size_t i = 0; i < *num_aspect_ratio; ++i) { + std::string aspectStr = optionsArray[i].String(); + if (aspectStr == "TV AUTO") (*aspect_ratio)[i] = tvDisplayMode_AUTO; + else if (aspectStr == "TV DIRECT") (*aspect_ratio)[i] = tvDisplayMode_DIRECT; + else if (aspectStr == "TV FULL") (*aspect_ratio)[i] = tvDisplayMode_FULL; + else if (aspectStr == "TV NORMAL") (*aspect_ratio)[i] = tvDisplayMode_NORMAL; + else if (aspectStr == "TV 16X9 STRETCH") (*aspect_ratio)[i] = tvDisplayMode_16x9; + else if (aspectStr == "TV 4X3 PILLARBOX") (*aspect_ratio)[i] = tvDisplayMode_4x3; + else if (aspectStr == "TV ZOOM") (*aspect_ratio)[i] = tvDisplayMode_ZOOM; + else (*aspect_ratio)[i] = tvDisplayMode_MAX; + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + free(*aspect_ratio); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +tvError_t AVOutputTV::GetTVPictureModeCaps(tvPQModeIndex_t** mode, size_t* num_pic_modes, tvContextCaps_t** context_caps) { + LOGINFO("Entry\n"); + JsonObject root; + if (ReadJsonFile(root) != tvERROR_NONE) { + return tvERROR_GENERAL; + } + + std::string key = "PictureMode"; + if (!root.HasLabel(key.c_str())) { + LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); + return tvERROR_GENERAL; + } + + JsonObject data = root[key.c_str()].Object(); + if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { + LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); + return tvERROR_OPERATION_NOT_SUPPORTED; + } + + JsonObject rangeInfo = data["rangeInfo"].Object(); + JsonArray optionsArray = rangeInfo["options"].Array(); + + *num_pic_modes = optionsArray.Length(); + *mode = static_cast(malloc(*num_pic_modes * sizeof(tvPQModeIndex_t))); + if (!(*mode)) { + return tvERROR_GENERAL; + } + + for (size_t i = 0; i < *num_pic_modes; ++i) { + std::string modeStr = optionsArray[i].String(); + + if (modeStr == "Standard") (*mode)[i] = PQ_MODE_STANDARD; + else if (modeStr == "Vivid") (*mode)[i] = PQ_MODE_VIVID; + else if (modeStr == "EnergySaving" || modeStr == "Energy Saving") (*mode)[i] = PQ_MODE_ENERGY_SAVING; + else if (modeStr == "Theater") (*mode)[i] = PQ_MODE_THEATER; + else if (modeStr == "Game") (*mode)[i] = PQ_MODE_GAME; + else if (modeStr == "Sports") (*mode)[i] = PQ_MODE_SPORTS; + else if (modeStr == "AI PQ") (*mode)[i] = PQ_MODE_AIPQ; + else if (modeStr == "Dark") (*mode)[i] = PQ_MODE_DARK; + else if (modeStr == "Bright") (*mode)[i] = PQ_MODE_BRIGHT; + else if (modeStr == "IQ") (*mode)[i] = PQ_MODE_IQ; + else (*mode)[i] = PQ_MODE_INVALID; + } + + if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { + free(*mode); + return tvERROR_GENERAL; + } + + return tvERROR_NONE; +} + +#endif + + int AVOutputTV::ReadCapablitiesFromConf(std::string param, capDetails_t& info) + { + int ret = 0; + + /*Consider User WhiteBalance as CustomWhiteBalance + To avoid clash with Factory WhiteBalance Calibration capablities*/ + + if ( param == "WhiteBalance") { + param = "CustomWhiteBalance"; + } else if ( param == "AutoBacklightMode") { + param = "BacklightControl"; + } + + try { + CIniFile inFile(CAPABLITY_FILE_NAME); + std::string configString; + + if(param == "CMS") + { + configString = param + ".color"; + info.color = inFile.Get(configString); + + configString = param + ".component"; + info.component = inFile.Get(configString); + } + + if(param == "CustomWhiteBalance") + { + configString = param + ".color"; + info.color = inFile.Get(configString); + + configString = param + ".control"; + info.control = inFile.Get(configString); + + } + + if ((param == "DolbyVisionMode") || (param == "Backlight") || (param == "CMS") || (param == "CustomWhiteBalance") || (param == "HDRMode") || (param == "BacklightControl") || (param == "DimmingMode")) { + configString = param + ".platformsupport"; + info.isPlatformSupport = inFile.Get(configString); + printf(" platformsupport : %s\n",info.isPlatformSupport.c_str() ); + } + + if ( (param == "ColorTemperature") || (param == "DimmingMode") || + ( param == "BacklightControl") || (param == "DolbyVisionMode") || + (param == "HDR10Mode") || (param == "HLGMode") || (param == "AspectRatio") || + (param == "PictureMode") || (param == "VideoSource") || (param == "VideoFormat") || + (param == "VideoFrameRate") || (param == "HDRMode") ) { + configString = param + ".range"; + info.range = inFile.Get(configString); + printf(" String Range info : %s\n",info.range.c_str() ); + } else if ( (param == "CMS" )) { + configString.clear(); + configString = param + ".range_Saturation_from"; + info.range = inFile.Get(configString); + configString = param + ".range_Saturation_to"; + info.range += ","+inFile.Get(configString); + + configString = param + ".range_Hue_from"; + info.range += ","+inFile.Get(configString); + configString = param + ".range_Hue_to"; + info.range += ","+inFile.Get(configString); + + configString = param + ".range_Luma_from"; + info.range += ","+inFile.Get(configString); + configString = param + ".range_Luma_to"; + info.range += ","+inFile.Get(configString); + } else if ( (param == "CustomWhiteBalance")) { + configString = param + ".range_Gain_from"; + info.range = inFile.Get(configString); + configString = param + ".range_Gain_to"; + info.range += ","+inFile.Get(configString); + + configString = param + ".range_Offset_from"; + info.range += ","+inFile.Get(configString); + configString = param + ".range_Offset_to"; + info.range += ","+inFile.Get(configString); + } else { + configString = param + ".range_from"; + info.range = inFile.Get(configString); + configString = param + ".range_to"; + info.range += ","+inFile.Get(configString); + printf(" Integer Range Info : %s\n",info.range.c_str() ); + } + + if ((param == "VideoSource") || (param == "PictureMode") || (param == "VideoFormat") ) { configString.clear(); configString = param + ".index"; info.index = inFile.Get(configString); @@ -2372,7 +4285,6 @@ namespace Plugin { } return ret; } - bool AVOutputTV::checkCMSColorAndComponentCapability(const std::string capValue, const std::string inputValue) { // Parse capValue into a set std::set capSet; diff --git a/AVOutput/CHANGELOG.md b/AVOutput/CHANGELOG.md index e5f68a0f..774b8127 100644 --- a/AVOutput/CHANGELOG.md +++ b/AVOutput/CHANGELOG.md @@ -13,6 +13,9 @@ All notable changes to this RDK Service will be documented in this file. * **Security** in case of vulnerabilities. * Changes in CHANGELOG should be updated when commits are added to the main or release branches. There should be one CHANGELOG entry per JIRA Ticket. This is not enforced on sprint branches since there could be multiple changes for the same JIRA ticket during development. +## [1.2.0] - 2025-06-25 +### Added +- Advance PQ Params ## [1.1.2] - 2025-07-01 ### Fixed From 414c41b235b663601c98a0a2b12c5e8b902a082d Mon Sep 17 00:00:00 2001 From: aktamilbe <59253707+aktamilbe@users.noreply.github.com> Date: Wed, 16 Jul 2025 06:06:07 +0100 Subject: [PATCH 11/14] RDKEMW-5197 : Updated review comments --- AVOutput/AVOutput.cpp | 2 +- AVOutput/AVOutputTV.cpp | 100 ++++++++-------------------------- AVOutput/AVOutputTV.h | 7 +-- AVOutput/AVOutputTVHelper.cpp | 45 +++++---------- 4 files changed, 41 insertions(+), 113 deletions(-) diff --git a/AVOutput/AVOutput.cpp b/AVOutput/AVOutput.cpp index b8a3a229..a1ecc207 100644 --- a/AVOutput/AVOutput.cpp +++ b/AVOutput/AVOutput.cpp @@ -23,7 +23,7 @@ #include "UtilsSearchRDKProfile.h" #define API_VERSION_NUMBER_MAJOR 1 -#define API_VERSION_NUMBER_MINOR 2 +#define API_VERSION_NUMBER_MINOR 1 #define API_VERSION_NUMBER_PATCH 0 namespace WPEFramework { diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index 1bc5c8a2..22af19d1 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -868,7 +868,7 @@ namespace Plugin { uint32_t AVOutputTV::getBacklightCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_backlight) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetBacklightCaps(max_backlight, context_caps); #else return GetBacklightCaps(max_backlight, context_caps); @@ -878,7 +878,7 @@ namespace Plugin { uint32_t AVOutputTV::getBrightnessCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_brightness) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetBrightnessCaps(max_brightness, context_caps); #else return GetBrightnessCaps(max_brightness, context_caps); @@ -889,7 +889,7 @@ namespace Plugin { uint32_t AVOutputTV::getContrastCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_contrast) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetContrastCaps(max_contrast, context_caps); #else return GetContrastCaps(max_contrast, context_caps); @@ -900,7 +900,7 @@ namespace Plugin { uint32_t AVOutputTV::getSharpnessCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_sharpness) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetSharpnessCaps(max_sharpness, context_caps); #else return GetSharpnessCaps(max_sharpness, context_caps); @@ -911,7 +911,7 @@ namespace Plugin { uint32_t AVOutputTV::getSaturationCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_saturation) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetSaturationCaps(max_saturation, context_caps); #else return GetSaturationCaps(max_saturation, context_caps); @@ -922,7 +922,7 @@ namespace Plugin { uint32_t AVOutputTV::getHueCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_hue) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetHueCaps(max_hue, context_caps); #else return GetHueCaps(max_hue, context_caps); @@ -933,7 +933,7 @@ namespace Plugin { uint32_t AVOutputTV::getPrecisionDetailCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_precision) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetPrecisionDetailCaps(max_precision, context_caps); #else return GetPrecisionDetailCaps(max_precision, context_caps); @@ -944,7 +944,7 @@ namespace Plugin { uint32_t AVOutputTV::getLocalContrastEnhancementCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetLocalContrastEnhancementCaps(max_val, context_caps); #else return GetLocalContrastEnhancementCaps(max_val, context_caps); @@ -955,7 +955,7 @@ namespace Plugin { uint32_t AVOutputTV::getMPEGNoiseReductionCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetMPEGNoiseReductionCaps(max_val, context_caps); #else return GetMPEGNoiseReductionCaps(max_val, context_caps); @@ -966,7 +966,7 @@ namespace Plugin { uint32_t AVOutputTV::getDigitalNoiseReductionCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetDigitalNoiseReductionCaps(max_val, context_caps); #else return GetDigitalNoiseReductionCaps(max_val, context_caps); @@ -977,7 +977,7 @@ namespace Plugin { uint32_t AVOutputTV::getAISuperResolutionCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetAISuperResolutionCaps(max_val, context_caps); #else return GetAISuperResolutionCaps(max_val, context_caps); @@ -1023,7 +1023,7 @@ namespace Plugin { } response["uiMatrixPositions"] = uiPosArray; response["context"] = parseContextCaps(context_caps); -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN // TODO:: Review cleanup once HAL is available, as memory will be allocated in HAL. delete[] ui_matrix_positions; #endif @@ -1033,7 +1033,7 @@ namespace Plugin { uint32_t AVOutputTV::getMEMCCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetMEMCCaps(max_val, context_caps); #else return GetMEMCCaps(max_val, context_caps); @@ -1044,7 +1044,7 @@ namespace Plugin { uint32_t AVOutputTV::getLowLatencyStateCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_latency) { -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN return this->GetLowLatencyStateCaps(max_latency, context_caps); #else return GetLowLatencyStateCaps(max_latency, context_caps); @@ -1103,7 +1103,7 @@ namespace Plugin { response["options"] = optionsArray; response["context"] = parseContextCaps(context_caps); - #if HAL_NOT_READY + #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN free(color_temp); #endif @@ -1141,7 +1141,7 @@ namespace Plugin { response["context"] = parseContextCaps(context_caps); - #if HAL_NOT_READY + #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN free(sdr_gamma); #endif @@ -1172,7 +1172,7 @@ namespace Plugin { response["context"] = parseContextCaps(context_caps); - #if HAL_NOT_READY + #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN free(dimming_mode); #endif @@ -1194,7 +1194,7 @@ namespace Plugin { response["context"] = parseContextCaps(m_aspectRatioCaps); - #if HAL_NOT_READY + #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN free(m_aspectRatio); #endif @@ -1216,7 +1216,7 @@ namespace Plugin { response["context"] = parseContextCaps(m_pictureModeCaps); - #if HAL_NOT_READY + #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN free(m_pictureModes); #endif @@ -1248,7 +1248,7 @@ namespace Plugin { response["context"] = parseContextCaps(m_backlightModeCaps); - #if HAL_NOT_READY + #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN // TODO: Review cleanup once HAL is available, as memory will be allocated in HAL. free(m_backlightModes); #endif @@ -1288,7 +1288,7 @@ namespace Plugin { // Indicate success response["success"] = true; -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN // TODO: Clean up when HAL handles memory delete min_values; delete max_values; @@ -1591,80 +1591,43 @@ namespace Plugin { uint32_t AVOutputTV::resetPrecisionDetail(const JsonObject& parameters, JsonObject& response) { - #if HAL_NOT_READY - bool success = false; - #else bool success = resetPQParamToDefault(parameters, "PrecisionDetail", PQ_PARAM_PRECISION_DETAIL, SetPrecisionDetail); - #endif returnResponse(success); } uint32_t AVOutputTV::resetLocalContrastEnhancement(const JsonObject& parameters, JsonObject& response) { - #if HAL_NOT_READY - bool success = false; - #else - #if ENABLE_PQ_PARAM bool success = resetPQParamToDefault(parameters, "LocalContrastEnhancement", PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT, SetLocalContrastEnhancement); - #else - bool success = true; - #endif - #endif returnResponse(success); } uint32_t AVOutputTV::resetMPEGNoiseReduction(const JsonObject& parameters, JsonObject& response) { - #if HAL_NOT_READY - bool success = false; - #else - #if ENABLE_PQ_PARAM bool success = resetPQParamToDefault(parameters, "MPEGNoiseReduction", PQ_PARAM_MPEG_NOISE_REDUCTION, SetMPEGNoiseReduction); - #else - bool success = true; - #endif - #endif returnResponse(success); } uint32_t AVOutputTV::resetDigitalNoiseReduction(const JsonObject& parameters, JsonObject& response) { - #if HAL_NOT_READY - bool success = false; - #else - #if ENABLE_PQ_PARAM bool success = resetPQParamToDefault(parameters, "DigitalNoiseReduction", PQ_PARAM_DIGITAL_NOISE_REDUCTION, SetDigitalNoiseReduction); - #else - bool success = true; - #endif - - #endif returnResponse(success); } uint32_t AVOutputTV::resetMEMC(const JsonObject& parameters, JsonObject& response) { - #if HAL_NOT_READY - bool success = false; - #else bool success = resetPQParamToDefault(parameters, "MEMC", PQ_PARAM_MEMC, SetMEMC); - #endif returnResponse(success); } uint32_t AVOutputTV::resetAISuperResolution(const JsonObject& parameters, JsonObject& response) { -#if HAL_NOT_READY - bool success= false; -#else bool success= resetPQParamToDefault(parameters,"AISuperResolution", PQ_PARAM_AI_SUPER_RESOLUTION, SetAISuperResolution); -#endif returnResponse(success); } @@ -1805,14 +1768,11 @@ namespace Plugin { LOGINFO("currentPQMode: %d, currentFmt: %d, currentSrc: %d", currentPQMode, currentFmt, currentSrc); if (isSetRequiredForParam(parameters, tr181ParamName)) { - #if HAL_NOT_READY - #else tvError_t ret = halSetter(currentSrc, currentPQMode, currentFmt, value); if (ret != tvERROR_NONE) { LOGERR("HAL setter failed for %s", inputParamName.c_str()); returnResponse(false); } - #endif } // Persist @@ -1868,7 +1828,6 @@ namespace Plugin { uint32_t AVOutputTV::setLocalContrastEnhancement(const JsonObject& parameters, JsonObject& response) { -#if ENABLE_PQ_PARAM return setContextPQParam( parameters, response, "localContrastEnhancement", "LocalContrastEnhancement", @@ -1878,14 +1837,10 @@ namespace Plugin { return SetLocalContrastEnhancement(src, mode, fmt, val); } ); -#else - returnResponse(true); -#endif } uint32_t AVOutputTV::setMPEGNoiseReduction(const JsonObject& parameters, JsonObject& response) { -#if ENABLE_PQ_PARAM return setContextPQParam( parameters, response, "mpegNoiseReduction", "MPEGNoiseReduction", @@ -1895,14 +1850,10 @@ namespace Plugin { return SetMPEGNoiseReduction(src, mode, fmt, val); } ); -#else - returnResponse(true); -#endif } uint32_t AVOutputTV::setDigitalNoiseReduction(const JsonObject& parameters, JsonObject& response) { -#if ENABLE_PQ_PARAM return setContextPQParam( parameters, response, "digitalNoiseReduction", "DigitalNoiseReduction", @@ -1912,9 +1863,6 @@ namespace Plugin { return SetDigitalNoiseReduction(src, mode, fmt, val); } ); -#else - returnResponse(true); -#endif } uint32_t AVOutputTV::getBacklight(const JsonObject& parameters, JsonObject& response) @@ -4440,7 +4388,7 @@ namespace Plugin { if (ctx.videoSrcType == currentSrc && ctx.videoFormatType == currentFmt) { if (SetTVPictureMode(mode.c_str()) != tvERROR_NONE) { LOGERR("SetTVPictureMode failed for mode: %s", mode.c_str()); - continue; + return false; } } //TODO:: Revisit this logic. Have to revert if HAL call fails. @@ -5384,7 +5332,7 @@ namespace Plugin { } response["component"] = componentJson; response["context"] = parseContextCaps(context_caps); -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN // Clean up dynamic memory delete[] colorArray; delete[] componentArray; @@ -5893,7 +5841,7 @@ namespace Plugin { response["color"] = colorJson; response["context"] = parseContextCaps(context_caps); -#if HAL_NOT_READY +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN delete[] colorArray; delete[] controlArray; #endif diff --git a/AVOutput/AVOutputTV.h b/AVOutput/AVOutputTV.h index 84c89526..4737ba71 100644 --- a/AVOutput/AVOutputTV.h +++ b/AVOutput/AVOutputTV.h @@ -469,9 +469,8 @@ class AVOutputTV : public AVOutputBase { int *max_offset, tvWBColor_t **color, tvWBControl_t **control, size_t* num_color, size_t* num_control, tvContextCaps_t ** context_caps); -#define HAL_NOT_READY 0 -#if HAL_NOT_READY -#define CAPABLITY_FILE_NAMEV2 "/opt/panel/pq_capabilities.json" +#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN +#define CAPABILITY_FILE_NAMEV2 "/opt/panel/pq_capabilities.json" tvError_t GetBacklightCaps(int *max_backlight, tvContextCaps_t **context_caps); tvError_t GetBrightnessCaps(int *max_brightness, tvContextCaps_t **context_caps); tvError_t GetContrastCaps(int* max_contrast, tvContextCaps_t** context_caps); @@ -488,7 +487,7 @@ class AVOutputTV : public AVOutputBase { tvError_t GetAISuperResolutionCaps(int* maxAISuperResolution, tvContextCaps_t** context_caps); tvError_t GetMEMCCaps(int* maxMEMC, tvContextCaps_t** context_caps); #else -#define CAPABLITY_FILE_NAMEV2 "/etc/pq_capabilities.json" +#define CAPABILITY_FILE_NAMEV2 "/etc/pq_capabilities.json" #endif uint32_t getPQCapabilityWithContext( const std::function& getCapsFunc, diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index c93340d0..40deb3d1 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -1290,9 +1290,7 @@ namespace Plugin { if (m_dimmingModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) { updateAVoutputTVParam("sync", "DimmingMode", info, PQ_PARAM_DIMMINGMODE, level); } else { -#if !HAL_NOT_READY updateAVoutputTVParamV2("sync", "DimmingMode", paramJson, PQ_PARAM_DIMMINGMODE,level); -#endif } // Backlight @@ -1334,10 +1332,19 @@ namespace Plugin { //AspectRatio m_aspectRatioStatus = GetAspectRatioCaps(&m_aspectRatio, &m_numAspectRatio, &m_aspectRatioCaps); + //LowLatencyState m_lowLatencyStateStatus = GetLowLatencyStateCaps(&m_maxlowLatencyState, &m_lowLatencyStateCaps); + if (m_lowLatencyStateStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + updateAVoutputTVParam("sync", "LowLatencyState", info, PQ_PARAM_LOWLATENCY_STATE, level); + } else { + updateAVoutputTVParamV2("sync", "LowLatencyState", paramJson, PQ_PARAM_LOWLATENCY_STATE, level); + } // PrecisionDetail m_precisionDetailStatus = GetPrecisionDetailCaps(&m_maxPrecisionDetail, &m_precisionDetailCaps); + if (m_localContrastEnhancementStatus == tvERROR_NONE) { + updateAVoutputTVParamV2("sync", "PrecisionDetails", paramJson, PQ_PARAM_PRECISION_DETAIL, level); + } //PictureMode m_pictureModeStatus = GetTVPictureModeCaps(&m_pictureModes, &m_numPictureModes, &m_pictureModeCaps); @@ -3307,79 +3314,52 @@ namespace Plugin { case PQ_PARAM_ASPECT_RATIO: ret |= SaveAspectRatio((tvVideoSrcType_t)paramIndex.sourceIndex, paramIndex.pqmodeIndex,(tvVideoFormatType_t)paramIndex.formatIndex,(tvDisplayMode_t)level); break; - case PQ_PARAM_PRECISION_DETAIL: - #if HAL_NOT_READY - #else + case PQ_PARAM_PRECISION_DETAIL: ret |= SetPrecisionDetail((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, level); - #endif break; case PQ_PARAM_LOCAL_CONTRAST_ENHANCEMENT: - #if HAL_NOT_READY - #else - #if ENABLE_PQ_PARAM ret |= SetLocalContrastEnhancement((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, level); - #endif - #endif break; case PQ_PARAM_MPEG_NOISE_REDUCTION: - #if HAL_NOT_READY - #else - #if ENABLE_PQ_PARAM ret |= SetMPEGNoiseReduction((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, level); - #endif - #endif break; case PQ_PARAM_DIGITAL_NOISE_REDUCTION: - #if HAL_NOT_READY - #else - #if ENABLE_PQ_PARAM ret |= SetDigitalNoiseReduction((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, level); - #endif - #endif break; case PQ_PARAM_AI_SUPER_RESOLUTION: - #if HAL_NOT_READY - #else ret |= SetAISuperResolution((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, level); - #endif break; case PQ_PARAM_MEMC: - #if HAL_NOT_READY - #else ret |= SetMEMC((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, level); - #endif break; - #if HAL_NOT_READY - #else case PQ_PARAM_BACKLIGHT_MODE: ret |= SaveBacklightMode((tvVideoSrcType_t)paramIndex.sourceIndex, (tvPQModeIndex_t)paramIndex.pqmodeIndex, (tvVideoFormatType_t)paramIndex.formatIndex, static_cast(level)); - #endif break; case PQ_PARAM_HDR10_MODE: case PQ_PARAM_HLG_MODE: @@ -3405,8 +3385,9 @@ namespace Plugin { return ret; } +#ifdef ENABLE_CAPS_SUPPORT_FROM_PLUGIN tvError_t AVOutputTV::ReadJsonFile(JsonObject& root) { - std::ifstream file(CAPABLITY_FILE_NAMEV2); + std::ifstream file(CAPABILITY_FILE_NAMEV2); if (!file.is_open()) { LOGWARN("AVOutputPlugins: %s: Unable to open file", __FUNCTION__); return tvERROR_GENERAL; @@ -3469,6 +3450,7 @@ tvError_t AVOutputTV::ExtractContextCaps(const JsonObject& data, tvContextCaps_t return tvERROR_NONE; } + template bool LookupEnum(const std::string& str, const std::map& map, EnumType& outEnum) { for (const auto& entry : map) { @@ -3891,7 +3873,6 @@ tvError_t AVOutputTV::GetCustom2PointWhiteBalanceCaps(int* min_gain, int* min_of return tvERROR_NONE; } -#if HAL_NOT_READY tvError_t AVOutputTV::GetBacklightCaps(int* max_backlight, tvContextCaps_t** context_caps) { return GetCaps("Backlight", max_backlight, context_caps); } From 25299433c41afb4ba0dd89f3e6f75ab75bdf82d5 Mon Sep 17 00:00:00 2001 From: aktamilbe <59253707+aktamilbe@users.noreply.github.com> Date: Wed, 16 Jul 2025 11:55:09 +0100 Subject: [PATCH 12/14] RDKEMW-5197 : Removed Plugin Caps implementation --- AVOutput/AVOutput.h | 2 - AVOutput/AVOutputTV.cpp | 96 +---- AVOutput/AVOutputTV.h | 24 +- AVOutput/AVOutputTVHelper.cpp | 775 ---------------------------------- 4 files changed, 4 insertions(+), 893 deletions(-) diff --git a/AVOutput/AVOutput.h b/AVOutput/AVOutput.h index fb260ada..13536705 100644 --- a/AVOutput/AVOutput.h +++ b/AVOutput/AVOutput.h @@ -60,8 +60,6 @@ namespace Plugin { const std::string Initialize(PluginHost::IShell* service); void Deinitialize(PluginHost::IShell* service); virtual string Information() const override { return {}; } - virtual void AddRef() const { } - virtual uint32_t Release() const {return 0; } BEGIN_INTERFACE_MAP(AVOutput) INTERFACE_ENTRY(PluginHost::IPlugin) INTERFACE_ENTRY(PluginHost::IDispatcher) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index 22af19d1..4b393dd7 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -868,120 +868,76 @@ namespace Plugin { uint32_t AVOutputTV::getBacklightCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_backlight) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetBacklightCaps(max_backlight, context_caps); -#else return GetBacklightCaps(max_backlight, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getBrightnessCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_brightness) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetBrightnessCaps(max_brightness, context_caps); -#else return GetBrightnessCaps(max_brightness, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getContrastCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_contrast) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetContrastCaps(max_contrast, context_caps); -#else return GetContrastCaps(max_contrast, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getSharpnessCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_sharpness) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetSharpnessCaps(max_sharpness, context_caps); -#else return GetSharpnessCaps(max_sharpness, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getSaturationCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_saturation) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetSaturationCaps(max_saturation, context_caps); -#else return GetSaturationCaps(max_saturation, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getHueCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this]( tvContextCaps_t** context_caps, int* max_hue) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetHueCaps(max_hue, context_caps); -#else return GetHueCaps(max_hue, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getPrecisionDetailCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_precision) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetPrecisionDetailCaps(max_precision, context_caps); -#else return GetPrecisionDetailCaps(max_precision, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getLocalContrastEnhancementCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetLocalContrastEnhancementCaps(max_val, context_caps); -#else return GetLocalContrastEnhancementCaps(max_val, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getMPEGNoiseReductionCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetMPEGNoiseReductionCaps(max_val, context_caps); -#else return GetMPEGNoiseReductionCaps(max_val, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getDigitalNoiseReductionCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetDigitalNoiseReductionCaps(max_val, context_caps); -#else return GetDigitalNoiseReductionCaps(max_val, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getAISuperResolutionCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetAISuperResolutionCaps(max_val, context_caps); -#else return GetAISuperResolutionCaps(max_val, context_caps); -#endif }, parameters, response); } @@ -1023,32 +979,20 @@ namespace Plugin { } response["uiMatrixPositions"] = uiPosArray; response["context"] = parseContextCaps(context_caps); -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - // TODO:: Review cleanup once HAL is available, as memory will be allocated in HAL. - delete[] ui_matrix_positions; -#endif LOGINFO("Exit\n"); returnResponse(true); } uint32_t AVOutputTV::getMEMCCaps(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_val) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetMEMCCaps(max_val, context_caps); -#else return GetMEMCCaps(max_val, context_caps); -#endif }, parameters, response); } uint32_t AVOutputTV::getLowLatencyStateCapsV2(const JsonObject& parameters, JsonObject& response) { return getPQCapabilityWithContext([this](tvContextCaps_t** context_caps, int* max_latency) { -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - return this->GetLowLatencyStateCaps(max_latency, context_caps); -#else return GetLowLatencyStateCaps(max_latency, context_caps); -#endif }, parameters, response); } @@ -1103,9 +1047,6 @@ namespace Plugin { response["options"] = optionsArray; response["context"] = parseContextCaps(context_caps); - #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - free(color_temp); - #endif returnResponse(true); } @@ -1141,10 +1082,6 @@ namespace Plugin { response["context"] = parseContextCaps(context_caps); - #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - free(sdr_gamma); - #endif - returnResponse(true); } @@ -1172,10 +1109,6 @@ namespace Plugin { response["context"] = parseContextCaps(context_caps); - #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - free(dimming_mode); - #endif - returnResponse(true); } @@ -1194,10 +1127,6 @@ namespace Plugin { response["context"] = parseContextCaps(m_aspectRatioCaps); - #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - free(m_aspectRatio); - #endif - returnResponse(true); } @@ -1216,10 +1145,6 @@ namespace Plugin { response["context"] = parseContextCaps(m_pictureModeCaps); - #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - free(m_pictureModes); - #endif - returnResponse(true); } @@ -1248,11 +1173,6 @@ namespace Plugin { response["context"] = parseContextCaps(m_backlightModeCaps); - #if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - // TODO: Review cleanup once HAL is available, as memory will be allocated in HAL. - free(m_backlightModes); - #endif - returnResponse(true); } @@ -1288,12 +1208,6 @@ namespace Plugin { // Indicate success response["success"] = true; -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - // TODO: Clean up when HAL handles memory - delete min_values; - delete max_values; -#endif - returnResponse(true); } @@ -5332,11 +5246,7 @@ namespace Plugin { } response["component"] = componentJson; response["context"] = parseContextCaps(context_caps); -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - // Clean up dynamic memory - delete[] colorArray; - delete[] componentArray; -#endif + LOGINFO("Exit: getCMSCapsV2"); returnResponse(true); } @@ -5841,10 +5751,6 @@ namespace Plugin { response["color"] = colorJson; response["context"] = parseContextCaps(context_caps); -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN - delete[] colorArray; - delete[] controlArray; -#endif LOGINFO("Exit: get2PointWBCapsV2"); returnResponse(true); diff --git a/AVOutput/AVOutputTV.h b/AVOutput/AVOutputTV.h index 4737ba71..ddfd384d 100644 --- a/AVOutput/AVOutputTV.h +++ b/AVOutput/AVOutputTV.h @@ -73,6 +73,7 @@ #define STRING_COLORTEMPERATURE "ColorTemperature." #define CREATE_DIRTY(__X__) (__X__+=STRING_DIRTY) #define CAPABLITY_FILE_NAME "pq_capabilities.ini" +#define CAPABILITY_FILE_NAMEV2 "/etc/pq_capabilities.json" class CIniFile @@ -236,7 +237,7 @@ class AVOutputTV : public AVOutputBase { DECLARE_JSON_RPC_METHOD(getAutoBacklightModeCaps) DECLARE_JSON_RPC_METHOD(getBacklightCapsV2) DECLARE_JSON_RPC_METHOD(getBrightnessCapsV2) - DECLARE_JSON_RPC_METHOD(getContrastCapsV2) + DECLARE_JSON_RPC_METHOD(getContrastCapsV2) DECLARE_JSON_RPC_METHOD(getSharpnessCapsV2) DECLARE_JSON_RPC_METHOD(getSaturationCapsV2) DECLARE_JSON_RPC_METHOD(getHueCapsV2) @@ -469,26 +470,7 @@ class AVOutputTV : public AVOutputBase { int *max_offset, tvWBColor_t **color, tvWBControl_t **control, size_t* num_color, size_t* num_control, tvContextCaps_t ** context_caps); -#if ENABLE_CAPS_SUPPORT_FROM_PLUGIN -#define CAPABILITY_FILE_NAMEV2 "/opt/panel/pq_capabilities.json" - tvError_t GetBacklightCaps(int *max_backlight, tvContextCaps_t **context_caps); - tvError_t GetBrightnessCaps(int *max_brightness, tvContextCaps_t **context_caps); - tvError_t GetContrastCaps(int* max_contrast, tvContextCaps_t** context_caps); - tvError_t GetSharpnessCaps(int *max_sharpness, tvContextCaps_t **context_caps); - tvError_t GetSaturationCaps(int* max_saturation, tvContextCaps_t** context_caps); - tvError_t GetHueCaps(int* max_hue, tvContextCaps_t** context_caps); - tvError_t GetPrecisionDetailCaps(int* max_precision, tvContextCaps_t** context_caps); - tvError_t GetLowLatencyStateCaps(int* max_latency, tvContextCaps_t ** context_caps); - tvError_t GetColorTemperatureCaps(tvColorTemp_t** color_temp, size_t* num_color_temp, tvContextCaps_t** context_caps); - tvError_t GetSdrGammaCaps(tvSdrGamma_t** sdr_gamma, size_t* num_sdr_gamma, tvContextCaps_t** context_caps); - tvError_t GetTVDimmingModeCaps(tvDimmingMode_t** dimming_mode, size_t* num_dimming_mode, tvContextCaps_t** context_caps); - tvError_t GetAspectRatioCaps(tvDisplayMode_t** aspect_ratio, size_t* num_aspect_ratio, tvContextCaps_t** context_caps); - tvError_t GetTVPictureModeCaps(tvPQModeIndex_t** mode, size_t* num_pic_modes, tvContextCaps_t** context_caps); - tvError_t GetAISuperResolutionCaps(int* maxAISuperResolution, tvContextCaps_t** context_caps); - tvError_t GetMEMCCaps(int* maxMEMC, tvContextCaps_t** context_caps); -#else -#define CAPABILITY_FILE_NAMEV2 "/etc/pq_capabilities.json" -#endif + uint32_t getPQCapabilityWithContext( const std::function& getCapsFunc, const JsonObject& parameters, diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 40deb3d1..1581ca51 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -3385,781 +3385,6 @@ namespace Plugin { return ret; } -#ifdef ENABLE_CAPS_SUPPORT_FROM_PLUGIN -tvError_t AVOutputTV::ReadJsonFile(JsonObject& root) { - std::ifstream file(CAPABILITY_FILE_NAMEV2); - if (!file.is_open()) { - LOGWARN("AVOutputPlugins: %s: Unable to open file", __FUNCTION__); - return tvERROR_GENERAL; - } - - std::string jsonStr((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - file.close(); - - if (!root.FromString(jsonStr)) { - LOGWARN("AVOutputPlugins: %s: JSON parsing failed", __FUNCTION__); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -tvError_t AVOutputTV::ExtractRangeInfo(const JsonObject& data, int* max_value) { - if (!data.HasLabel("rangeInfo")) { - LOGWARN("AVOutputPlugins: %s: 'rangeInfo' not available", __FUNCTION__); - return tvERROR_NONE; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - if (rangeInfo.HasLabel("to")) { - if (!max_value) { - LOGWARN("AVOutputPlugins: %s: NULL input param max_value", __FUNCTION__); - return tvERROR_INVALID_PARAM; - } - *max_value = rangeInfo["to"].Number(); - return tvERROR_NONE; - } - - LOGWARN("AVOutputPlugins: %s: Invalid 'rangeInfo' format", __FUNCTION__); - return tvERROR_GENERAL; -} - -tvError_t AVOutputTV::ExtractContextCaps(const JsonObject& data, tvContextCaps_t** context_caps) { - if (!context_caps) { - LOGWARN("AVOutputPlugins: %s: NULL input param", __FUNCTION__); - return tvERROR_INVALID_PARAM; - } - - if (!data.HasLabel("context")) { - LOGWARN("AVOutputPlugins: %s: 'context' missing", __FUNCTION__); - return tvERROR_GENERAL; - } - - JsonObject context = data["context"].Object(); - if (!context.IsSet()) { - LOGWARN("AVOutputPlugins: %s: Context is not set", __FUNCTION__); - return tvERROR_GENERAL; - } - - std::vector contexts = ParseContextCaps(context); - *context_caps = AllocateContextCaps(contexts); - if (!*context_caps) { - LOGWARN("AVOutputPlugins: %s: Memory allocation failed", __FUNCTION__); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -template -bool LookupEnum(const std::string& str, const std::map& map, EnumType& outEnum) { - for (const auto& entry : map) { - if (entry.second == str) { - outEnum = static_cast(entry.first); - return true; - } - } - return false; -} - -std::vector AVOutputTV::ParseContextCaps(const JsonObject& context) -{ - std::vector contexts; - std::set> seen; - - WPEFramework::Core::JSON::VariantContainer::Iterator modeIterator = context.Variants(); - while (modeIterator.Next()) { - std::string modeStr = modeIterator.Label(); - - tvPQModeIndex_t modeEnum; - if (!LookupEnum(modeStr, pqModeMap, modeEnum)) continue; - - const auto& modeValue = context[modeStr.c_str()]; - if (!modeValue.IsSet() || modeValue.Content() != WPEFramework::Core::JSON::Variant::type::OBJECT) continue; - - JsonObject formatMap = modeValue.Object(); - WPEFramework::Core::JSON::VariantContainer::Iterator formatIterator = formatMap.Variants(); - while (formatIterator.Next()) { - std::string formatStr = formatIterator.Label(); - - tvVideoFormatType_t fmtEnum; - if (!LookupEnum(formatStr, videoFormatMap, fmtEnum)) continue; - - const auto& formatValue = formatMap[formatStr.c_str()]; - if (!formatValue.IsSet() || formatValue.Content() != WPEFramework::Core::JSON::Variant::type::ARRAY) continue; - - JsonArray sources = formatValue.Array(); - for (uint32_t i = 0; i < sources.Length(); ++i) { - std::string srcStr = sources[i].String(); - - tvVideoSrcType_t srcEnum; - if (!LookupEnum(srcStr, videoSrcMap, srcEnum)) continue; - - auto triplet = std::make_tuple(modeEnum, fmtEnum, srcEnum); - if (seen.find(triplet) == seen.end()) { - contexts.push_back({modeEnum, fmtEnum, srcEnum}); - seen.insert(triplet); - } - } - } - } - - return contexts; -} - -tvContextCaps_t* AVOutputTV::AllocateContextCaps(const std::vector& contexts) { - tvContextCaps_t* context_caps = new (std::nothrow) tvContextCaps_t; - if (!context_caps) { - return nullptr; - } - - context_caps->num_contexts = contexts.size(); - context_caps->contexts = contexts.empty() ? nullptr : new (std::nothrow) tvConfigContext_t[contexts.size()]; - - if (!contexts.empty() && !context_caps->contexts) { - delete context_caps; - return nullptr; - } - - if (!contexts.empty()) { - std::copy(contexts.begin(), contexts.end(), context_caps->contexts); - } - return context_caps; -} - -tvError_t AVOutputTV::GetCaps(const std::string& key, int* max_value, tvContextCaps_t** context_caps) { - LOGINFO("Entry\n"); - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - if (ExtractRangeInfo(data, max_value) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -tvError_t AVOutputTV::GetDVCalibrationCaps(tvDVCalibrationSettings_t **min_values, tvDVCalibrationSettings_t **max_values, tvContextCaps_t **context_caps) { - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - if (!root.HasLabel("DolbyVisionCalibration")) { - LOGWARN("AVOutputPlugins: %s: Missing 'DolbyVisionCalibration' label", __FUNCTION__); - return tvERROR_GENERAL; - } - - JsonObject data = root["DolbyVisionCalibration"].Object(); - *min_values = new tvDVCalibrationSettings_t(); - *max_values = new tvDVCalibrationSettings_t(); - - std::map keyMap = { - {"Tmax", &tvDVCalibrationSettings_t::Tmax}, - {"Tmin", &tvDVCalibrationSettings_t::Tmin}, - {"Tgamma", &tvDVCalibrationSettings_t::Tgamma}, - {"Rx", &tvDVCalibrationSettings_t::Rx}, - {"Ry", &tvDVCalibrationSettings_t::Ry}, - {"Gx", &tvDVCalibrationSettings_t::Gx}, - {"Gy", &tvDVCalibrationSettings_t::Gy}, - {"Bx", &tvDVCalibrationSettings_t::Bx}, - {"By", &tvDVCalibrationSettings_t::By}, - {"Wx", &tvDVCalibrationSettings_t::Wx}, - {"Wy", &tvDVCalibrationSettings_t::Wy} - }; - - for (auto it = keyMap.begin(); it != keyMap.end(); ++it) { - const std::string& key = it->first; - double tvDVCalibrationSettings_t::*member = it->second; - std::string minKey = "range" + key; - if (data.HasLabel(minKey.c_str())) { - JsonObject range = data[minKey.c_str()].Object(); - (*min_values)->*member = range["from"].Number(); - (*max_values)->*member = range["to"].Number(); - } - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - return tvERROR_NONE; -} - -tvError_t AVOutputTV::GetBacklightModeCaps(tvBacklightMode_t** backlight_mode, size_t* num_backlight_mode, tvContextCaps_t** context_caps) -{ - LOGINFO("Entry\n"); - - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - std::string key = "BacklightMode"; - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - JsonArray optionsArray = rangeInfo["options"].Array(); - - *num_backlight_mode = optionsArray.Length(); - *backlight_mode = static_cast(malloc(*num_backlight_mode * sizeof(tvBacklightMode_t))); - if (!(*backlight_mode)) { - return tvERROR_GENERAL; - } - - for (size_t i = 0; i < *num_backlight_mode; ++i) { - std::string modeStr = optionsArray[i].String(); - auto it = backlightModeReverseMap.find(modeStr); - if (it != backlightModeReverseMap.end()) { - (*backlight_mode)[i] = static_cast (it->second); - } else { - (*backlight_mode)[i] = tvBacklightMode_INVALID; - } - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - free(*backlight_mode); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -// LocalContrastEnhancement -tvError_t AVOutputTV::GetLocalContrastEnhancementCaps(int * maxLocalContrastEnhancement, tvContextCaps_t ** context_caps) { - return GetCaps("LocalContrastEnhancement", maxLocalContrastEnhancement, context_caps); -} - -// MPEGNoiseReduction -tvError_t AVOutputTV::GetMPEGNoiseReductionCaps(int * maxMPEGNoiseReduction, tvContextCaps_t ** context_caps) { - return GetCaps("MPEGNoiseReduction", maxMPEGNoiseReduction, context_caps); -} - -// DigitalNoiseReduction -tvError_t AVOutputTV::GetDigitalNoiseReductionCaps(int * maxDigitalNoiseReduction, tvContextCaps_t ** context_caps) { - return GetCaps("DigitalNoiseReduction", maxDigitalNoiseReduction, context_caps); -} - -tvError_t AVOutputTV::GetMultiPointWBCaps(int* num_hal_matrix_points, - int* rgb_min, - int* rgb_max, - int* num_ui_matrix_points, - double** ui_matrix_positions, - tvContextCaps_t** context_caps) -{ - if (!num_hal_matrix_points || !rgb_min || !rgb_max || - !num_ui_matrix_points || !ui_matrix_positions || !context_caps) - return tvERROR_INVALID_PARAM; - - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) - return tvERROR_GENERAL; - - const std::string key = "MultiPointWB"; - if (!root.HasLabel(key.c_str())) - return tvERROR_OPERATION_NOT_SUPPORTED; - - JsonObject data = root[key.c_str()].Object(); - - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) - return tvERROR_OPERATION_NOT_SUPPORTED; - - // Extract matrix points - if (!data.HasLabel("points")) - return tvERROR_INVALID_PARAM; - *num_hal_matrix_points = data["points"].Number(); - - // Extract range info - if (!data.HasLabel("rangeInfo")) - return tvERROR_INVALID_PARAM; - - JsonObject range = data["rangeInfo"].Object(); - if (!range.HasLabel("from") || !range.HasLabel("to")) - return tvERROR_INVALID_PARAM; - - *rgb_min = range["from"].Number(); - *rgb_max = range["to"].Number(); - - // Allocate UI matrix points (same count for now) - *num_ui_matrix_points = *num_hal_matrix_points; - *ui_matrix_positions = new double[*num_ui_matrix_points]; - if (!(*ui_matrix_positions)) - return tvERROR_GENERAL; - - for (int i = 0; i < *num_ui_matrix_points; ++i) - (*ui_matrix_positions)[i] = static_cast(i) / (*num_ui_matrix_points - 1); - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) - return tvERROR_GENERAL; - - return tvERROR_NONE; -} - -tvError_t AVOutputTV::GetCMSCaps(int* max_hue, - int* max_saturation, - int* max_luma, - tvDataComponentColor_t** color, - tvComponentType_t** component, - size_t* num_color, - size_t* num_component, - tvContextCaps_t** context_caps) -{ - if (!max_hue || !max_saturation || !max_luma || !color || !component || !num_color || !num_component || !context_caps) { - return tvERROR_INVALID_PARAM; - } - - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - const char* key = "CMS"; - if (!root.HasLabel(key)) { - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject cms = root[key].Object(); - - if (!cms.HasLabel("platformSupport") || !cms["platformSupport"].Boolean()) { - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - // Extract ranges - *max_hue = cms.HasLabel("rangeHue") ? cms["rangeHue"].Object()["to"].Number() : 0; - *max_saturation = cms.HasLabel("rangeSaturation") ? cms["rangeSaturation"].Object()["to"].Number() : 0; - *max_luma = cms.HasLabel("rangeLuma") ? cms["rangeLuma"].Object()["to"].Number() : 0; - - // Extract colors - const JsonArray& colorArray = cms["color"].Array(); - *num_color = colorArray.Length(); - *color = new tvDataComponentColor_t[*num_color]; - for (size_t i = 0; i < *num_color; ++i) { - std::string colorStr = colorArray[i].String(); - if (getCMSColorEnumFromString(colorStr, (*color)[i]) != 0) { - delete[] *color; - *color = nullptr; - return tvERROR_INVALID_PARAM; - } - } - - // Extract components - const JsonArray& compArray = cms["component"].Array(); - *num_component = compArray.Length(); - *component = new tvComponentType_t[*num_component]; - for (size_t i = 0; i < *num_component; ++i) { - std::string compStr = compArray[i].String(); - if (getCMSComponentEnumFromString(compStr, (*component)[i]) != 0) { - delete[] *color; - delete[] *component; - *color = nullptr; - *component = nullptr; - return tvERROR_INVALID_PARAM; - } - } - - // Extract context capabilities - if (ExtractContextCaps(cms, context_caps) != tvERROR_NONE) { - delete[] *color; - delete[] *component; - *color = nullptr; - *component = nullptr; - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -tvError_t AVOutputTV::GetCustom2PointWhiteBalanceCaps(int* min_gain, int* min_offset, - int* max_gain, int* max_offset, - tvWBColor_t** color, - tvWBControl_t** control, - size_t* num_color, size_t* num_control, - tvContextCaps_t** context_caps) -{ - if (!min_gain || !min_offset || !max_gain || !max_offset || - !color || !control || !num_color || !num_control || !context_caps) - { - LOGERR("Invalid input pointers"); - return tvERROR_INVALID_PARAM; - } - - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - LOGERR("Failed to read JSON capabilities"); - return tvERROR_GENERAL; - } - - const char* key = "Custom2PointWhiteBalance"; - if (!root.HasLabel(key)) { - LOGERR("Missing key: %s", key); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject section = root[key].Object(); - - if (!section.HasLabel("platformSupport") || !section["platformSupport"].Boolean()) { - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - // Parse rangeGain and rangeOffset - *min_gain = section["rangeGain"].Object()["from"].Number(); - *max_gain = section["rangeGain"].Object()["to"].Number(); - *min_offset = section["rangeOffset"].Object()["from"].Number(); - *max_offset = section["rangeOffset"].Object()["to"].Number(); - - // Parse control array - JsonArray controlArray = section["control"].Array(); - *num_control = controlArray.Length(); - *control = new tvWBControl_t[*num_control]; - for (size_t i = 0; i < *num_control; ++i) { - std::string ctrlStr = controlArray[i].String(); - if (getWBControlEnumFromString(ctrlStr, (*control)[i]) != 0) { - LOGERR("Invalid control: %s", ctrlStr.c_str()); - delete[] *control; - *control = nullptr; - return tvERROR_INVALID_PARAM; - } - } - - // Parse color array - JsonArray colorArray = section["color"].Array(); - *num_color = colorArray.Length(); - *color = new tvWBColor_t[*num_color]; - for (size_t i = 0; i < *num_color; ++i) { - std::string colStr = colorArray[i].String(); - if (getWBColorEnumFromString(colStr, (*color)[i]) != 0) { - LOGERR("Invalid color: %s", colStr.c_str()); - delete[] *color; - delete[] *control; - *color = nullptr; - *control = nullptr; - return tvERROR_INVALID_PARAM; - } - } - - // Parse contextCaps - if (ExtractContextCaps(section, context_caps) != tvERROR_NONE) { - delete[] *color; - delete[] *control; - *color = nullptr; - *control = nullptr; - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -tvError_t AVOutputTV::GetBacklightCaps(int* max_backlight, tvContextCaps_t** context_caps) { - return GetCaps("Backlight", max_backlight, context_caps); -} - -tvError_t AVOutputTV::GetBrightnessCaps(int* max_brightness, tvContextCaps_t** context_caps) { - return GetCaps("Brightness", max_brightness, context_caps); -} - -tvError_t AVOutputTV::GetContrastCaps(int* max_contrast, tvContextCaps_t** context_caps) { - return GetCaps("Contrast", max_contrast, context_caps); -} - -tvError_t AVOutputTV::GetSharpnessCaps(int* max_sharpness, tvContextCaps_t** context_caps) { - return GetCaps("Sharpness", max_sharpness, context_caps); -} - -tvError_t AVOutputTV::GetSaturationCaps(int* max_saturation, tvContextCaps_t** context_caps) { - return GetCaps("Saturation", max_saturation, context_caps); -} - -tvError_t AVOutputTV::GetHueCaps(int* max_hue, tvContextCaps_t** context_caps) { - return GetCaps("Hue", max_hue, context_caps); -} - -tvError_t AVOutputTV::GetLowLatencyStateCaps(int* max_latency, tvContextCaps_t ** context_caps){ - return GetCaps("LowLatencyState", max_latency, context_caps); -} - -// PrecisionDetail -tvError_t AVOutputTV::GetPrecisionDetailCaps(int * maxPrecision, tvContextCaps_t ** context_caps) { - return GetCaps("PrecisionDetail", maxPrecision, context_caps); -} - -// AISuperResolution -tvError_t AVOutputTV::GetAISuperResolutionCaps(int * maxAISuperResolution, tvContextCaps_t ** context_caps) { - return GetCaps("AISuperResolution", maxAISuperResolution, context_caps); -} - -// MEMC -tvError_t AVOutputTV::GetMEMCCaps(int * maxMEMC, tvContextCaps_t ** context_caps) { - return GetCaps("MEMC", maxMEMC, context_caps); -} - -tvError_t AVOutputTV::GetColorTemperatureCaps(tvColorTemp_t** color_temp, size_t* num_color_temp, tvContextCaps_t** context_caps) { - LOGINFO("Entry\n"); - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - std::string key = "ColorTemperature"; - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - JsonArray optionsArray = rangeInfo["options"].Array(); - - *num_color_temp = optionsArray.Length(); - *color_temp = static_cast(malloc(*num_color_temp * sizeof(tvColorTemp_t))); - if (!(*color_temp)) { - return tvERROR_GENERAL; - } - - for (size_t i = 0; i < *num_color_temp; ++i) { - std::string tempStr = optionsArray[i].String(); - if (tempStr == "Standard") (*color_temp)[i] = tvColorTemp_STANDARD; - else if (tempStr == "Warm") (*color_temp)[i] = tvColorTemp_WARM; - else if (tempStr == "Cold") (*color_temp)[i] = tvColorTemp_COLD; - else if (tempStr == "UserDefined") (*color_temp)[i] = tvColorTemp_USER; - else if (tempStr == "Supercold") (*color_temp)[i] = tvColorTemp_SUPERCOLD; - else if (tempStr == "BoostStandard") (*color_temp)[i] = tvColorTemp_BOOST_STANDARD; - else if (tempStr == "BoostWarm") (*color_temp)[i] = tvColorTemp_BOOST_WARM; - else if (tempStr == "BoostCold") (*color_temp)[i] = tvColorTemp_BOOST_COLD; - else if (tempStr == "BoostUserDefined") (*color_temp)[i] = tvColorTemp_BOOST_USER; - else if (tempStr == "BoostSupercold") (*color_temp)[i] = tvColorTemp_BOOST_SUPERCOLD; - else (*color_temp)[i] = tvColorTemp_STANDARD; - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - free(*color_temp); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - - -tvError_t AVOutputTV::GetSdrGammaCaps(tvSdrGamma_t** sdr_gamma, size_t* num_sdr_gamma, tvContextCaps_t** context_caps) { - LOGINFO("Entry\n"); - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - std::string key = "SDRGamma"; - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - JsonArray optionsArray = rangeInfo["options"].Array(); - - *num_sdr_gamma = optionsArray.Length(); - *sdr_gamma = static_cast(malloc(*num_sdr_gamma * sizeof(tvSdrGamma_t))); - if (!(*sdr_gamma)) { - return tvERROR_GENERAL; - } - - for (size_t i = 0; i < *num_sdr_gamma; ++i) { - std::string gammaStr = optionsArray[i].String(); - if (gammaStr == "1.8") (*sdr_gamma)[i] = tvSdrGamma_1_8; - else if (gammaStr == "1.9") (*sdr_gamma)[i] = tvSdrGamma_1_9; - else if (gammaStr == "2.0") (*sdr_gamma)[i] = tvSdrGamma_2_0; - else if (gammaStr == "2.1") (*sdr_gamma)[i] = tvSdrGamma_2_1; - else if (gammaStr == "2.2") (*sdr_gamma)[i] = tvSdrGamma_2_2; - else if (gammaStr == "2.3") (*sdr_gamma)[i] = tvSdrGamma_2_3; - else if (gammaStr == "2.4") (*sdr_gamma)[i] = tvSdrGamma_2_4; - else if (gammaStr == "BT.1886") (*sdr_gamma)[i] = tvSdrGamma_BT_1886; - else (*sdr_gamma)[i] = tvSdrGamma_INVALID; - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - free(*sdr_gamma); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} -tvError_t AVOutputTV::GetTVDimmingModeCaps(tvDimmingMode_t** dimming_mode, size_t* num_dimming_mode, tvContextCaps_t** context_caps){ - LOGINFO("Entry\n"); - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - std::string key = "DimmingMode"; - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - JsonArray optionsArray = rangeInfo["options"].Array(); - *num_dimming_mode = optionsArray.Length(); - *dimming_mode = static_cast(malloc(*num_dimming_mode * sizeof(tvDimmingMode_t))); - if (!(*dimming_mode)) { - return tvERROR_GENERAL; - } - - for (size_t i = 0; i < *num_dimming_mode; ++i) { - std::string modeStr = optionsArray[i].String(); - if (modeStr == "Fixed") (*dimming_mode)[i] = tvDimmingMode_Fixed; - else if (modeStr == "Local") (*dimming_mode)[i] = tvDimmingMode_Local; - else if (modeStr == "Global") (*dimming_mode)[i] = tvDimmingMode_Global; - else (*dimming_mode)[i] = tvDimmingMode_MAX; - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - free(*dimming_mode); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; - -} - -tvError_t AVOutputTV::GetAspectRatioCaps(tvDisplayMode_t** aspect_ratio, size_t* num_aspect_ratio, tvContextCaps_t** context_caps) { - LOGINFO("Entry\n"); - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - std::string key = "AspectRatio"; - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - JsonArray optionsArray = rangeInfo["options"].Array(); - - *num_aspect_ratio = optionsArray.Length(); - *aspect_ratio = static_cast(malloc(*num_aspect_ratio * sizeof(tvDisplayMode_t))); - if (!(*aspect_ratio)) { - return tvERROR_GENERAL; - } - - for (size_t i = 0; i < *num_aspect_ratio; ++i) { - std::string aspectStr = optionsArray[i].String(); - if (aspectStr == "TV AUTO") (*aspect_ratio)[i] = tvDisplayMode_AUTO; - else if (aspectStr == "TV DIRECT") (*aspect_ratio)[i] = tvDisplayMode_DIRECT; - else if (aspectStr == "TV FULL") (*aspect_ratio)[i] = tvDisplayMode_FULL; - else if (aspectStr == "TV NORMAL") (*aspect_ratio)[i] = tvDisplayMode_NORMAL; - else if (aspectStr == "TV 16X9 STRETCH") (*aspect_ratio)[i] = tvDisplayMode_16x9; - else if (aspectStr == "TV 4X3 PILLARBOX") (*aspect_ratio)[i] = tvDisplayMode_4x3; - else if (aspectStr == "TV ZOOM") (*aspect_ratio)[i] = tvDisplayMode_ZOOM; - else (*aspect_ratio)[i] = tvDisplayMode_MAX; - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - free(*aspect_ratio); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -tvError_t AVOutputTV::GetTVPictureModeCaps(tvPQModeIndex_t** mode, size_t* num_pic_modes, tvContextCaps_t** context_caps) { - LOGINFO("Entry\n"); - JsonObject root; - if (ReadJsonFile(root) != tvERROR_NONE) { - return tvERROR_GENERAL; - } - - std::string key = "PictureMode"; - if (!root.HasLabel(key.c_str())) { - LOGWARN("AVOutputPlugins: %s: Missing '%s' label", __FUNCTION__, key.c_str()); - return tvERROR_GENERAL; - } - - JsonObject data = root[key.c_str()].Object(); - if (!data.HasLabel("platformSupport") || !data["platformSupport"].Boolean()) { - LOGWARN("AVOutputPlugins: %s: Platform support is false", __FUNCTION__); - return tvERROR_OPERATION_NOT_SUPPORTED; - } - - JsonObject rangeInfo = data["rangeInfo"].Object(); - JsonArray optionsArray = rangeInfo["options"].Array(); - - *num_pic_modes = optionsArray.Length(); - *mode = static_cast(malloc(*num_pic_modes * sizeof(tvPQModeIndex_t))); - if (!(*mode)) { - return tvERROR_GENERAL; - } - - for (size_t i = 0; i < *num_pic_modes; ++i) { - std::string modeStr = optionsArray[i].String(); - - if (modeStr == "Standard") (*mode)[i] = PQ_MODE_STANDARD; - else if (modeStr == "Vivid") (*mode)[i] = PQ_MODE_VIVID; - else if (modeStr == "EnergySaving" || modeStr == "Energy Saving") (*mode)[i] = PQ_MODE_ENERGY_SAVING; - else if (modeStr == "Theater") (*mode)[i] = PQ_MODE_THEATER; - else if (modeStr == "Game") (*mode)[i] = PQ_MODE_GAME; - else if (modeStr == "Sports") (*mode)[i] = PQ_MODE_SPORTS; - else if (modeStr == "AI PQ") (*mode)[i] = PQ_MODE_AIPQ; - else if (modeStr == "Dark") (*mode)[i] = PQ_MODE_DARK; - else if (modeStr == "Bright") (*mode)[i] = PQ_MODE_BRIGHT; - else if (modeStr == "IQ") (*mode)[i] = PQ_MODE_IQ; - else (*mode)[i] = PQ_MODE_INVALID; - } - - if (ExtractContextCaps(data, context_caps) != tvERROR_NONE) { - free(*mode); - return tvERROR_GENERAL; - } - - return tvERROR_NONE; -} - -#endif - int AVOutputTV::ReadCapablitiesFromConf(std::string param, capDetails_t& info) { int ret = 0; From 10dbd4920835a43be19f412e5fd512d4e81e70ce Mon Sep 17 00:00:00 2001 From: aktamilbe <59253707+aktamilbe@users.noreply.github.com> Date: Fri, 18 Jul 2025 05:57:31 +0100 Subject: [PATCH 13/14] RDKEMW-5197 : Discard CMS Changes --- AVOutput/AVOutputTV.h | 34 ---------------------------------- AVOutput/AVOutputTVHelper.cpp | 7 ++++--- 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/AVOutput/AVOutputTV.h b/AVOutput/AVOutputTV.h index ddfd384d..e383b330 100644 --- a/AVOutput/AVOutputTV.h +++ b/AVOutput/AVOutputTV.h @@ -73,8 +73,6 @@ #define STRING_COLORTEMPERATURE "ColorTemperature." #define CREATE_DIRTY(__X__) (__X__+=STRING_DIRTY) #define CAPABLITY_FILE_NAME "pq_capabilities.ini" -#define CAPABILITY_FILE_NAMEV2 "/etc/pq_capabilities.json" - class CIniFile { @@ -439,38 +437,6 @@ class AVOutputTV : public AVOutputBase { static void initializeReverseMaps(); static const std::unordered_map backlightModeReverseMap; - tvError_t ReadJsonFile(JsonObject& root); - tvError_t ExtractContextCaps(const JsonObject& data, tvContextCaps_t** context_caps); - tvError_t ExtractRangeInfo(const JsonObject& data, int* max_value); - std::vector ParseContextCaps(const JsonObject& context); - tvContextCaps_t* AllocateContextCaps(const std::vector& contexts); - tvError_t GetCaps(const std::string& key, int* max_value, tvContextCaps_t** context_caps); - - tvError_t GetDVCalibrationCaps(tvDVCalibrationSettings_t **min_values, tvDVCalibrationSettings_t **max_values, tvContextCaps_t **context_caps); - tvError_t GetBacklightModeCaps(tvBacklightMode_t** backlight_mode, size_t* num_backlight_mode, tvContextCaps_t** context_caps); - tvError_t GetLocalContrastEnhancementCaps(int* maxLocalContrastEnhancement, tvContextCaps_t** context_caps); - tvError_t GetMPEGNoiseReductionCaps(int* maxMPEGNoiseReduction, tvContextCaps_t** context_caps); - tvError_t GetDigitalNoiseReductionCaps(int* maxDigitalNoiseReduction, tvContextCaps_t** context_caps); - tvError_t GetMultiPointWBCaps(int* num_hal_matrix_points, - int* rgb_min, - int* rgb_max, - int* num_ui_matrix_points, - double** ui_matrix_positions, - tvContextCaps_t** context_caps); - tvError_t GetCMSCaps(int* max_hue, - int* max_saturation, - int* max_luma, - tvDataComponentColor_t** color, - tvComponentType_t** component, - size_t* num_color, - size_t* num_component, - tvContextCaps_t** context_caps); - tvError_t GetCustom2PointWhiteBalanceCaps( int *min_gain, - int *min_offset, int *max_gain, - int *max_offset, tvWBColor_t **color, - tvWBControl_t **control, size_t* num_color, - size_t* num_control, tvContextCaps_t ** context_caps); - uint32_t getPQCapabilityWithContext( const std::function& getCapsFunc, const JsonObject& parameters, diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 1581ca51..966ec70b 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -1377,8 +1377,9 @@ namespace Plugin { if (m_MEMCStatus == tvERROR_NONE) { updateAVoutputTVParamV2("sync", "MEMC", paramJson, PQ_PARAM_MEMC, level); } - - m_cmsStatus = GetCMSCaps(&m_maxCmsHue, &m_maxCmsSaturation, &m_maxCmsLuma, + + //Commented due to missing HAL implementation + /*m_cmsStatus = GetCMSCaps(&m_maxCmsHue, &m_maxCmsSaturation, &m_maxCmsLuma, &m_cmsColorArr, &m_cmsComponentArr, &m_numColor, &m_numComponent, &m_cmsCaps); if (m_cmsStatus == tvERROR_NONE) { @@ -1391,7 +1392,7 @@ namespace Plugin { m_cmsComponentList.push_back(componentStr); } syncCMSParamsV2(); - } + }*/ if(m_cmsStatus == tvERROR_OPERATION_NOT_SUPPORTED) { syncCMSParams(); From c891f28552aff70956f8c4fd1da087e244b573ef Mon Sep 17 00:00:00 2001 From: skk451 Date: Tue, 29 Jul 2025 14:30:58 +0100 Subject: [PATCH 14/14] RDKEMW-5197 Sync code updated --- AVOutput/AVOutputTV.cpp | 65 ++++++++++---------------- AVOutput/AVOutputTVHelper.cpp | 86 +++++++++-------------------------- 2 files changed, 44 insertions(+), 107 deletions(-) diff --git a/AVOutput/AVOutputTV.cpp b/AVOutput/AVOutputTV.cpp index 4b393dd7..34ff9c82 100644 --- a/AVOutput/AVOutputTV.cpp +++ b/AVOutput/AVOutputTV.cpp @@ -799,6 +799,7 @@ namespace Plugin { LOGWARN("AVOutputPlugins: %s: result: %d", __FUNCTION__, result); if (result != tvERROR_NONE) { + response["platformSupport"] = false; returnResponse(false); } @@ -963,6 +964,7 @@ namespace Plugin { if (ret != tvERROR_NONE) { LOGWARN("GetMultiPointWBCaps failed: %s", getErrorString(ret).c_str()); + response["platformSupport"] = false; returnResponse(false); } response["platformSupport"] = true; @@ -1032,6 +1034,7 @@ namespace Plugin { tvError_t err = GetColorTemperatureCaps(&color_temp, &num_color_temp, &context_caps); if (err != tvERROR_NONE) { + response["platformSupport"] = false; return err; } @@ -1059,6 +1062,7 @@ namespace Plugin { tvError_t err = GetSdrGammaCaps(&sdr_gamma, &num_sdr_gamma, &context_caps); if (err != tvERROR_NONE) { + response["platformSupport"] = false; return err; } @@ -1093,6 +1097,7 @@ namespace Plugin { tvError_t err = GetTVDimmingModeCaps(&dimming_mode, &num_dimming_mode, &context_caps); if (err != tvERROR_NONE) { + response["platformSupport"] = false; return err; } @@ -1114,8 +1119,6 @@ namespace Plugin { uint32_t AVOutputTV::getZoomModeCapsV2(const JsonObject& parameters, JsonObject& response) { - response["platformSupport"] = true; - JsonArray optionsArray; for (size_t i = 0; i < m_numAspectRatio; ++i) { auto it = zoomModeReverseMap.find(m_aspectRatio[i]); @@ -1123,17 +1126,18 @@ namespace Plugin { optionsArray.Add(it->second); } } - response["options"] = optionsArray; + bool platformSupport = (optionsArray.Length() > 0); + + response["platformSupport"] = platformSupport; + response["options"] = optionsArray; response["context"] = parseContextCaps(m_aspectRatioCaps); - returnResponse(true); + returnResponse(platformSupport); } uint32_t AVOutputTV::getPictureModeCapsV2(const JsonObject& parameters, JsonObject& response) { - response["platformSupport"] = true; - JsonArray optionsArray; for (size_t i = 0; i < m_numPictureModes; ++i) { auto it = pqModeMap.find(m_pictureModes[i]); @@ -1141,17 +1145,18 @@ namespace Plugin { optionsArray.Add(it->second); } } - response["options"] = optionsArray; + bool platformSupport = (optionsArray.Length() > 0); + + response["platformSupport"] = platformSupport; + response["options"] = optionsArray; response["context"] = parseContextCaps(m_pictureModeCaps); - returnResponse(true); + returnResponse(platformSupport); } uint32_t AVOutputTV::getAutoBacklightModeCapsV2(const JsonObject& parameters, JsonObject& response) { - response["platformSupport"] = true; - JsonArray optionsArray; for (size_t i = 0; i < m_numBacklightModes; ++i) { switch (m_backlightModes[i]) { @@ -1169,45 +1174,19 @@ namespace Plugin { break; } } - response["options"] = optionsArray; + bool platformSupport = (optionsArray.Length() > 0); + + response["platformSupport"] = platformSupport; + response["options"] = optionsArray; response["context"] = parseContextCaps(m_backlightModeCaps); - returnResponse(true); + returnResponse(platformSupport); } + uint32_t AVOutputTV::getDolbyVisionCalibrationCaps(const JsonObject& parameters, JsonObject& response) { - tvDVCalibrationSettings_t* min_values = nullptr; - tvDVCalibrationSettings_t* max_values = nullptr; - tvContextCaps_t* context_caps = nullptr; - - if (GetDVCalibrationCaps(&min_values, &max_values, &context_caps) != tvERROR_NONE) { - returnResponse(false); - } - - // Set platform support - response["platformSupport"] = true; - - // Add all range fields (flattened as per expected JSON) - response["rangeTmax"] = JsonObject({{"from", min_values->Tmax}, {"to", max_values->Tmax}}); - response["rangeTmin"] = JsonObject({{"from", min_values->Tmin}, {"to", max_values->Tmin}}); - response["rangeTgamma"] = JsonObject({{"from", min_values->Tgamma}, {"to", max_values->Tgamma}}); - response["rangeRx"] = JsonObject({{"from", min_values->Rx}, {"to", max_values->Rx}}); - response["rangeRy"] = JsonObject({{"from", min_values->Ry}, {"to", max_values->Ry}}); - response["rangeGx"] = JsonObject({{"from", min_values->Gx}, {"to", max_values->Gx}}); - response["rangeGy"] = JsonObject({{"from", min_values->Gy}, {"to", max_values->Gy}}); - response["rangeBx"] = JsonObject({{"from", min_values->Bx}, {"to", max_values->Bx}}); - response["rangeBy"] = JsonObject({{"from", min_values->By}, {"to", max_values->By}}); - response["rangeWx"] = JsonObject({{"from", min_values->Wx}, {"to", max_values->Wx}}); - response["rangeWy"] = JsonObject({{"from", min_values->Wy}, {"to", max_values->Wy}}); - - // Add context list - response["context"] = parseContextCaps(context_caps); - - // Indicate success - response["success"] = true; - returnResponse(true); } @@ -5215,6 +5194,7 @@ namespace Plugin { if (ret != tvERROR_NONE) { LOGERR("GetCMSCaps failed with error: %d", ret); + response["platformSupport"] = false; returnResponse(false); } response["platformSupport"] = true; @@ -5721,6 +5701,7 @@ namespace Plugin { if (ret != tvERROR_NONE) { LOGERR("GetCustom2PointWhiteBalanceCaps failed with error: %d", ret); + response["platformSupport"] = false; returnResponse(false); } diff --git a/AVOutput/AVOutputTVHelper.cpp b/AVOutput/AVOutputTVHelper.cpp index 966ec70b..41a32bb5 100644 --- a/AVOutput/AVOutputTVHelper.cpp +++ b/AVOutput/AVOutputTVHelper.cpp @@ -1281,9 +1281,6 @@ namespace Plugin { updateAVoutputTVParamV2("sync", "ColorTemp", paramJson, PQ_PARAM_COLOR_TEMPERATURE,level); } - // HDRMode - updateAVoutputTVParam("sync", "HDRMode", info, PQ_PARAM_DOLBY_MODE, level); - // DimmingMode m_dimmingModeStatus = GetTVDimmingModeCaps(&m_dimmingModes, &m_numdimmingModes, &m_dimmingModeCaps); LOGINFO("GetTVDimmingModeCaps returned status: %d, numdimmingModes: %d", m_dimmingModeStatus, m_numdimmingModes); @@ -1297,27 +1294,7 @@ namespace Plugin { LOGINFO("Calling GetBacklightCaps..."); m_backlightStatus = GetBacklightCaps(&m_maxBacklight, &m_backlightCaps); LOGINFO("GetBacklightCaps returned status: %d, maxBacklight: %d", m_backlightStatus, m_maxBacklight); -#if DEBUG - if (m_backlightCaps) - { - LOGINFO("Backlight caps pointer is valid. Num contexts: %zu", m_backlightCaps->num_contexts); - for (size_t i = 0; i < m_backlightCaps->num_contexts; ++i) { - const auto& context = m_backlightCaps->contexts[i]; - std::string pqModeStr = AVOutputTV::pqModeMap.count(context.pq_mode) ? - AVOutputTV::pqModeMap.at(context.pq_mode) : "Unknown"; - std::string formatStr = AVOutputTV::videoFormatMap.count(context.videoFormatType) ? - AVOutputTV::videoFormatMap.at(context.videoFormatType) : "Unknown"; - std::string srcStr = AVOutputTV::videoSrcMap.count(context.videoSrcType) ? - AVOutputTV::videoSrcMap.at(context.videoSrcType) : "Unknown"; - LOGINFO("Context[%zu]: PQMode = %s (%d), Format = %s (%d), Source = %s (%d)", - i, pqModeStr.c_str(), context.pq_mode, - formatStr.c_str(), context.videoFormatType, - srcStr.c_str(), context.videoSrcType); - } - } else { - LOGWARN("Backlight caps pointer is null."); - } -#endif + if (m_backlightStatus == tvERROR_OPERATION_NOT_SUPPORTED) { updateAVoutputTVParam("sync", "Backlight", info, PQ_PARAM_BACKLIGHT, level); } else { @@ -1398,11 +1375,14 @@ namespace Plugin { syncCMSParams(); } - syncWBParams(); + //syncWBParams(); Enable once Get2PointWBCaps is implemented + if(m_pictureModeStatus == tvERROR_OPERATION_NOT_SUPPORTED) + { // Dolby Vision Mode info.format = "DV"; // Sync only for Dolby updateAVoutputTVParam("sync", "DolbyVisionMode", info, PQ_PARAM_DOLBY_MODE, level); + } LOGINFO("Exit %s : pqmode : %s source : %s format : %s\n", __FUNCTION__, pqmode.c_str(), source.c_str(), format.c_str()); return tvERROR_NONE; @@ -1464,9 +1444,7 @@ namespace Plugin { break; } } -#if DEBUG - LOGINFO("Got mode string from TR181: %s -> index=%d", modeStr.c_str(), modeIndex); -#endif + tvError_t tv_err = SaveSourcePictureMode(ctx.videoSrcType, ctx.videoFormatType, modeIndex); if (tv_err != tvERROR_NONE) { LOGWARN("Failed SaveSourcePictureMode for %s / %s\n", sourceStr.c_str(), formatStr.c_str()); @@ -2182,6 +2160,11 @@ namespace Plugin { inputInfo.source = source; inputInfo.format = format; + JsonObject paramJson; + paramJson["pictureMode"] = inputInfo.pqmode; + paramJson["videoSource"] = inputInfo.source; + paramJson["videoFormat"] = inputInfo.format; + memset(¶m, 0, sizeof(param)); tr181ErrorCode_t err = getLocalParam(rfc_caller_id, AVOUTPUT_ASPECTRATIO_RFC_PARAM, ¶m); if ( tr181Success == err ) { @@ -2226,14 +2209,17 @@ namespace Plugin { LOGERR("AspectRatio set failed: %s\n",getErrorString(ret).c_str()); } else { - //Save DisplayMode to ssm_data - int retval=updateAVoutputTVParam("set","ZoomMode",inputInfo,PQ_PARAM_ASPECT_RATIO,mode); - - if(retval != 0) { + if (m_aspectRatioStatus == tvERROR_OPERATION_NOT_SUPPORTED) { + int retval=updateAVoutputTVParam("set","ZoomMode",inputInfo,PQ_PARAM_ASPECT_RATIO,mode); + if(retval != 0) { LOGERR("Failed to Save DisplayMode to ssm_data\n"); ret = tvERROR_GENERAL; + } + LOGINFO("Aspect Ratio initialized successfully, value: %s\n", param.value); + } + else { + updateAVoutputTVParamV2("set", "ZoomMode", paramJson, PQ_PARAM_ASPECT_RATIO,mode); } - LOGINFO("Aspect Ratio initialized successfully, value: %s\n", param.value); } } @@ -2760,10 +2746,7 @@ namespace Plugin { if (caps && caps->num_contexts > 0) { for (size_t i = 0; i < caps->num_contexts; ++i) { const tvConfigContext_t& available = caps->contexts[i]; -#if DEBUG - LOGINFO("Context[%zu]: PQMode=%d, Format=%d, Source=%d", i, - available.pq_mode, available.videoFormatType, available.videoSrcType); -#endif + if (available.videoSrcType == validContext.videoSrcType && available.videoFormatType == validContext.videoFormatType && available.pq_mode == validContext.pq_mode) { @@ -2975,22 +2958,7 @@ namespace Plugin { const auto resolvedPicModes = resolveParam("pictureMode", curPicMode); const auto resolvedFormats = resolveParam("videoFormat", curFormat); const auto resolvedSources = resolveParam("videoSource", curSource); -#if DEBUG - // Helper function to log vector content - auto logResolvedValues = [&](const std::string& label, const std::vector& values) { - std::string joined; - for (const auto& val : values) { - if (!joined.empty()) joined += ", "; - joined += val; - } - LOGINFO("Resolved %s: [%s]", label.c_str(), joined.c_str()); - }; - // Debug logs - logResolvedValues("pictureMode", resolvedPicModes); - logResolvedValues("videoSource", resolvedSources); - logResolvedValues("videoFormat", resolvedFormats); -#endif // Check if current combination exists in resolved sets for (const auto& pm : resolvedPicModes) { @@ -3135,9 +3103,7 @@ namespace Plugin { const JsonObject& parameters, tvPQParameterIndex_t pqParamIndex,int level) { -#if DEBUG LOGINFO("Entry %s: Action: %s, Param: %s, Level: %d", __FUNCTION__, action.c_str(), tr181ParamName.c_str(), level); -#endif int ret = 0; const bool isSet = (action == "set"); const bool isReset = (action == "reset"); @@ -3145,15 +3111,7 @@ namespace Plugin { std::vector validContexts = getValidContextsFromParameters(parameters, tr181ParamName); LOGINFO("%s: Number of validContexts = %zu", __FUNCTION__, validContexts.size()); -#if DEBUG - for (const auto& ctx : validContexts) { - std::string pqStr = pqModeMap.count(ctx.pq_mode) ? pqModeMap.at(ctx.pq_mode) : std::to_string(ctx.pq_mode); - std::string fmtStr = videoFormatMap.count(ctx.videoFormatType) ? videoFormatMap.at(ctx.videoFormatType) : std::to_string(ctx.videoFormatType); - std::string srcStr = videoSrcMap.count(ctx.videoSrcType) ? videoSrcMap.at(ctx.videoSrcType) : std::to_string(ctx.videoSrcType); - LOGINFO("Valid Context - PQMode: %s, Format: %s, Source: %s", pqStr.c_str(), fmtStr.c_str(), srcStr.c_str()); - } -#endif if (validContexts.empty()) { LOGWARN("%s: No valid contexts found for parameters", __FUNCTION__); return (int)tvERROR_GENERAL; @@ -3182,9 +3140,7 @@ namespace Plugin { for (const auto& ctx : validContexts) { for (const auto& colorStr : colors) { for (const auto& componentStr : components) { -#if DEBUG - LOGINFO("%s: Processing Color: %s, Component: %s", __FUNCTION__, colorStr.c_str(), componentStr.c_str()); -#endif + tvPQParameterIndex_t pqIndex; if (convertCMSParamToPQEnum(componentStr, colorStr, pqIndex) != 0) { LOGERR("%s: convertCMSParamToPQEnum failed for color: %s, component: %s",