From 29d5198c74435c4bb10bcfa635187f005a0c681d Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Sat, 23 Jun 2012 10:12:38 +0200 Subject: [PATCH] added a callback for clients that is called when a source is (de)activated, so the client can respond to this action, e.g. by starting a media player application --- include/cectypes.h | 9 +++++++ src/LibCecSharp/CecSharpTypes.h | 30 ++++++++++++++++++++++ src/lib/CECClient.cpp | 24 +++++++++++++++++ src/lib/CECClient.h | 2 ++ src/lib/devices/CECBusDevice.cpp | 44 +++++++++++++++++++++++++++----- 5 files changed, 102 insertions(+), 7 deletions(-) diff --git a/include/cectypes.h b/include/cectypes.h index bb9dc32..df59193 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -1124,6 +1124,7 @@ typedef int (CEC_CDECL* CBCecCommandType)(void *param, const cec_command &); typedef int (CEC_CDECL* CBCecConfigurationChangedType)(void *param, const libcec_configuration &); typedef int (CEC_CDECL* CBCecAlertType)(void *param, const libcec_alert, const libcec_parameter &); typedef int (CEC_CDECL* CBCecMenuStateChangedType)(void *param, const cec_menu_state); +typedef void (CEC_CDECL* CBCecSourceActivatedType)(void *param, const cec_logical_address, const uint8_t); typedef struct ICECCallbacks { @@ -1174,6 +1175,13 @@ typedef struct ICECCallbacks */ CBCecMenuStateChangedType CBCecMenuStateChanged; + /*! + * @brief Called when a source that's handled by this client is activated. + * @param logicalAddress The address that was just activated. + * @param bActivated 1 when activated, 0 when deactivated. + */ + CBCecSourceActivatedType CBCecSourceActivated; + #ifdef __cplusplus ICECCallbacks(void) { Clear(); } ~ICECCallbacks(void) { Clear(); }; @@ -1186,6 +1194,7 @@ typedef struct ICECCallbacks CBCecConfigurationChanged = NULL; CBCecAlert = NULL; CBCecMenuStateChanged = NULL; + CBCecSourceActivated = NULL; } #endif } ICECCallbacks; diff --git a/src/LibCecSharp/CecSharpTypes.h b/src/LibCecSharp/CecSharpTypes.h index 2eec98e..09cdae1 100644 --- a/src/LibCecSharp/CecSharpTypes.h +++ b/src/LibCecSharp/CecSharpTypes.h @@ -698,6 +698,7 @@ namespace CecSharp typedef int (__stdcall *CONFIGCB) (const CEC::libcec_configuration &config); typedef int (__stdcall *ALERTCB) (const CEC::libcec_alert, const CEC::libcec_parameter &data); typedef int (__stdcall *MENUCB) (const CEC::cec_menu_state newVal); + typedef void (__stdcall *ACTICB) (const CEC::cec_logical_address logicalAddress, const uint8_t bActivated); static LOGCB g_logCB; static KEYCB g_keyCB; @@ -705,6 +706,7 @@ namespace CecSharp static CONFIGCB g_configCB; static ALERTCB g_alertCB; static MENUCB g_menuCB; + static ACTICB g_sourceActivatedCB; static CEC::ICECCallbacks g_cecCallbacks; int CecLogMessageCB(void *cbParam, const CEC::cec_log_message &message) @@ -749,6 +751,12 @@ namespace CecSharp return 0; } + void CecSourceActivatedCB(void *cbParam, const CEC::cec_logical_address logicalAddress, const uint8_t bActivated) + { + if (g_sourceActivatedCB) + g_sourceActivatedCB(logicalAddress, bActivated); + } + #pragma managed // delegates for the unmanaged callback methods public delegate int CecLogMessageManagedDelegate(const CEC::cec_log_message &); @@ -757,6 +765,7 @@ namespace CecSharp public delegate int CecConfigManagedDelegate(const CEC::libcec_configuration &); public delegate int CecAlertManagedDelegate(const CEC::libcec_alert, const CEC::libcec_parameter &); public delegate int CecMenuManagedDelegate(const CEC::cec_menu_state newVal); + public delegate void CecSourceActivatedManagedDelegate(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated); // callback method interface public ref class CecCallbackMethods @@ -828,6 +837,10 @@ namespace CecSharp return 0; } + virtual void SourceActivated(CecLogicalAddress logicalAddress, bool bActivated) + { + } + protected: // managed callback methods int CecLogMessageManaged(const CEC::cec_log_message &message) @@ -897,6 +910,12 @@ namespace CecSharp return iReturn; } + void CecSourceActivatedManaged(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated) + { + if (m_bHasCallbacks) + m_callbacks->SourceActivated((CecLogicalAddress)logicalAddress, bActivated == 1); + } + void DestroyDelegates() { m_bHasCallbacks = false; @@ -908,6 +927,7 @@ namespace CecSharp m_commandGCHandle.Free(); m_alertGCHandle.Free(); m_menuGCHandle.Free(); + m_sourceActivatedGCHandle.Free(); } } @@ -955,6 +975,12 @@ namespace CecSharp g_menuCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_menuDelegate).ToPointer()); g_cecCallbacks.CBCecMenuStateChanged = CecMenuCB; + // create the delegate method for the source activated callback + m_sourceActivatedDelegate = gcnew CecSourceActivatedManagedDelegate(this, &CecCallbackMethods::CecSourceActivatedManaged); + m_sourceActivatedGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_sourceActivatedDelegate); + g_sourceActivatedCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_sourceActivatedDelegate).ToPointer()); + g_cecCallbacks.CBCecSourceActivated = CecSourceActivatedCB; + delete context; m_bDelegatesCreated = true; } @@ -984,6 +1010,10 @@ namespace CecSharp static System::Runtime::InteropServices::GCHandle m_menuGCHandle; MENUCB m_menuCallback; + CecSourceActivatedManagedDelegate ^ m_sourceActivatedDelegate; + static System::Runtime::InteropServices::GCHandle m_sourceActivatedGCHandle; + ACTICB m_sourceActivatedCallback; + CecCallbackMethods ^ m_callbacks; bool m_bHasCallbacks; bool m_bDelegatesCreated; diff --git a/src/lib/CECClient.cpp b/src/lib/CECClient.cpp index d2a3dcc..accd565 100644 --- a/src/lib/CECClient.cpp +++ b/src/lib/CECClient.cpp @@ -906,6 +906,30 @@ int CCECClient::MenuStateChanged(const cec_menu_state newState) return 0; } +void CCECClient::SourceActivated(const cec_logical_address logicalAddress) +{ + CLockObject lock(m_mutex); + + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source activated: %s (%x)", ToString(logicalAddress), logicalAddress); + + if (m_configuration.callbacks && + m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_7_1 && + m_configuration.callbacks->CBCecSourceActivated) + m_configuration.callbacks->CBCecSourceActivated(m_configuration.callbackParam, logicalAddress, 1); +} + +void CCECClient::SourceDeactivated(const cec_logical_address logicalAddress) +{ + CLockObject lock(m_mutex); + + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source deactivated: %s (%x)", ToString(logicalAddress), logicalAddress); + + if (m_configuration.callbacks && + m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_7_1 && + m_configuration.callbacks->CBCecSourceActivated) + m_configuration.callbacks->CBCecSourceActivated(m_configuration.callbackParam, logicalAddress, 0); +} + void CCECClient::Alert(const libcec_alert type, const libcec_parameter ¶m) { CLockObject lock(m_mutex); diff --git a/src/lib/CECClient.h b/src/lib/CECClient.h index 87a4b7f..fccb083 100644 --- a/src/lib/CECClient.h +++ b/src/lib/CECClient.h @@ -182,6 +182,8 @@ namespace CEC virtual void AddKey(const cec_keypress &key); virtual void SetCurrentButton(const cec_user_control_code iButtonCode); virtual void CheckKeypressTimeout(void); + virtual void SourceActivated(const cec_logical_address logicalAddress); + virtual void SourceDeactivated(const cec_logical_address logicalAddress); protected: /*! diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index 88d6b46..f01d47c 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -32,6 +32,7 @@ #include "CECBusDevice.h" #include "../CECProcessor.h" +#include "../CECClient.h" #include "../implementations/ANCommandHandler.h" #include "../implementations/CECCommandHandler.h" #include "../implementations/SLCommandHandler.h" @@ -916,30 +917,59 @@ bool CCECBusDevice::RequestActiveSource(bool bWaitForResponse /* = true */) void CCECBusDevice::MarkAsActiveSource(void) { - CLockObject lock(m_mutex); - if (!m_bActiveSource) - LIB_CEC->AddLog(CEC_LOG_DEBUG, "making %s (%x) the active source", GetLogicalAddressName(), m_iLogicalAddress); - else - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%x) was already marked as active source", GetLogicalAddressName(), m_iLogicalAddress); + bool bWasActivated(false); + + // set the power status to powered on + SetPowerStatus(CEC_POWER_STATUS_ON); + + // mark this device as active source + { + CLockObject lock(m_mutex); + if (!m_bActiveSource) + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "making %s (%x) the active source", GetLogicalAddressName(), m_iLogicalAddress); + bWasActivated = true; + } + else + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%x) was already marked as active source", GetLogicalAddressName(), m_iLogicalAddress); + m_bActiveSource = true; + } + + // mark other devices as inactive sources CECDEVICEVEC devices; m_processor->GetDevices()->Get(devices); for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++) if ((*it)->GetLogicalAddress() != m_iLogicalAddress) (*it)->MarkAsInactiveSource(); - m_bActiveSource = true; - SetPowerStatus(CEC_POWER_STATUS_ON); + if (bWasActivated) + { + CCECClient *client = GetClient(); + if (client) + client->SourceActivated(m_iLogicalAddress); + } } void CCECBusDevice::MarkAsInactiveSource(void) { + bool bWasDeactivated(false); { CLockObject lock(m_mutex); if (m_bActiveSource) + { LIB_CEC->AddLog(CEC_LOG_DEBUG, "marking %s (%X) as inactive source", GetLogicalAddressName(), m_iLogicalAddress); + bWasDeactivated = true; + } m_bActiveSource = false; } + + if (bWasDeactivated) + { + CCECClient *client = GetClient(); + if (client) + client->SourceDeactivated(m_iLogicalAddress); + } } bool CCECBusDevice::TransmitActiveSource(void) -- 2.34.1