diff --git a/.github/workflows/native_full_build.yml b/.github/workflows/native_full_build.yml index 0c481434..8764bae0 100644 --- a/.github/workflows/native_full_build.yml +++ b/.github/workflows/native_full_build.yml @@ -4,7 +4,7 @@ on: push: branches: [ main, 'sprint/**', 'release/**', develop ] pull_request: - branches: [ main, 'sprint/**', 'release/**', topic/RDK*, develop ] + branches: [ main, 'sprint/**', 'release/**', topic/RDK*, feature/RDK*, develop ] jobs: build-devicesettings-on-pr: @@ -23,4 +23,4 @@ jobs: sh -e cov_build.sh env: GITHUB_TOKEN: ${{ secrets.RDKCM_RDKE }} - RDK_PLATFORM_SOC: broadcom \ No newline at end of file + RDK_PLATFORM_SOC: broadcom diff --git a/.gitignore b/.gitignore index ec702b33..42473dff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,54 @@ /install/bin/TODO /install/lib/TODO + +*.o +*.so +# test samples +sample/IsOutputHDR +sample/enableSurroundDecoder +sample/getAudioConfig +sample/getCPUTemp +sample/getDSHalVersion +sample/getDisplayAttributes +sample/getDrmHdmiStatus +sample/getEDIDBytes +sample/getFPBrightness +sample/getHDCPStatus +sample/getHdmiPreference +sample/getHostEDID +sample/getSocIDFromSDK +sample/getVideoOutputPorts +sample/getZoomSettings +sample/hdmiIn +sample/isDisplayConnected +sample/ms12ProfileTest +sample/powerModeTest +sample/resetOutputToSDR +sample/setARCSAD +sample/setAudioDucking +sample/setAudioEnable +sample/setAudioGain +sample/setAudioLevel +sample/setAudioMode +sample/setAudioMute +sample/setBassEnhancer +sample/setDRCMode +sample/setDialogEnhancement +sample/setFPBrightness +sample/setFPColor +sample/setFPColorRGB +sample/setFPTextDisplay +sample/setFPTextTimeFormat +sample/setGraphicEQ +sample/setHdmiPreference +sample/setMISteering +sample/setResolution +sample/setSurroundVirtualizer +sample/setVolumeLeveller +sample/setZoomSettings +sample/testFrontPanel + +.cache +.clang-format +compile_commands.json +.harper-dictionary.txt diff --git a/build_dependencies.sh b/build_dependencies.sh index 090f105a..566fca25 100644 --- a/build_dependencies.sh +++ b/build_dependencies.sh @@ -47,7 +47,7 @@ cd rfc autoreconf -i ./configure --enable-rfctool=yes --enable-tr181set=yes cd rfcapi -make librfcapi_la_CPPFLAGS="-I/usr/include/cjson" +make CXXFLAGS="-DUSE_IARMBUS" librfcapi_la_CPPFLAGS="-I/usr/include/cjson" make install export RFC_PATH=$ROOT/rfc diff --git a/ds/Makefile b/ds/Makefile index e7c41ddd..d69caba9 100644 --- a/ds/Makefile +++ b/ds/Makefile @@ -20,9 +20,11 @@ RM := rm -rf CFLAGS += -std=c++0x -g -fPIC -D_REENTRANT -Wall LIBNAME := ds LIBNAMEFULL := lib$(LIBNAME).so -LIBNAMECLI := lib$(LIBNAME)-cli.so +LIBNAMECLI := lib$(LIBNAME)-cli.so INSTALL := $(PWD)/install OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) +# In future add a conditional to choose implementation class based on build configuration +OBJS += iarm/IarmImpl.o #$(PWD)/config should be first include path # to override generic configs ifneq ($(STANDALONE_BUILD_ENABLED),y) diff --git a/ds/dslogger.cpp b/ds/dslogger.cpp index be81ee48..2fd2f81e 100644 --- a/ds/dslogger.cpp +++ b/ds/dslogger.cpp @@ -25,11 +25,13 @@ * @{ **/ +#include +#include #include "dslogger.h" -#include -#define MAX_LOG_BUFF 500 +#define unlikely(x) (__builtin_expect(!!(x), 0)) +#define MAX_LOG_BUFF 512 DS_LogCb logCb = NULL; @@ -38,26 +40,31 @@ void DS_RegisterForLog(DS_LogCb cb) logCb = cb; } -int ds_log(int priority,const char *format, ...) +int ds_log(int priority, const char* fileName, int lineNum, const char *format, ...) { - char tmp_buff[MAX_LOG_BUFF]; + char tmp_buff[MAX_LOG_BUFF] = {'\0'}; + + int offset = snprintf(tmp_buff, MAX_LOG_BUFF, "[%s:%d] ", fileName, lineNum); + + // formatting error + if (unlikely(offset < 0)) { + offset = 0; + tmp_buff[0] = '\0'; // Ensure buffer is null-terminated if snprintf fails + } + va_list args; va_start(args, format); - vsnprintf(tmp_buff,MAX_LOG_BUFF-1,format, args); + vsnprintf(tmp_buff + offset, MAX_LOG_BUFF - offset, format, args); va_end(args); - if(logCb != NULL) - { - logCb(priority,tmp_buff); - } - else - { - return printf(tmp_buff); + + if (nullptr != logCb) { + logCb(priority, tmp_buff); + } else { + return printf("%s\n", tmp_buff); } + return 0; } - - - /** @} */ /** @} */ diff --git a/ds/hdmiIn.cpp b/ds/hdmiIn.cpp index 18b2ac97..927df499 100755 --- a/ds/hdmiIn.cpp +++ b/ds/hdmiIn.cpp @@ -678,6 +678,17 @@ void HdmiInput::getHdmiVersion (int iHdmiPort, dsHdmiMaxCapabilityVersion_t *cap printf ("%s:%d - HDMI Compatibility Version = %d\n", __PRETTY_FUNCTION__, __LINE__, *capversion); } +dsError_t HdmiInput::getHDMIARCPortId(int &portId) { + + dsError_t error = dsERR_GENERAL; + error = dsGetHDMIARCPortId(portId); + if(dsERR_NONE != error) + { + portId = -1; + } + return error; +} + } diff --git a/ds/host.cpp b/ds/host.cpp index d621e479..e2475e14 100644 --- a/ds/host.cpp +++ b/ds/host.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2025 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,25 +28,20 @@ #include -#include -#include -#include "iarmProxy.hpp" +#include + #include "audioOutputPortConfig.hpp" #include "videoOutputPortConfig.hpp" #include "list.hpp" #include "host.hpp" #include "videoDeviceConfig.hpp" -#include "dsVideoPort.h" -#include "dsVideoDevice.h" #include "dsAudio.h" -#include "dsDisplay.h" -#include "dslogger.h" #include "dsHost.h" -#include "dsTypes.h" #include "unsupportedOperationException.hpp" -#include "hostEDID.hpp" #include "dsInternal.h" +#include "iarm/IarmImpl.hpp" + /** * @file host.cpp * @brief The host module is the central module of the Device Settings module. @@ -56,24 +51,16 @@ using namespace std; namespace device { - - const int Host::kPowerOn = dsPOWER_ON; - const int Host::kPowerOff = dsPOWER_OFF; - const int Host::kPowerStandby = dsPOWER_STANDBY; - - - Host::Host() - { - // TODO Auto-generated destructor stub - } - - Host::~Host() { - if (true) - { - IARMProxy::getInstance().UnRegisterPowerEventHandler(); - } - } +Host::Host() + : m_impl(nullptr) +{ +} + +Host::~Host() +{ + m_impl = nullptr; +} /** * @addtogroup dssettingshostapi @@ -103,145 +90,6 @@ namespace device return instance; } - -/** - * @fn void Host::addPowerModeListener(PowerModeChangeListener *l) - * @brief This API is used to register listeners for Power Mode change event. - * The listener object is created by application and should be released by the application once the listener is removed. - * Listeners will be notified with the new mode via the listener's powerModeChanged() callback. - * - * @param[in] PowerModeChangeListener Pointer to Power Mode change listener - * - * @return None - */ - void Host::addPowerModeListener(PowerModeChangeListener *l) - { - std::list < PowerModeChangeListener* > ::iterator it; - - it = find (powerEvntListeners.begin(),powerEvntListeners.end(), l); - if (it == powerEvntListeners.end()) - { - powerEvntListeners.push_back (l); - cout << "Added Power Mode listener...!\n"; - } - else - { - cout << "Already register for Power Mode Change\n"; - } - return ; - } - - -/** - * @fn void Host::removePowerModeChangeListener(PowerModeChangeListener *l) - * @brief This API is used to remove a listener from Power Mode change listener list. - * - * @param[in]PowerModeChangeListener The listener to remove. - * - * @return None - */ - void Host::removePowerModeChangeListener(PowerModeChangeListener *l) - { - std::list < PowerModeChangeListener* > ::iterator it ; - it = find (powerEvntListeners.begin(),powerEvntListeners.end(), l); - if (it == powerEvntListeners.end()) - { - cout << "Not Registered for Power Mode change yet...!\n"; - } - else - { - powerEvntListeners.erase (it); - cout << "Removed from Power Mode listener group..!\n"; - } - return; - } - - -/** - * @fn void Host::addDisplayConnectionListener (DisplayConnectionChangeListener *l) - * @brief This API is used to register listeners for Display connection change event. - * The listener will be notified if Display device is connected/disconnected from the video output port. - * The notification only carries the state change of the connection. - * It does not carry any other system state change that may have been triggered by the connection. - * The application is responsible to query the various parts of system to detect any such change. - * For example, when a TV device is replaced, the application shall query the video output port again upon the connection - * for the new resolution supported by the TV. - * The listener object is created by application and should be released by the application once the listener is removed. - * - * @param[in] DisplayConnectionChangeListener Pointer to Display connection change listener - * - * @return None - */ - void Host::addDisplayConnectionListener (DisplayConnectionChangeListener *l) - { - std::list < DisplayConnectionChangeListener* > ::iterator it; - - it = find (dispEvntListeners.begin(), dispEvntListeners.end(), l); - if (it == dispEvntListeners.end()) - { - dispEvntListeners.push_back (l); - cout << "Added Display listener...!\n"; - } - else - { - cout << "Already registered to the Display listener\n"; - } - return ; - } - - -/** - * @fn void Host::removeDisplayConnectionListener (DisplayConnectionChangeListener *l) - * @brief This API is used to remove listeners from the Display connection change event list. - * - * @param[in] DisplayConnectionChangeListener The listener to remove - * - * @return None - */ - void Host::removeDisplayConnectionListener (DisplayConnectionChangeListener *l) - { - std::list < DisplayConnectionChangeListener* > ::iterator it ; - it = find (dispEvntListeners.begin(), dispEvntListeners.end(), l); - if (it == dispEvntListeners.end()) - { - cout << "Not Registered to Display Listener yet...!\n"; - } - else - { - dispEvntListeners.erase (it); - cout << "Removed from the Display listener...!\n"; - } - return; - } - - -/** - * @fn void Host::notifyPowerChange (const int mode) - * @brief This function is used to get the current power state. - * - * @param[in] mode Power mode of the decoder. - * @return None. - */ - void Host::notifyPowerChange (const int mode) - { - std::list < PowerModeChangeListener* > ::iterator it; - for ( it = powerEvntListeners.begin() ; it != powerEvntListeners.end(); it++ ) - { - (*it)->powerModeChanged (mode); - } - } - - void Host::notifyDisplayConnectionChange (int portHandle, bool newConnectionStatus) - { - std::list < DisplayConnectionChangeListener* > ::iterator it; - for ( it = dispEvntListeners.begin() ; it != dispEvntListeners.end(); it++ ) - { - (*it)->displayConnectionChanged(getVideoOutputPort(portHandle), newConnectionStatus); - getVideoOutputPort(portHandle).setDisplayConnected(newConnectionStatus); - } - } - - /** * @fn bool Host::setPowerMode(int mode) * @brief This API is used to change the power mode of the device. @@ -254,7 +102,7 @@ namespace device * * @return None */ - bool Host::setPowerMode(int mode) + bool Host::setPowerMode(int) { throw UnsupportedOperationException(); } @@ -603,7 +451,7 @@ namespace device void Host::getMS12ConfigDetails(std::string &configType) { dsError_t ret = dsERR_NONE; - char type[MS12_CONFIG_BUF_SIZE]; + char type[MS12_CONFIG_BUF_SIZE] = { 0 }; ret = dsGetMS12ConfigType(type); if (ret == dsERR_NONE) { @@ -913,11 +761,270 @@ namespace device printf ("%s:%d - Set Audio Mixer levels for audio input: %d with volume = %d\n", __PRETTY_FUNCTION__, __LINE__,aInput, volume); } +DefaultImpl& Host::impl() +{ + // lazy instantiation + if (!m_impl) { + m_impl = std::unique_ptr(new DefaultImpl()); + } + return *m_impl; +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInEventHotPlug(dsHdmiInPort_t port, bool isConnected) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInEventHotPlug called. port: %d, isConnected: %d", port, isConnected); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInEventSignalStatus(dsHdmiInPort_t port, dsHdmiInSignalStatus_t signalStatus) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInEventSignalStatus called. port: %d, signalStatus: %d", port, signalStatus); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInEventStatus(dsHdmiInPort_t activePort, bool isPresented) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInEventStatus called. activePort: %d, isPresented: %d", activePort, isPresented); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInVideoModeUpdate(dsHdmiInPort_t port, const dsVideoPortResolution_t& videoPortResolution) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInVideoModeUpdate called. port: %d, interlaced: %d", port, videoPortResolution.interlaced); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInAllmStatus(dsHdmiInPort_t port, bool allmStatus) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInAllmStatus called. port: %d, allmStatus: %d", port, allmStatus); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInAVIContentType(dsHdmiInPort_t port, dsAviContentType_t aviContentType) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInAVIContentType called. port: %d, aviContentType: %d", port, aviContentType); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInVRRStatus(dsHdmiInPort_t port, dsVRRType_t vrrType) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInVRRStatus called. port: %d, vrrType: %d", port, vrrType); +} + +/* virtual */ void Host::IHdmiInEvents::OnHdmiInAVLatency(int audioDelay, int videoDelay) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHdmiInAVLatency called. audioDelay: %d, videoDelay: %d", audioDelay, videoDelay); +} + +/* virtual */ void Host::IVideoDeviceEvents::OnDisplayFrameratePreChange(const std::string& frameRate) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnDisplayFrameratePreChange called. frameRate: %s", frameRate.c_str()); +} + +/* virtual */ void Host::IVideoDeviceEvents::OnDisplayFrameratePostChange(const std::string& frameRate) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnDisplayFrameratePostChange called. frameRate: %s", frameRate.c_str()); +} + +/* virtual */ void Host::IVideoDeviceEvents::OnZoomSettingsChanged(dsVideoZoom_t zoomSetting) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnZoomSettingsChanged called. zoomSetting: %d", zoomSetting); +} + +/* virtual */ void Host::IVideoOutputPortEvents::OnResolutionPreChange(int width, int height) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnResolutionPreChange called. width: %d, height: %d", width, height); +} + +/* virtual */ void Host::IVideoOutputPortEvents::OnResolutionPostChange(int width, int height) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnResolutionPostChange called. width: %d, height: %d", width, height); +} + +/* virtual */ void Host::IVideoOutputPortEvents::OnHDCPStatusChange(dsHdcpStatus_t hdcpStatus) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnHDCPStatusChange called. hdcpStatus: %d", hdcpStatus); +} + +/* virtual */ void Host::IVideoOutputPortEvents::OnVideoFormatUpdate(dsHDRStandard_t videoFormatHDR) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnVideoFormatUpdate called. videoFormatHDR: %d", videoFormatHDR); +} + +/* virtual */ void Host::IAudioOutputPortEvents::OnAssociatedAudioMixingChanged(bool mixing) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAssociatedAudioMixingChanged called. mixing: %d", mixing); +} +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioFaderControlChanged(int mixerBalance) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioFaderControlChanged called. mixerBalance: %d", mixerBalance); +} +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioPrimaryLanguageChanged(const std::string& primaryLanguage) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioPrimaryLanguageChanged called. primaryLanguage: %s", primaryLanguage.c_str()); +} + +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioSecondaryLanguageChanged(const std::string& secondaryLanguage) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioSecondaryLanguageChanged called. secondaryLanguage: %s", secondaryLanguage.c_str()); +} + +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioOutHotPlug(dsAudioPortType_t portType, uint32_t uiPortNumber, bool isPortConnected) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioOutHotPlug called. portType: %d, uiPortNumber: %d, isPortConnected: %d", portType, uiPortNumber, isPortConnected); +} +/* virtual */ void Host::IAudioOutputPortEvents::OnDolbyAtmosCapabilitiesChanged(dsATMOSCapability_t atmosCapability, bool status) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnDolbyAtmosCapabilitiesChanged called. atmosCapability: %d, status: %d", atmosCapability, status); } +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioPortStateChanged(dsAudioPortState_t audioPortState) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioPortStateChanged called. audioPortState: %d", audioPortState); +} + +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioModeEvent(dsAudioPortType_t audioPortType, dsAudioStereoMode_t audioStereoMode) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioModeEvent called. audioPortType: %d, audioStereoMode: %d", audioPortType, audioStereoMode); +} + +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioLevelChangedEvent(int audioLevel) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioLevelChangedEvent called. audioLevel: %d", audioLevel); +} + +/* virtual */ void Host::IAudioOutputPortEvents::OnAudioFormatUpdate(dsAudioFormat_t audioFormat) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnAudioFormatUpdate called. audioFormat: %d", audioFormat); +} + +/* virtual */ void Host::IDisplayDeviceEvents::OnDisplayHDMIHotPlug(dsDisplayEvent_t displayEvent) +{ + // If client needs to handle this event, they should override this method + INT_DEBUG("Base impl of OnDisplayHDMIHotPlug called. displayEvent: %d", displayEvent); +} +/* virtual */ void Host::ICompositeInEvents::OnCompositeInHotPlug(dsCompositeInPort_t port, bool isConnected) +{ + /* If client needs to handle this event, they should override this method */ + INT_DEBUG("Base impl of OnCompositeInHotPlug called. port: %d isConnected %d", port, isConnected); +} + +/* virtual */ void Host::ICompositeInEvents::OnCompositeInSignalStatus(dsCompositeInPort_t port, dsCompInSignalStatus_t signalStatus) +{ + /* If client needs to handle this event, they should override this method */ + INT_DEBUG("Base impl of OnCompositeInSignalStatus called. port: %d signalStatus %d", port, signalStatus); +} + +/* virtual */ void Host::ICompositeInEvents::OnCompositeInStatus(dsCompositeInPort_t activePort, bool isPresented) +{ + /* If client needs to handle this event, they should override this method */ + INT_DEBUG("Base impl of OnCompositeInStatus called. activePort: %d isPresented %d", activePort, isPresented); +} +/* virtual */ void Host::ICompositeInEvents::OnCompositeInVideoModeUpdate(dsCompositeInPort_t activePort, dsVideoPortResolution_t videoResolution) +{ + /* If client needs to handle this event, they should override this method */ + INT_DEBUG("Base impl of OnCompositeInVideoModeUpdate called. activePort: %d videoResolution %d", activePort, videoResolution.pixelResolution); +} + +/* virtual */ void Host::IDisplayEvents::OnDisplayRxSense(dsDisplayEvent_t displayEvent) +{ + /* If client needs to handle this event, they should override this method */ + INT_DEBUG("Base impl of OnDisplayRxSense called. displayEvent: %d ", displayEvent); +} + +dsError_t Host::Register(IHdmiInEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(IHdmiInEvents* listener) +{ + return impl().UnRegister(listener); +} + +dsError_t Host::Register(ICompositeInEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(ICompositeInEvents* listener) +{ + return impl().UnRegister(listener); +} + +dsError_t Host::Register(IDisplayEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(IDisplayEvents* listener) +{ + return impl().UnRegister(listener); +} + +dsError_t Host::Register(IVideoDeviceEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(IVideoDeviceEvents* listener) +{ + return impl().UnRegister(listener); +} + +dsError_t Host::Register(IVideoOutputPortEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(IVideoOutputPortEvents* listener) +{ + return impl().UnRegister(listener); +} + +dsError_t Host::Register(IAudioOutputPortEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(IAudioOutputPortEvents* listener) +{ + return impl().UnRegister(listener); +} + +dsError_t Host::Register(IDisplayDeviceEvents* listener, const std::string& clientName) +{ + return impl().Register(listener, clientName); +} + +dsError_t Host::UnRegister(IDisplayDeviceEvents* listener) +{ + return impl().UnRegister(listener); +} /** @} */ +} /* namespace device */ /** @} */ + /** @} */ diff --git a/ds/iarm/IarmImpl.cpp b/ds/iarm/IarmImpl.cpp new file mode 100755 index 00000000..4a721796 --- /dev/null +++ b/ds/iarm/IarmImpl.cpp @@ -0,0 +1,1080 @@ +#include +#include +#include +#include + +#include "IarmImpl.hpp" + +#include "dsMgr.h" +#include "dslogger.h" + +#include "libIBus.h" + +namespace device { + +struct EventHandlerMapping { + IARM_EventId_t eventId; + IARM_EventHandler_t handler; +}; + +// unregisterIarmEvents can be called by registerIarmEvents in case of failure. +// Hence defined before registerIarmEvents +template +static bool unregisterIarmEvents(const EventHandlerMapping (&handlers)[N]) +{ + bool unregistered = true; + + for (const auto& eh : handlers) { + if (IARM_RESULT_SUCCESS != IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME, eh.eventId)) { + INT_ERROR("Failed to unregister IARM event handler for %d", eh.eventId); + unregistered = false; + // don't break here, try to unregister all handlers + } + } + return unregistered; +} + +template +static bool registerIarmEvents(const EventHandlerMapping (&handlers)[N]) +{ + bool registered = true; + + for (const auto& eh : handlers) { + if (IARM_RESULT_SUCCESS != IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME, eh.eventId, eh.handler)) { + INT_ERROR("Failed to register IARM event handler for %d", eh.eventId); + registered = false; + // no point in continuing as we will attempt to unregister anyway + break; + } + } + + if (!registered) { + // in case of failure / partial failure + // we should unregister any handlers that were registered + unregisterIarmEvents(handlers); + } + + return registered; +} + +inline bool isValidOwner(const char* owner) +{ + if (std::string(IARM_BUS_DSMGR_NAME) != std::string(owner)) { + INT_ERROR("Invalid owner %s, expected %s", owner, IARM_BUS_DSMGR_NAME); + return false; + } + return true; +} + +// IARMGroupXYZ are c to c++ shim (all methods are static) +// Required to perform group event register and unregister with IARM +// Thread safety to be ensured by the caller +class IARMGroupVideoDevice { +public: + static bool RegisterIarmEvents() + { + return registerIarmEvents(handlers); + } + + static bool UnRegisterIarmEvents() + { + return unregisterIarmEvents(handlers); + } + +private: + static void iarmDisplayFrameratePreChangeHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_PRECHANGE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + std::string framerate(eventData->data.DisplayFrameRateChange.framerate); + + IarmImpl::Dispatch([&framerate](IVideoDeviceEvents* listener) { + listener->OnDisplayFrameratePreChange(framerate); + }); + } else { + INT_ERROR("Invalid data received for display framerate pre-change"); + } + } + + static void iarmDisplayFrameratePostChangeHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_POSTCHANGE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + std::string framerate(eventData->data.DisplayFrameRateChange.framerate); + + IarmImpl::Dispatch([&framerate](IVideoDeviceEvents* listener) { + listener->OnDisplayFrameratePostChange(framerate); + }); + } else { + INT_ERROR("Invalid data received for display framerate post-change"); + } + } + + static void iarmZoomSettingsChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_ZOOM_SETTINGS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsVideoZoom_t zoomSetting = static_cast(eventData->data.dfc.zoomsettings); + + IarmImpl::Dispatch([zoomSetting](IVideoDeviceEvents* listener) { + listener->OnZoomSettingsChanged(zoomSetting); + }); + } else { + INT_ERROR("Invalid data received for zoom settings change"); + } + }; + + static constexpr EventHandlerMapping handlers[] = { + { IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_PRECHANGE, &IARMGroupVideoDevice::iarmDisplayFrameratePreChangeHandler }, + { IARM_BUS_DSMGR_EVENT_DISPLAY_FRAMRATE_POSTCHANGE, &IARMGroupVideoDevice::iarmDisplayFrameratePostChangeHandler }, + { IARM_BUS_DSMGR_EVENT_ZOOM_SETTINGS, &IARMGroupVideoDevice::iarmZoomSettingsChangedHandler }, + }; +}; + +class IARMGroupVideoOutputPort { +public: + static bool RegisterIarmEvents() + { + return registerIarmEvents(handlers); + } + + static bool UnRegisterIarmEvents() + { + return unregisterIarmEvents(handlers); + } + +private: + static void iarmResolutionPreChangeHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_RES_PRECHANGE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + int width = eventData->data.resn.width; + int height = eventData->data.resn.height; + + IarmImpl::Dispatch([width, height](IVideoOutputPortEvents* listener) { + listener->OnResolutionPreChange(width, height); + }); + } else { + INT_ERROR("Invalid data received for resolution pre-change"); + } + } + + static void iarmResolutionPostChangeHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + int width = eventData->data.resn.width; + int height = eventData->data.resn.height; + + IarmImpl::Dispatch([width, height](IVideoOutputPortEvents* listener) { + listener->OnResolutionPostChange(width, height); + }); + } else { + INT_ERROR("Invalid data received for resolution post-change"); + } + } + + static void iarmHDCPStatusChangeHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDCP_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdcpStatus_t hdcpStatus = static_cast(eventData->data.hdmi_hdcp.hdcpStatus); + IarmImpl::Dispatch([hdcpStatus](IVideoOutputPortEvents* listener) { + listener->OnHDCPStatusChange(hdcpStatus); + }); + } else { + INT_ERROR("Invalid data received for HDCP status change"); + } + } + + static void iarmVideoFormatUpdateHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_VIDEO_FORMAT_UPDATE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHDRStandard_t videoFormat = eventData->data.VideoFormatInfo.videoFormat; + + IarmImpl::Dispatch([videoFormat](IVideoOutputPortEvents* listener) { + listener->OnVideoFormatUpdate(videoFormat); + }); + } else { + INT_ERROR("Invalid data received for video format update"); + } + } + + static constexpr EventHandlerMapping handlers[] = { + { IARM_BUS_DSMGR_EVENT_RES_PRECHANGE, &IARMGroupVideoOutputPort::iarmResolutionPreChangeHandler }, + { IARM_BUS_DSMGR_EVENT_RES_POSTCHANGE, &IARMGroupVideoOutputPort::iarmResolutionPostChangeHandler }, + { IARM_BUS_DSMGR_EVENT_HDCP_STATUS, &IARMGroupVideoOutputPort::iarmHDCPStatusChangeHandler }, + { IARM_BUS_DSMGR_EVENT_VIDEO_FORMAT_UPDATE, &IARMGroupVideoOutputPort::iarmVideoFormatUpdateHandler }, + }; +}; + +class IARMGroupAudioOutputPort { +public: + static bool RegisterIarmEvents() + { + return registerIarmEvents(handlers); + } + + static bool UnRegisterIarmEvents() + { + return unregisterIarmEvents(handlers); + } + +private: + static void iarmAssociatedAudioMixingChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_ASSOCIATED_AUDIO_MIXING_CHANGED received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + bool mixing = eventData->data.AssociatedAudioMixingInfo.mixing; + + IarmImpl::Dispatch([mixing](IAudioOutputPortEvents* listener) { + listener->OnAssociatedAudioMixingChanged(mixing); + }); + } else { + INT_ERROR("Invalid data received for associated audio mixing change"); + } + }; + + static void iarmAudioFaderControlChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_FADER_CONTROL_CHANGED received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + int mixerBalance = eventData->data.FaderControlInfo.mixerbalance; + + IarmImpl::Dispatch([mixerBalance](IAudioOutputPortEvents* listener) { + listener->OnAudioFaderControlChanged(mixerBalance); + }); + } else { + INT_ERROR("Invalid data received for audio fader control change"); + } + }; + + static void iarmAudioPrimaryLanguageChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_PRIMARY_LANGUAGE_CHANGED received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + std::string primaryLanguage(eventData->data.AudioLanguageInfo.audioLanguage); + + IarmImpl::Dispatch([&primaryLanguage](IAudioOutputPortEvents* listener) { + listener->OnAudioPrimaryLanguageChanged(primaryLanguage); + }); + } else { + INT_ERROR("Invalid data received for primary language change"); + } + }; + + static void iarmAudioSecondaryLanguageChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_SECONDARY_LANGUAGE_CHANGED received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + std::string secondaryLanguage(eventData->data.AudioLanguageInfo.audioLanguage); + + IarmImpl::Dispatch([&secondaryLanguage](IAudioOutputPortEvents* listener) { + listener->OnAudioSecondaryLanguageChanged(secondaryLanguage); + }); + } else { + INT_ERROR("Invalid data received for secondary language change"); + } + }; + + static void iarmAudioOutHotPlugHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_OUT_HOTPLUG received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsAudioPortType_t portType = eventData->data.audio_out_connect.portType; + uint32_t uiPortNumber = eventData->data.audio_out_connect.uiPortNo; + bool isPortConnected = eventData->data.audio_out_connect.isPortConnected; + + IarmImpl::Dispatch([portType, uiPortNumber, isPortConnected](IAudioOutputPortEvents* listener) { + listener->OnAudioOutHotPlug(portType, uiPortNumber, isPortConnected); + }); + } else { + INT_ERROR("Invalid data received for audio out hot plug change"); + } + }; + + static void iarmDolbyAtmosCapabilitiesChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_ATMOS_CAPS_CHANGED received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsATMOSCapability_t atmosCapability = eventData->data.AtmosCapsChange.caps; + bool status = eventData->data.AtmosCapsChange.status; + + IarmImpl::Dispatch([atmosCapability, status](IAudioOutputPortEvents* listener) { + listener->OnDolbyAtmosCapabilitiesChanged(atmosCapability, status); + }); + + } else { + INT_ERROR("Invalid data received for Dolby Atmos capabilities change"); + } + }; + + static void iarmAudioPortStateChangedHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_PORT_STATE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsAudioPortState_t audioPortState = eventData->data.AudioPortStateInfo.audioPortState; + + IarmImpl::Dispatch([audioPortState](IAudioOutputPortEvents* listener) { + listener->OnAudioPortStateChanged(audioPortState); + }); + } else { + INT_ERROR("Invalid data received for audio port state change"); + } + }; + + static void iarmAudioModeEventHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_MODE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsAudioPortType_t audioPortType = static_cast(eventData->data.Audioport.type); + dsAudioStereoMode_t audioStereoMode = static_cast(eventData->data.Audioport.mode); + + IarmImpl::Dispatch([audioPortType, audioStereoMode](IAudioOutputPortEvents* listener) { + listener->OnAudioModeEvent(audioPortType, audioStereoMode); + }); + } else { + INT_ERROR("Invalid data received for audio mode change"); + } + }; + + static void iarmAudioLevelChangedEventHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_LEVEL_CHANGED received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + int audioLevel = eventData->data.AudioLevelInfo.level; + + IarmImpl::Dispatch([audioLevel](IAudioOutputPortEvents* listener) { + listener->OnAudioLevelChangedEvent(audioLevel); + }); + } else { + INT_ERROR("Invalid data received for audio level change"); + } + }; + + static void iarmAudioFormatUpdateHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_AUDIO_FORMAT_UPDATE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsAudioFormat_t audioFormat = eventData->data.AudioFormatInfo.audioFormat; + + IarmImpl::Dispatch([audioFormat](IAudioOutputPortEvents* listener) { + listener->OnAudioFormatUpdate(audioFormat); + }); + } else { + INT_ERROR("Invalid data received for audio format update"); + } + }; + +private: + static constexpr EventHandlerMapping handlers[] = { + { IARM_BUS_DSMGR_EVENT_AUDIO_ASSOCIATED_AUDIO_MIXING_CHANGED, &IARMGroupAudioOutputPort::iarmAssociatedAudioMixingChangedHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_FADER_CONTROL_CHANGED, &IARMGroupAudioOutputPort::iarmAudioFaderControlChangedHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_PRIMARY_LANGUAGE_CHANGED, &IARMGroupAudioOutputPort::iarmAudioPrimaryLanguageChangedHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_SECONDARY_LANGUAGE_CHANGED, &IARMGroupAudioOutputPort::iarmAudioSecondaryLanguageChangedHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_OUT_HOTPLUG, &IARMGroupAudioOutputPort::iarmAudioOutHotPlugHandler }, + { IARM_BUS_DSMGR_EVENT_ATMOS_CAPS_CHANGED, &IARMGroupAudioOutputPort::iarmDolbyAtmosCapabilitiesChangedHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_PORT_STATE, &IARMGroupAudioOutputPort::iarmAudioPortStateChangedHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_MODE, &IARMGroupAudioOutputPort::iarmAudioModeEventHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_LEVEL_CHANGED, &IARMGroupAudioOutputPort::iarmAudioLevelChangedEventHandler }, + { IARM_BUS_DSMGR_EVENT_AUDIO_FORMAT_UPDATE, &IARMGroupAudioOutputPort::iarmAudioFormatUpdateHandler }, + }; +}; + +class IARMGroupComposite { +public: + static bool RegisterIarmEvents() + { + return registerIarmEvents(handlers); + } + + static bool UnRegisterIarmEvents() + { + return unregisterIarmEvents(handlers); + } + +private: + static void iarmCompositeInHotPlugHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsCompositeInPort_t compositePort = eventData->data.composite_in_connect.port; + bool isConnected = eventData->data.composite_in_connect.isPortConnected; + IarmImpl::Dispatch([compositePort, isConnected](ICompositeInEvents* listener) { + listener->OnCompositeInHotPlug(compositePort, isConnected); + }); + } else { + INT_ERROR("Invalid data received for Composite Status Handler in iarmCompositeInHotPlugHandler"); + } + } + + static void iarmCompositeInSignalStatusHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsCompositeInPort_t compositePort = eventData->data.composite_in_sig_status.port; + dsCompInSignalStatus_t compositeSigStatus = eventData->data.composite_in_sig_status.status; + + IarmImpl::Dispatch([compositePort, compositeSigStatus](ICompositeInEvents* listener) { + listener->OnCompositeInSignalStatus(compositePort, compositeSigStatus); + }); + } else { + INT_ERROR("Invalid data received for Composite Status Handler in iarmCompositeInSignalStatusHandler"); + } + } + + static void iarmCompositeInStatusHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsCompositeInPort_t compositePort = eventData->data.composite_in_status.port; + bool isPresented = eventData->data.composite_in_status.isPresented; + IarmImpl::Dispatch([compositePort, isPresented](ICompositeInEvents* listener) { + listener->OnCompositeInStatus(compositePort, isPresented); + }); + } else { + INT_ERROR("Invalid data received for Composite Status Handler in iarmCompositeInStatusHandler"); + } + } + + static void iarmCompositeInVideoModeUpdateHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE received owner = %s, eventId = %d", owner, eventId); + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsCompositeInPort_t compositePort = eventData->data.composite_in_video_mode.port; + + dsVideoPortResolution_t videoResolution {}; + + videoResolution.name[0] = '\0'; + videoResolution.aspectRatio = dsVIDEO_ASPECT_RATIO_MAX; + videoResolution.stereoScopicMode = dsVIDEO_SSMODE_UNKNOWN; + videoResolution.pixelResolution = eventData->data.composite_in_video_mode.resolution.pixelResolution; + videoResolution.interlaced = eventData->data.composite_in_video_mode.resolution.interlaced; + videoResolution.frameRate = eventData->data.composite_in_video_mode.resolution.frameRate; + + IarmImpl::Dispatch([compositePort, videoResolution](ICompositeInEvents* listener) { + listener->OnCompositeInVideoModeUpdate(compositePort, videoResolution); + }); + } else { + INT_ERROR("Invalid data received for Composite Video Mode Update in iarmCompositeInVideoModeUpdateHandler"); + } + } + +private: + static constexpr EventHandlerMapping handlers[] = { + { IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_HOTPLUG, &IARMGroupComposite::iarmCompositeInHotPlugHandler }, + { IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_SIGNAL_STATUS, &IARMGroupComposite::iarmCompositeInSignalStatusHandler }, + { IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_STATUS, &IARMGroupComposite::iarmCompositeInStatusHandler }, + { IARM_BUS_DSMGR_EVENT_COMPOSITE_IN_VIDEO_MODE_UPDATE, &IARMGroupComposite::iarmCompositeInVideoModeUpdateHandler }, + }; +}; + +class IARMGroupDisplay { +public: + static bool RegisterIarmEvents() + { + return registerIarmEvents(handlers); + } + + static bool UnRegisterIarmEvents() + { + return unregisterIarmEvents(handlers); + } + +private: + static void iarmDisplayDisplayRxSense(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_RX_SENSE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsDisplayEvent_t displayStatusEvent = static_cast(eventData->data.hdmi_rxsense.status); + IarmImpl::Dispatch([displayStatusEvent](IDisplayEvents* listener) { + listener->OnDisplayRxSense(displayStatusEvent); + }); + } else { + INT_ERROR("Invalid data received for Composite Status Handler in iarmDisplayDisplayRxSense"); + } + } + +private: + static constexpr EventHandlerMapping handlers[] = { + { IARM_BUS_DSMGR_EVENT_RX_SENSE, &IARMGroupDisplay::iarmDisplayDisplayRxSense } + }; +}; + +class IARMGroupDisplayDevice { +public: + static bool RegisterIarmEvents() + { + IARM_Result_t result = IARM_Bus_RegisterEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG, + &IARMGroupDisplayDevice::iarmDisplayHDMIHotPlugHandler); + + if (IARM_RESULT_SUCCESS != result) { + INT_ERROR("Failed to register IARM event handler for IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG"); + } + return (IARM_RESULT_SUCCESS == result); + } + + static bool UnRegisterIarmEvents() + { + IARM_Result_t result = IARM_Bus_UnRegisterEventHandler(IARM_BUS_DSMGR_NAME, IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG); + if (IARM_RESULT_SUCCESS != result) { + INT_ERROR("Failed to unregister IARM event handler for IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG"); + } + return (IARM_RESULT_SUCCESS == result); + } + +private: + static void iarmDisplayHDMIHotPlugHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_HOTPLUG received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsDisplayEvent_t displayEvent = static_cast(eventData->data.hdmi_hpd.event); + + IarmImpl::Dispatch([displayEvent](IDisplayDeviceEvents* listener) { + listener->OnDisplayHDMIHotPlug(displayEvent); + }); + } else { + INT_ERROR("Invalid data received for HDMI (out) hot plug change"); + } + } +}; /* IARMGroupDisplayDevice */ + +class IARMGroupHdmiIn { +public: + static bool RegisterIarmEvents() + { + return registerIarmEvents(handlers); + } + + static bool UnRegisterIarmEvents() + { + return unregisterIarmEvents(handlers); + } + +private: + static void iarmHdmiInEventHotPlugHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t port = eventData->data.hdmi_in_connect.port; + bool isConnected = eventData->data.hdmi_in_connect.isPortConnected; + + IarmImpl::Dispatch([port, isConnected](IHdmiInEvents* listener) { + listener->OnHdmiInEventHotPlug(port, isConnected); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn hot plug"); + } + }; + + static void iarmHdmiInEventSignalStatusHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t port = eventData->data.hdmi_in_sig_status.port; + dsHdmiInSignalStatus_t sigStatus = eventData->data.hdmi_in_sig_status.status; + + IarmImpl::Dispatch([port, sigStatus](IHdmiInEvents* listener) { + listener->OnHdmiInEventSignalStatus(port, sigStatus); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn signal status"); + } + }; + + static void iarmHdmiInEventStatusHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t activePort = eventData->data.hdmi_in_status.port; + bool isPresented = eventData->data.hdmi_in_status.isPresented; + + IarmImpl::Dispatch([activePort, isPresented](IHdmiInEvents* listener) { + listener->OnHdmiInEventStatus(activePort, isPresented); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn event status"); + } + }; + + static void iarmHdmiInVideoModeUpdateHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t port = eventData->data.hdmi_in_video_mode.port; + dsVideoPortResolution_t res; + + res.name[0] = '\0'; + res.aspectRatio = dsVIDEO_ASPECT_RATIO_MAX; + res.stereoScopicMode = dsVIDEO_SSMODE_UNKNOWN; + res.pixelResolution = eventData->data.hdmi_in_video_mode.resolution.pixelResolution; + res.interlaced = eventData->data.hdmi_in_video_mode.resolution.interlaced; + res.frameRate = eventData->data.hdmi_in_video_mode.resolution.frameRate; + + IarmImpl::Dispatch([port, res](IHdmiInEvents* listener) { + listener->OnHdmiInVideoModeUpdate(port, res); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn video mode update"); + } + }; + + static void iarmHdmiInAllmStatusHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t port = eventData->data.hdmi_in_allm_mode.port; + bool allmStatus = eventData->data.hdmi_in_allm_mode.allm_mode; + + IarmImpl::Dispatch([port, allmStatus](IHdmiInEvents* listener) { + listener->OnHdmiInAllmStatus(port, allmStatus); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn allm status"); + } + }; + + static void iarmHdmiInVRRStatusHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t port = eventData->data.hdmi_in_vrr_mode.port; + dsVRRType_t vrrType = eventData->data.hdmi_in_vrr_mode.vrr_type; + + IarmImpl::Dispatch([port, vrrType](IHdmiInEvents* listener) { + listener->OnHdmiInVRRStatus(port, vrrType); + }); + + } else { + INT_ERROR("Invalid data received for HdmiIn vrr status"); + } + }; + + static void iarmHdmiInAVIContentTypeHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + dsHdmiInPort_t port = eventData->data.hdmi_in_content_type.port; + dsAviContentType_t type = eventData->data.hdmi_in_content_type.aviContentType; + + IarmImpl::Dispatch([port, type](IHdmiInEvents* listener) { + listener->OnHdmiInAVIContentType(port, type); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn avi content type"); + } + }; + + static void iarmHdmiInAVLatencyHandler(const char* owner, IARM_EventId_t eventId, void* data, size_t) + { + INT_INFO("IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY received owner = %s, eventId = %d", owner, eventId); + + if (!isValidOwner(owner)) { + return; + } + + auto* eventData = static_cast(data); + + if (eventData) { + int audioDelay = eventData->data.hdmi_in_av_latency.audio_output_delay; + int videoDelay = eventData->data.hdmi_in_av_latency.video_latency; + + IarmImpl::Dispatch([audioDelay, videoDelay](IHdmiInEvents* listener) { + listener->OnHdmiInAVLatency(audioDelay, videoDelay); + }); + } else { + INT_ERROR("Invalid data received for HdmiIn av latency"); + } + }; + +private: + static constexpr EventHandlerMapping handlers[] = { + { IARM_BUS_DSMGR_EVENT_HDMI_IN_HOTPLUG, &IARMGroupHdmiIn::iarmHdmiInEventHotPlugHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_SIGNAL_STATUS, &IARMGroupHdmiIn::iarmHdmiInEventSignalStatusHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_STATUS, &IARMGroupHdmiIn::iarmHdmiInEventStatusHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_VIDEO_MODE_UPDATE, &IARMGroupHdmiIn::iarmHdmiInVideoModeUpdateHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_ALLM_STATUS, &IARMGroupHdmiIn::iarmHdmiInAllmStatusHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_VRR_STATUS, &IARMGroupHdmiIn::iarmHdmiInVRRStatusHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_AVI_CONTENT_TYPE, &IARMGroupHdmiIn::iarmHdmiInAVIContentTypeHandler }, + { IARM_BUS_DSMGR_EVENT_HDMI_IN_AV_LATENCY, &IARMGroupHdmiIn::iarmHdmiInAVLatencyHandler } + }; +}; // IARMGroupHdmiIn + +/* static data */ +constexpr EventHandlerMapping IARMGroupHdmiIn::handlers[]; +constexpr EventHandlerMapping IARMGroupVideoDevice::handlers[]; +constexpr EventHandlerMapping IARMGroupVideoOutputPort::handlers[]; +constexpr EventHandlerMapping IARMGroupAudioOutputPort::handlers[]; +constexpr EventHandlerMapping IARMGroupComposite::handlers[]; +constexpr EventHandlerMapping IARMGroupDisplay::handlers[]; + +IarmImpl::CallbackList IarmImpl::s_hdmiInListeners; +IarmImpl::CallbackList IarmImpl::s_videoDeviceListeners; +IarmImpl::CallbackList IarmImpl::s_videoOutputPortListeners; +IarmImpl::CallbackList IarmImpl::s_audioOutputPortListeners; +IarmImpl::CallbackList IarmImpl::s_compositeListeners; +IarmImpl::CallbackList IarmImpl::s_displayListeners; +IarmImpl::CallbackList IarmImpl::s_displayDeviceListeners; + +IarmImpl::~IarmImpl() +{ + s_hdmiInListeners.Release(); + s_videoDeviceListeners.Release(); + s_videoOutputPortListeners.Release(); + s_audioOutputPortListeners.Release(); + s_compositeListeners.Release(); + s_displayListeners.Release(); + s_displayDeviceListeners.Release(); +} + +template +/* static */ void IarmImpl::Dispatch(const std::list>& listeners, F&& fn) +{ + std::stringstream ss; + + for (auto& pair : listeners) { + // pair.first is the listener + // pair.second is the clientName + + auto start = std::chrono::steady_clock::now(); + + fn(pair.first); + + auto end = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast(end - start); + ss << "\t client= " << pair.second << " @ " << pair.first << ", elapsed = " << elapsed.count() << " ms\n"; + } + + INT_INFO("%s Dispatch done to %zu listeners\n%s", typeid(T).name(), listeners.size(), ss.str().c_str()); +} + +dsError_t IarmImpl::Register(IHdmiInEvents* listener, const std::string& clientName) +{ + return s_hdmiInListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(IHdmiInEvents* listener) +{ + return s_hdmiInListeners.UnRegister(listener); +} + +// Dispatcher for IHdmiInEvents +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_hdmiInListeners.Mutex()); + Dispatch(s_hdmiInListeners, std::move(fn)); +} + +dsError_t IarmImpl::Register(IVideoDeviceEvents* listener, const std::string& clientName) +{ + return s_videoDeviceListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(IVideoDeviceEvents* listener) +{ + return s_videoDeviceListeners.UnRegister(listener); +} + +// Dispatcher for IARMGroupVideoDevice +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_videoDeviceListeners.Mutex()); + Dispatch(s_videoDeviceListeners, std::move(fn)); +} + +dsError_t IarmImpl::Register(IVideoOutputPortEvents* listener, const std::string& clientName) +{ + return s_videoOutputPortListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(IVideoOutputPortEvents* listener) +{ + return s_videoOutputPortListeners.UnRegister(listener); +} + +// Dispatcher for IVideoOutputPortEvents +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_videoOutputPortListeners.Mutex()); + Dispatch(s_videoOutputPortListeners, std::move(fn)); +} + +dsError_t IarmImpl::Register(IAudioOutputPortEvents* listener, const std::string& clientName) +{ + return s_audioOutputPortListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(IAudioOutputPortEvents* listener) +{ + return s_audioOutputPortListeners.UnRegister(listener); +} + +// Dispatcher for IAudioOutputPortEvents +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_audioOutputPortListeners.Mutex()); + Dispatch(s_audioOutputPortListeners, std::move(fn)); +} + +dsError_t IarmImpl::Register(ICompositeInEvents* listener, const std::string& clientName) +{ + return s_compositeListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(ICompositeInEvents* listener) +{ + return s_compositeListeners.UnRegister(listener); +} + +// Dispatcher for IARMGroupComposite +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_compositeListeners.Mutex()); + Dispatch(s_compositeListeners, std::move(fn)); +} + +dsError_t IarmImpl::Register(IDisplayEvents* listener, const std::string& clientName) +{ + return s_displayListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(IDisplayEvents* listener) +{ + return s_displayListeners.UnRegister(listener); +} + +// Dispatcher for IARMGroupDisplay +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_displayListeners.Mutex()); + Dispatch(s_displayListeners, std::move(fn)); +} + +dsError_t IarmImpl::Register(IDisplayDeviceEvents* listener, const std::string& clientName) +{ + return s_displayDeviceListeners.Register(listener, clientName); +} + +dsError_t IarmImpl::UnRegister(IDisplayDeviceEvents* listener) +{ + return s_displayDeviceListeners.UnRegister(listener); +} + +// Dispatcher for IDisplayDeviceEvents +/* static */ void IarmImpl::Dispatch(std::function&& fn) +{ + std::lock_guard lock(s_displayDeviceListeners.Mutex()); + Dispatch(s_displayDeviceListeners, std::move(fn)); +} + +} // namespace device diff --git a/ds/iarm/IarmImpl.hpp b/ds/iarm/IarmImpl.hpp new file mode 100755 index 00000000..d2c829b2 --- /dev/null +++ b/ds/iarm/IarmImpl.hpp @@ -0,0 +1,282 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 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 +#include +#include + +#include "dsError.h" +#include "dslogger.h" +#include "host.hpp" + +namespace device { + +// Forward declaration for IARM Implementation Groups +class IARMGroupHdmiIn; +class IARMGroupVideoDevice; +class IARMGroupVideoOutputPort; +class IARMGroupAudioOutputPort; +class IARMGroupDisplayDevice; +class IARMGroupComposite; +class IARMGroupDisplay; + +using IHdmiInEvents = Host::IHdmiInEvents; +using IVideoDeviceEvents = Host::IVideoDeviceEvents; +using IVideoOutputPortEvents = Host::IVideoOutputPortEvents; +using IAudioOutputPortEvents = Host::IAudioOutputPortEvents; +using IDisplayDeviceEvents = Host::IDisplayDeviceEvents; +using ICompositeInEvents = device::Host::ICompositeInEvents; +using IDisplayEvents = device::Host::IDisplayEvents; + +class IarmImpl { + + // Manages a list of listeners and corresponding IARM Event Group operations. + // Private internal class, not to be used directly by clients. + template + class CallbackList : public std::list> { + public: + CallbackList() + : m_registered(false) + { + } + + ~CallbackList() + { + // As best practise caller is supposed to call Release() explicitly + // this is just for safety (see IarmImpl destructor) + Release(); + } + + // disable copy and move semantics + CallbackList(const CallbackList&) = delete; + CallbackList& operator=(const CallbackList&) = delete; + CallbackList(CallbackList&&) = delete; + CallbackList& operator=(CallbackList&&) = delete; + + // @brief Register a listener, also register IARM events if not already registered + // if the listener is already registered, listener will not be added again + // if IARM event registration fails, listener will not be added + // clientName is for logging purposes only, if not available, pass empty string + dsError_t Register(T listener, const std::string& clientName) + { + if (nullptr == listener) { + INT_ERROR("%s listener is null", typeid(T).name()); + return dsERR_INVALID_PARAM; // Error: Listener is null + } + + std::lock_guard lock(m_mutex); + + if (!m_registered) { + m_registered = IARMGroup::RegisterIarmEvents(); + + if (!m_registered) { + INT_ERROR("Failed to register IARMGroup %s", typeid(IARMGroup).name()); + return dsERR_OPERATION_FAILED; // Error: Failed to register IARM group + } + } + + auto it = std::find_if(this->begin(), this->end(), [listener](const std::pair& pair) { + return pair.first == listener; + }); + + if (it != this->end()) { + // Listener already registered + INT_ERROR("%s %p is already registered", typeid(T).name(), listener); + return dsERR_NONE; // Success: Listener already registered + } + + this->emplace_back(listener, clientName); + + INT_INFO("%s %s %p registered", clientName.c_str(), typeid(T).name(), listener); + + return dsERR_NONE; + } + + // @brief UnRegister a listener, also unregister IARM events if no listeners are left + // if the listener is not registered, it will not be removed + dsError_t UnRegister(T listener) + { + if (nullptr == listener) { + INT_ERROR("%s listener is null", typeid(T).name()); + return dsERR_INVALID_PARAM; // Error: Listener is null + } + + std::lock_guard lock(m_mutex); + + // pair.first is the listener, pair.second is the clientName + auto it = std::find_if(this->begin(), this->end(), [listener](const std::pair& pair) { + return pair.first == listener; + }); + + if (it == this->end()) { + // Listener not found + INT_ERROR("%s %p is not registered", typeid(T).name(), listener); + return dsERR_RESOURCE_NOT_AVAILABLE; // Error: Listener not found + } + + const std::string clientName = it->second; + + this->erase(it); + + INT_INFO("%s %s %p unregistered", clientName.c_str(), typeid(T).name(), listener); + + if (this->empty() && m_registered) { + m_registered = !IARMGroup::UnRegisterIarmEvents(); + } + + return dsERR_NONE; // Success + } + + // @brief Release all listeners and unregister IARM events + // This will clear the list and unregister IARM events if no listeners are left + dsError_t Release() + { + std::lock_guard lock(m_mutex); + + if (m_registered) { + m_registered = !IARMGroup::UnRegisterIarmEvents(); + } + + this->clear(); + INT_INFO("CallbackList[T=%s] released, status: %d", typeid(T).name(), m_registered); + return dsERR_NONE; // Success + } + + std::mutex& Mutex() + { + return m_mutex; + } + + private: + std::mutex m_mutex; // To protect access to the list and callback notifications + bool m_registered = false; // To track if IARM events are registered + }; + +public: + IarmImpl() = default; + ~IarmImpl(); + + // @brief Register a listener for HDMI device events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IHdmiInEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for HDMI device events + // @param listener: class object implementing the listener + dsError_t UnRegister(IHdmiInEvents* listener); + + // @brief Register a listener for video device events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IVideoDeviceEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for video device events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IVideoDeviceEvents* listener); + + // @brief Register a listener for video port events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IVideoOutputPortEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for video port events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IVideoOutputPortEvents* listener); + + // @brief Register a listener for audio port events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IAudioOutputPortEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for audio port events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IAudioOutputPortEvents* listener); + + // @brief Register a listener for Composite events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(ICompositeInEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for Composite events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(ICompositeInEvents* listener); + + // @brief Register a listener for Composite events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IDisplayEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for Composite events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IDisplayEvents* listener); + + // @brief Register a listener for display device events + // @param listener: class object implementing the listener + // @param clientName: name of the client registering the listener, for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IDisplayDeviceEvents* listener, const std::string& clientName); + + // @brief UnRegister a listener for display device events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IDisplayDeviceEvents* listener); + +private: + static CallbackList s_hdmiInListeners; + static CallbackList s_videoDeviceListeners; + static CallbackList s_videoOutputPortListeners; + static CallbackList s_audioOutputPortListeners; + static CallbackList s_compositeListeners; + static CallbackList s_displayListeners; + static CallbackList s_displayDeviceListeners; + + template + static void Dispatch(const std::list>& listeners, F&& fn); + + static void Dispatch(std::function&& fn); + static void Dispatch(std::function&& fn); + static void Dispatch(std::function&& fn); + static void Dispatch(std::function&& fn); + static void Dispatch(std::function&& fn); + static void Dispatch(std::function&& fn); + static void Dispatch(std::function&& fn); + + // Dispatch is private, so all IARMGroup implementations will need to be friends + friend class IARMGroupHdmiIn; + friend class IARMGroupVideoDevice; + friend class IARMGroupVideoOutputPort; + friend class IARMGroupAudioOutputPort; + friend class IARMGroupComposite; + friend class IARMGroupDisplay; + friend class IARMGroupDisplayDevice; +}; +} // namespace device diff --git a/ds/include/displayConnectionChangeListener.hpp b/ds/include/displayConnectionChangeListener.hpp deleted file mode 100644 index 736cfd04..00000000 --- a/ds/include/displayConnectionChangeListener.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2016 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. -*/ - - - - -/** -* @defgroup devicesettings -* @{ -* @defgroup ds -* @{ -**/ - - -#ifndef _DS_DISPLAYCONNECTIONCHANGELISTENER_H_ -#define _DS_DISPLAYCONNECTIONCHANGELISTENER_H_ - -#include "videoOutputPort.hpp" - -namespace device { - -class DisplayConnectionChangeListener { -public: - DisplayConnectionChangeListener() {} - virtual ~DisplayConnectionChangeListener() {} - virtual void displayConnectionChanged(VideoOutputPort &port, int newConnectionStatus) = 0; -}; - -} - -#endif /* DISPLAYCONNECTIONCHANGELISTENER_H_ */ - - -/** @} */ -/** @} */ diff --git a/ds/include/dslogger.h b/ds/include/dslogger.h index 6bde12cb..e356979d 100644 --- a/ds/include/dslogger.h +++ b/ds/include/dslogger.h @@ -29,21 +29,39 @@ #ifndef _DS_LOGGER_H_ #define _DS_LOGGER_H_ +#include + #include "dsregisterlog.h" -#include -int ds_log(int priority,const char *format, ...); +int ds_log(int priority, const char* fileName, int lineNum, const char *format, ...); #define INFO_LEVEL 0 #define WARN_LEVEL 1 #define ERROR_LEVEL 2 #define DEBUG_LEVEL 3 +// Helper to extract filename from full path +// E.g. "/path/to/file.cpp" -> "file.cpp" +// IMPORTANT: This will work for Unix style paths only +static inline const char* fileName(const char* path) { + const char* slash = strrchr(path, '/'); + return slash ? slash + 1 : path; +} + +#ifndef DS_LOG_LEVEL +#define DS_LOG_LEVEL ERROR_LEVEL +#endif -#define INT_INFO(FORMAT, ...) ds_log(INFO_LEVEL ,FORMAT, ##__VA_ARGS__ ) -#define INT_WARN(FORMAT, ...) ds_log(WARN_LEVEL ,FORMAT, ##__VA_ARGS__ ) -#define INT_ERROR(FORMAT, ...) ds_log(ERROR_LEVEL ,FORMAT, ##__VA_ARGS__ ) -#define INT_DEBUG(FORMAT, ...) ds_log(DEBUG_LEVEL ,FORMAT, ##__VA_ARGS__ ) +#define INT_INFO(FORMAT, ...) ds_log(INFO_LEVEL, fileName(__FILE__), __LINE__, FORMAT, ##__VA_ARGS__ ) +#define INT_WARN(FORMAT, ...) ds_log(WARN_LEVEL, fileName(__FILE__), __LINE__, FORMAT, ##__VA_ARGS__ ) +#define INT_ERROR(FORMAT, ...) ds_log(ERROR_LEVEL, fileName(__FILE__), __LINE__, FORMAT, ##__VA_ARGS__ ) + +// conditionally enable debug logs, based on DS_LOG_LEVEL +#if DS_LOG_LEVEL >= DEBUG_LEVEL +#define INT_DEBUG(FORMAT, ...) ds_log(DEBUG_LEVEL, fileName(__FILE__), __LINE__, FORMAT, ##__VA_ARGS__ ) +#else +#define INT_DEBUG(FORMAT, ...) ((void)0) +#endif #endif diff --git a/ds/include/hdmiIn.hpp b/ds/include/hdmiIn.hpp index eb2da3dc..0aeb9e25 100755 --- a/ds/include/hdmiIn.hpp +++ b/ds/include/hdmiIn.hpp @@ -52,7 +52,7 @@ #include #include "dsTypes.h" - +#include "dsError.h" /** * @file hdmiIn.hpp @@ -101,6 +101,7 @@ class HdmiInput void getVRRSupport (int iHdmiPort, bool *vrr_suppport); void getVRRStatus (int iHdmiPort, dsHdmiInVrrStatus_t *vrrStatus); void getHdmiVersion (int iHdmiPort, dsHdmiMaxCapabilityVersion_t *capversion); + dsError_t getHDMIARCPortId(int &portId); private: HdmiInput (); /* default constructor */ virtual ~HdmiInput (); /* destructor */ diff --git a/ds/include/host.hpp b/ds/include/host.hpp index d14d42dc..02adbfa8 100644 --- a/ds/include/host.hpp +++ b/ds/include/host.hpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2025 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,42 +15,126 @@ * 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. -*/ - - + */ /** -* @defgroup devicesettings -* @{ -* @defgroup ds -* @{ -**/ + * @defgroup devicesettings + * @{ + * @defgroup ds + * @{ + **/ +/** + * This file provides all the devicesettings notifications for the usage of the various plugin clients. + * The notifications are classified in to various blocks. + * + * The Clients have to register for the respective required blocks like IHdmiInEvents, ICompositeInEvents, + * IVideoOutputPortEvents, IVideoDeviceEvents etc through the Register API Call. + * The Clients have to unregister for the respective required blocks like IHdmiInEvents, + * ICompositeInEvents, IVideoOutputPortEvents, IVideoDeviceEvents etc through the UnRegister API Call + * when the activity is completed. + * + * The clients need to implement the required notification handler functions for the respective blocks + * which they have registered. If clients don't need to handle some notifications in a block, they + * need not implement those functions. + * + * Example: A client can choose to register for IHdmiInEvents block of events and implement only + * required notification function OnHdmiInEventHotPlug and can ignore other functions in the same event + * block like OnHdmiInEventSignalStatus. + * + * The Client will receive the event notification for which it has registered and implemented the notification. + * This will happen when the respective action has taken place in the device. + * + * IHdmiInEvents + * OnHdmiInEventHotPlug : Will notify the HDMI Hot Plug IN/OUT Event + * OnHdmiInEventSignalStatus : Will notify the HDMI Signal Status + * OnHdmiInEventStatus : Will notify the port specific HDMI status + * OnHdmiInVideoModeUpdate : Will notify the HDMI video resolution changes + * OnHdmiInAllmStatus : Will notify the HDMI Auto Low Latency Mode + * OnHdmiInAVIContentType : Will notify the HDMI AVI info like Gaming, Cinema, Photo etc + * OnHdmiInVRRStatus : Will notify the HDMI VRR info(Variable Refresh Rate) + * OnHdmiInAVLatency : Will notify about the HDMI AV Latency info. + * + * ICompositeInEvents + * OnCompositeInHotPlug : Will notify about the Hotplug in Composite Mode. + * OnCompositeInSignalStatus : Will notify about the Signal Status in Composite Mode. + * OnCompositeInStatus : Will notify about the Composite Status in Composite Mode. + * OnCompositeInVideoModeUpdate : Will notify about the Update in video Mode in Composite Mode. + * + * IDisplayEvents + * OnDisplayRxSense : Will notify about the RX Sense + * + * IVideoDeviceEvents + * OnDisplayFrameratePreChange : Will notify about the Frame Rate Before Change. + * OnDisplayFrameratePostChange : Will notify about the Frame rate After change. + * OnZoomSettingsChanged : Will notify about the zoom settings changed + * + * IVideoOutputPortEvents + * OnResolutionPreChange : Will notify about the Resolution Pre Change + * OnHDCPStatusChange : Will notify about the HDCP status Change + * OnVideoFormatUpdate : Will notify about the Video Format Change. + * + * IAudioOutputPortEvents + * OnAssociatedAudioMixingChanged : Will notify about the Audio Mixer Change. + * OnAudioFaderControlChanged : Will notify about the Fader Control Change. + * OnAudioPrimaryLanguageChanged : Will notify about the Primary Language Change. + * OnAudioSecondaryLanguageChanged : Will notify about the Secondary Language Change. + * OnAudioOutHotPlug : Will notify about the Audio Out Hot Plug Change. + * OnDolbyAtmosCapabilitiesChanged : Will notify about the ATMOS capability Change. + * OnAudioPortStateChanged : Will notify about the Audio Port State Change. + * OnAudioModeEvent : Will notify about the Audio Mode Event Change. + * OnAudioLevelChangedEvent : Will notify about the Audio Level Change. + * OnAudioFormatUpdate : Will notify about the Audio Format Change. + * + * IDisplayDeviceEvents + * OnDisplayHDMIHotPlug : Will notify about the HDMI Hot Plug Change + **/ #ifndef _DS_HOST_HPP_ #define _DS_HOST_HPP_ +#include +#include -#include -#include "powerModeChangeListener.hpp" -#include "displayConnectionChangeListener.hpp" #include "audioOutputPort.hpp" -#include "videoOutputPort.hpp" -#include "videoDevice.hpp" +#include "dsAVDTypes.h" +#include "dsDisplay.h" +#include "dsError.h" +#include "list.hpp" #include "sleepMode.hpp" -#include "list.hpp" +#include "videoDevice.hpp" +#include "videoOutputPort.hpp" -#include -#include +// dsMgr.h cannot be exposed to clients as we plan to deprecate it +// this is only temporary until dsAudioPortState_t is moved to ds halif headers +#ifndef HAVE_DSAUDIOPORT_STATE_TYPE +#define HAVE_DSAUDIOPORT_STATE_TYPE +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _dsAudioPortState { + dsAUDIOPORT_STATE_UNINITIALIZED, + dsAUDIOPORT_STATE_INITIALIZED, + dsAUDIOPORT_STATE_MAX +} dsAudioPortState_t; +#ifdef __cplusplus +} +#endif +#endif // HAVE_DSAUDIOPORT_STATE_TYPE /** * @file host.hpp - * @brief It contains class,structures referenced by host.cpp file. + * @brief It contains class, structures referenced by host.cpp file. */ using namespace std; namespace device { +// Forward declaration of the implementation class +class IarmImpl; +// In future add a conditional to choose implementation class based on build configuration +using DefaultImpl = IarmImpl; /** * @class Host @@ -63,63 +147,311 @@ class Host { static const int kPowerOff; static const int kPowerStandby; - bool setPowerMode(int mode); - int getPowerMode(); + struct IHdmiInEvents { + virtual ~IHdmiInEvents() = default; + + // @brief HDMI Event Hot Plug + // @param port: port 0 or 1 et al + // @param isConnected: is it connected (true) or not (false) + virtual void OnHdmiInEventHotPlug(dsHdmiInPort_t port, bool isConnected); + + // @brief HDMI Event Signal status + // @param port: port 0 or 1 et al + // @param signalStatus: Signal Status + virtual void OnHdmiInEventSignalStatus(dsHdmiInPort_t port, dsHdmiInSignalStatus_t signalStatus); + + // @brief HDMI Event Signal status + // @param activePort: port 0 or 1 et al + // @param isPresented: is it presented or not + virtual void OnHdmiInEventStatus(dsHdmiInPort_t activePort, bool isPresented); + + // @brief HDMI Video Mode update + // @param port: port 0 or 1 et al + // @param videoPortResolution: Video port resolution + virtual void OnHdmiInVideoModeUpdate(dsHdmiInPort_t port, const dsVideoPortResolution_t& videoPortResolution); + + // @brief HDMI ALLM (Auto Low Latency Mode) status + // @param port: port 0 or 1 et al + // @param allmStatus: allm status + virtual void OnHdmiInAllmStatus(dsHdmiInPort_t port, bool allmStatus); + + // @brief HDMI Event AVI content type + // @param port: port 0 or 1 et al + // @param aviContentType: AVI content type + virtual void OnHdmiInAVIContentType(dsHdmiInPort_t port, dsAviContentType_t aviContentType); + + // @brief HDMI VRR status + // @param port: port 0 or 1 et al + // @param vrrType: VRR type + virtual void OnHdmiInVRRStatus(dsHdmiInPort_t port, dsVRRType_t vrrType); + + // @brief HDMI Event AV Latency + // @param audioDelay: audio delay (in millisecs) + // @param videoDelay: video delay (in millisecs) + virtual void OnHdmiInAVLatency(int audioDelay, int videoDelay); + }; + + // @brief Register a listener for HDMI device events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IHdmiInEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for HDMI device events + // @param listener: class object implementing the listener + dsError_t UnRegister(IHdmiInEvents* listener); + + struct ICompositeInEvents { + virtual ~ICompositeInEvents() = default; + + // @brief Composite In Hotplug event + // @param port: Port of the hotplug + // @param isConnected: Is it connected (true) or not(false) + virtual void OnCompositeInHotPlug(dsCompositeInPort_t port, bool isConnected); + + // @brief Composite In Signal status + // @param port: Port of the hotplug + // @param signalStatus: Signal status + virtual void OnCompositeInSignalStatus(dsCompositeInPort_t port, dsCompInSignalStatus_t signalStatus); + + // @brief Composite In status + // @param activePort: Active port + // @param isPresented: is it presented to user + virtual void OnCompositeInStatus(dsCompositeInPort_t activePort, bool isPresented); + + // @brief Composite In Video Mode Update + // @param activePort: Active port + // @param videoResolution: See DisplayVideoPortResolution + virtual void OnCompositeInVideoModeUpdate(dsCompositeInPort_t activePort, dsVideoPortResolution_t videoResolution); + }; + + // @brief Register a listener for composite events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(ICompositeInEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for composite events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(ICompositeInEvents* listener); + + struct IDisplayEvents { + virtual ~IDisplayEvents() = default; + + // @brief Display RX Sense event + // @param displayEvent: DS_DISPLAY_RXSENSE_ON or DS_DISPLAY_RXSENSE_OFF + virtual void OnDisplayRxSense(dsDisplayEvent_t displayEvent); + }; + + // @brief Register a listener for display events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IDisplayEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for display events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IDisplayEvents* listener); + + struct IVideoDeviceEvents { + virtual ~IVideoDeviceEvents() = default; + + // @brief Display Frame rate Pre-change notification + // @param frameRate: new framerate + virtual void OnDisplayFrameratePreChange(const std::string& frameRate); + + // @brief Display Frame rate Post-change notification + // @param frameRate: new framerate + virtual void OnDisplayFrameratePostChange(const std::string& frameRate); + + // @brief Zoom settings changed + // @param zoomSetting: Currently applied zoom setting + virtual void OnZoomSettingsChanged(dsVideoZoom_t zoomSetting); + }; + + // @brief Register a listener for video device events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IVideoDeviceEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for video device events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IVideoDeviceEvents* listener); + + struct IVideoOutputPortEvents { + virtual ~IVideoOutputPortEvents() = default; + + // @brief On Resolution Pre changed + // @param width: width of the resolution + // @param height: height of the resolution + virtual void OnResolutionPreChange(int width, int height); + + // @brief On Resolution Post change + // @param width: width of the resolution + // @param height: height of the resolution + virtual void OnResolutionPostChange(int width, int height); + + // @brief On HDCP Status change + // @param hdcpStatus: HDCP Status + virtual void OnHDCPStatusChange(dsHdcpStatus_t hdcpStatus); + + // @brief On Video Format update + // @param videoFormatHDR: Video format HDR standard + virtual void OnVideoFormatUpdate(dsHDRStandard_t videoFormatHDR); + }; + + // @brief Register a listener for video port events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IVideoOutputPortEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for video port events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IVideoOutputPortEvents* listener); + + struct IAudioOutputPortEvents { + virtual ~IAudioOutputPortEvents() = default; + + // @brief Associated Audio mixing changed + // @param mixing: true or false + virtual void OnAssociatedAudioMixingChanged(bool mixing); + + // @brief Audio Fader balance changed + // @param mixerBalance: applied mixer balance value + virtual void OnAudioFaderControlChanged(int mixerBalance); + + // @brief Primary language for Audio changed + // @param primaryLanguage: current primary language for audio + virtual void OnAudioPrimaryLanguageChanged(const std::string& primaryLanguage); + + // @brief Secondary language for Audio changed + // @param secondaryLanguage: current secondary language for audio + virtual void OnAudioSecondaryLanguageChanged(const std::string& secondaryLanguage); + + // @brief Audio output hot plug event + // @param portType: Type of audio port see AudioPortType + // @param uiPortNumber: The port number assigned by UI + // @param isPortConnected: true (connected) or false (not connected) + virtual void OnAudioOutHotPlug(dsAudioPortType_t portType, uint32_t uiPortNumber, bool isPortConnected); + + // @brief Dolby Atmos capabilities changed + // @param atmosCapability: the Dolby Atmos capability + // @param status: true (available) or false (not available) + virtual void OnDolbyAtmosCapabilitiesChanged(dsATMOSCapability_t atmosCapability, bool status); + + // @brief Audio port state changed + // @param audioPortState: audio port state + virtual void OnAudioPortStateChanged(dsAudioPortState_t audioPortState); + + // @brief Audio mode for the respective audio port - raised for every type of port + // @param audioPortType: audio port type see dsAudioPortType_t + // @param audioStereoMode: audio stereo mode - see dsAudioStereoMode_t + virtual void OnAudioModeEvent(dsAudioPortType_t audioPortType, dsAudioStereoMode_t audioStereoMode); + + // @brief Audio level changed + // @param audioiLevel: audio level value + virtual void OnAudioLevelChangedEvent(int audioLevel); + + // @brief Audio Output format changed + // @param audioFormat: Type of audio format see AudioFormat + virtual void OnAudioFormatUpdate(dsAudioFormat_t audioFormat); + }; + + // @brief Register a listener for audio port events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IAudioOutputPortEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for audio port events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IAudioOutputPortEvents* listener); + + struct IDisplayDeviceEvents { + virtual ~IDisplayDeviceEvents() = default; + + // @brief Display HDMI (out) Hot plug event + // @param displayEvent: display event type see dsDisplayEvent_t + virtual void OnDisplayHDMIHotPlug(dsDisplayEvent_t displayEvent); + }; + + // @brief Register a listener for display device events + // @param listener: class object implementing the listener + // @param clientName: Optional (but highly recommended) name of the client registering for events + // clientName is used for logging purposes only + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t Register(IDisplayDeviceEvents* listener, const std::string& clientName = ""); + + // @brief UnRegister a listener for display device events + // @param listener: class object implementing the listener + // @return dsERR_NONE on success, appropriate dsError_t on failure + dsError_t UnRegister(IDisplayDeviceEvents* listener); + + bool setPowerMode(int mode); + int getPowerMode(); SleepMode getPreferredSleepMode(); int setPreferredSleepMode(const SleepMode); - List getAvailableSleepModes(); - void addPowerModeListener(PowerModeChangeListener *l); - void removePowerModeChangeListener(PowerModeChangeListener *l); - void addDisplayConnectionListener(DisplayConnectionChangeListener *l); - void removeDisplayConnectionListener(DisplayConnectionChangeListener *l); + List getAvailableSleepModes(); - static Host& getInstance(void); + static Host& getInstance(void); List getVideoOutputPorts(); List getAudioOutputPorts(); List getVideoDevices(); - VideoOutputPort &getVideoOutputPort(const std::string &name); - VideoOutputPort &getVideoOutputPort(int id); - AudioOutputPort &getAudioOutputPort(const std::string &name); - AudioOutputPort &getAudioOutputPort(int id); - void notifyPowerChange(const int mode); + VideoOutputPort& getVideoOutputPort(const std::string& name); + VideoOutputPort& getVideoOutputPort(int id); + AudioOutputPort& getAudioOutputPort(const std::string& name); + AudioOutputPort& getAudioOutputPort(int id); float getCPUTemperature(); - uint32_t getVersion(void); + uint32_t getVersion(void); void setVersion(uint32_t versionNumber); - void getHostEDID(std::vector &edid) const; + void getHostEDID(std::vector& edid) const; std::string getSocIDFromSDK(); - void getSinkDeviceAtmosCapability(dsATMOSCapability_t & atmosCapability); + void getSinkDeviceAtmosCapability(dsATMOSCapability_t& atmosCapability); void setAudioAtmosOutputMode(bool enable); void setAssociatedAudioMixing(const bool mixing); - void getAssociatedAudioMixing(bool *mixing); + void getAssociatedAudioMixing(bool* mixing); void setFaderControl(const int mixerbalance); - void getFaderControl(int *mixerBalance); + void getFaderControl(int* mixerBalance); void setPrimaryLanguage(const std::string pLang); - void getPrimaryLanguage(std::string &pLang); + void getPrimaryLanguage(std::string& pLang); void setSecondaryLanguage(const std::string sLang); - void getSecondaryLanguage(std::string &sLang); + void getSecondaryLanguage(std::string& sLang); bool isHDMIOutPortPresent(); std::string getDefaultVideoPortName(); std::string getDefaultAudioPortName(); - void getCurrentAudioFormat(dsAudioFormat_t &audioFormat); - void getMS12ConfigDetails(std::string &configType); - void setAudioMixerLevels (dsAudioInput_t aInput, int volume); + void getCurrentAudioFormat(dsAudioFormat_t& audioFormat); + void getMS12ConfigDetails(std::string& configType); + void setAudioMixerLevels(dsAudioInput_t aInput, int volume); + private: - Host(); - virtual ~Host(); - //To Make the instance as thread-safe, using = delete, the result is, automatically generated methods (constructor, for example) from the compiler will not be created and, therefore, can not be called - Host (const Host&)= delete; - Host& operator=(const Host&)= delete; - - std::list < PowerModeChangeListener* > powerEvntListeners; - std::list < DisplayConnectionChangeListener* > dispEvntListeners; - void notifyDisplayConnectionChange(int portHandle, bool newConnectionStatus); + std::unique_ptr m_impl; + + Host(); + virtual ~Host(); + // Avoid copies + Host(const Host&) = delete; + Host& operator=(const Host&) = delete; + + DefaultImpl& impl(); }; } #endif /* _DS_HOST_HPP_ */ - /** @} */ /** @} */ diff --git a/ds/include/videoOutputPort.hpp b/ds/include/videoOutputPort.hpp index a9b71ade..291af68a 100644 --- a/ds/include/videoOutputPort.hpp +++ b/ds/include/videoOutputPort.hpp @@ -38,6 +38,7 @@ #include #include "dsTypes.h" +#include "dsError.h" /** * @file videoOutputPort.hpp @@ -283,6 +284,8 @@ class VideoOutputPort : public Enumerable { unsigned int getPreferredColorDepth(bool persist = true) ; void setPreferredColorDepth(const unsigned int colordepth, bool persist = true); void getColorDepthCapabilities (unsigned int *capabilities) const; + dsError_t SetStandbyVideoState(const string port , const bool enable); + dsError_t GetStandbyVideoState(const string port , bool &enable); private: Display _display; diff --git a/ds/videoOutputPort.cpp b/ds/videoOutputPort.cpp index c77aa5c4..b1431056 100644 --- a/ds/videoOutputPort.cpp +++ b/ds/videoOutputPort.cpp @@ -911,18 +911,28 @@ int VideoOutputPort::GetHdmiPreference() return hdcpProtocol; } +dsError_t VideoOutputPort::SetStandbyVideoState(const string port , const bool enable) +{ + return dsSetStandbyVideoState(port.c_str(), enable); +} + +dsError_t VideoOutputPort::GetStandbyVideoState(const string port, bool &isEnabled) +{ + return dsGetStandbyVideoState(port.c_str(), isEnabled); +} + /** * @fn void setAllmEnabled(bool enable); * @brief Enables/Disables ALLM mode for connected HDMI display. */ - void VideoOutputPort::Display::setAllmEnabled(bool enable) const - { - printf("VideoOutputPort::Display::setAllmEnabled \r\n"); - dsError_t ret = dsSetAllmEnabled(_handle,enable); - if (ret != dsERR_NONE) { - throw Exception(ret); - } - } +void VideoOutputPort::Display::setAllmEnabled(bool enable) const +{ + printf("VideoOutputPort::Display::setAllmEnabled \r\n"); + dsError_t ret = dsSetAllmEnabled(_handle,enable); + if (ret != dsERR_NONE) { + throw Exception(ret); + } +} /** * @fn void setAVIContentType(dsAviContentType_t contentType); diff --git a/rpc/cli/dsVideoPort.c b/rpc/cli/dsVideoPort.c index 5ff4c9e4..bab1aabd 100644 --- a/rpc/cli/dsVideoPort.c +++ b/rpc/cli/dsVideoPort.c @@ -965,6 +965,54 @@ dsError_t dsSetForceHDRMode(intptr_t handle, dsHDRStandard_t mode) return dsERR_GENERAL ; } +dsError_t dsSetStandbyVideoState(char *port, const bool enable) +{ + dsError_t dsErr = dsERR_GENERAL; + _DEBUG_ENTER(); + + if(NULL != port) + { + dsMgrStandbyVideoStateParam_t param = {0}; + strcpy(param.port, port); + param.isEnabled = enable; + param.result = -1; + + IARM_Result_t rpcRet = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_SetStandbyVideoState, + (void *)¶m, sizeof(param)); + + if (IARM_RESULT_SUCCESS == rpcRet && param.result == 0) + { + dsErr = dsERR_NONE; + } + } + return dsErr; +} + +dsError_t dsGetStandbyVideoState(char *port, bool &enable) +{ + dsError_t dsErr = dsERR_GENERAL; + _DEBUG_ENTER(); + + if(NULL != port) + { + dsMgrStandbyVideoStateParam_t param = {0}; + strcpy(param.port, port); + param.result = -1; + + IARM_Result_t rpcRet = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, + (char *)IARM_BUS_DSMGR_API_GetStandbyVideoState, + (void *)¶m, + sizeof(param)); + + if (IARM_RESULT_SUCCESS == rpcRet && param.result == 0) + { + enable = param.isEnabled; + dsErr = dsERR_NONE; + } + } + return dsErr ; +} /** @} */ /** @} */ diff --git a/rpc/include/dsMgr.h b/rpc/include/dsMgr.h index 49cf9c2c..93d63c66 100755 --- a/rpc/include/dsMgr.h +++ b/rpc/include/dsMgr.h @@ -81,11 +81,14 @@ typedef enum _DSMgr_EventId_t { IARM_BUS_DSMGR_EVENT_MAX, /*!< Max Event */ } IARM_Bus_DSMgr_EventId_t; +#ifndef HAVE_DSAUDIOPORT_STATE_TYPE +#define HAVE_DSAUDIOPORT_STATE_TYPE typedef enum _dsAudioPortState { dsAUDIOPORT_STATE_UNINITIALIZED, dsAUDIOPORT_STATE_INITIALIZED, dsAUDIOPORT_STATE_MAX } dsAudioPortState_t; +#endif /*! DS Manager Event Data */ typedef struct _DSMgr_EventData_t { diff --git a/sample/hdmiIn.cpp b/sample/hdmiIn.cpp index 819eb919..c1e49a39 100644 --- a/sample/hdmiIn.cpp +++ b/sample/hdmiIn.cpp @@ -32,7 +32,6 @@ #include "hdmiIn.hpp" #include "manager.hpp" #include "dsUtl.h" -#include "dsError.h" #include #include #include