m_busDevices[m_logicalAddresses.primary]->m_strDeviceName = m_strDeviceName;
/* get the vendor id from the TV, so we are using the correct handler */
- m_busDevices[CECDEVICE_TV]->GetVendorId();
+ m_busDevices[CECDEVICE_TV]->RequestVendorId();
ReplaceHandlers();
bReturn = SetHDMIPort(m_iBaseDevice, m_iHDMIPort, true);
{
m_bInitialised = true;
m_busDevices[m_logicalAddresses.primary]->m_bActiveSource = true;
- bReturn = m_busDevices[CECDEVICE_TV]->InitHandler();
+ bReturn = m_busDevices[CECDEVICE_TV]->ActivateSource();
}
if (bReturn)
return TryLogicalAddress(CECDEVICE_AUDIOSYSTEM);
}
+bool CCECProcessor::ChangeDeviceType(cec_device_type from, cec_device_type to)
+{
+ bool bChanged(false);
+
+ CStdString strLog;
+ strLog.Format("changing device type '%s' into '%s'", ToString(from), ToString(to));
+ AddLog(CEC_LOG_NOTICE, strLog);
+
+ CLockObject lock(&m_mutex);
+ CCECBusDevice *previousDevice = GetDeviceByType(from);
+ m_logicalAddresses.primary = CECDEVICE_UNKNOWN;
+
+ for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+ {
+ if (m_types.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
+ continue;
+
+ if (m_types.types[iPtr] == from)
+ {
+ bChanged = true;
+ m_types.types[iPtr] = to;
+ }
+ else if (m_types.types[iPtr] == to && bChanged)
+ {
+ m_types.types[iPtr] = CEC_DEVICE_TYPE_RESERVED;
+ }
+ }
+
+ if (bChanged)
+ {
+ FindLogicalAddresses();
+
+ CCECBusDevice *newDevice = GetDeviceByType(to);
+ if (previousDevice && newDevice)
+ {
+ newDevice->SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC);
+ previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_UNKNOWN);
+
+ newDevice->SetCecVersion(previousDevice->GetCecVersion(false));
+ previousDevice->SetCecVersion(CEC_VERSION_UNKNOWN);
+
+ newDevice->SetMenuLanguage(previousDevice->GetMenuLanguage(false));
+ cec_menu_language lang;
+ lang.device = previousDevice->GetLogicalAddress();
+ for (unsigned int iPtr = 0; iPtr < 4; iPtr++)
+ lang.language[iPtr] = '?';
+ lang.language[3] = 0;
+ previousDevice->SetMenuLanguage(lang);
+
+ newDevice->SetMenuState(previousDevice->GetMenuState());
+ previousDevice->SetMenuState(CEC_MENU_STATE_DEACTIVATED);
+
+ newDevice->SetOSDName(previousDevice->GetOSDName(false));
+ previousDevice->SetOSDName(ToString(previousDevice->GetLogicalAddress()));
+
+ newDevice->SetPhysicalAddress(previousDevice->GetPhysicalAddress(false));
+ previousDevice->SetPhysicalAddress(0xFFFF);
+
+ newDevice->SetPowerStatus(previousDevice->GetPowerStatus(false));
+ previousDevice->SetPowerStatus(CEC_POWER_STATUS_UNKNOWN);
+
+ newDevice->SetVendorId(previousDevice->GetVendorId(false));
+ previousDevice->SetVendorId(CEC_VENDOR_UNKNOWN);
+
+ if ((from == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || from == CEC_DEVICE_TYPE_RECORDING_DEVICE) &&
+ (to == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || to == CEC_DEVICE_TYPE_RECORDING_DEVICE))
+ {
+ ((CCECPlaybackDevice *) newDevice)->SetDeckControlMode(((CCECPlaybackDevice *) previousDevice)->GetDeckControlMode());
+ ((CCECPlaybackDevice *) previousDevice)->SetDeckControlMode(CEC_DECK_CONTROL_MODE_STOP);
+
+ ((CCECPlaybackDevice *) newDevice)->SetDeckStatus(((CCECPlaybackDevice *) previousDevice)->GetDeckStatus());
+ ((CCECPlaybackDevice *) previousDevice)->SetDeckStatus(CEC_DECK_INFO_STOP);
+ }
+ }
+ }
+
+ return true;
+}
+
bool CCECProcessor::FindLogicalAddresses(void)
{
bool bReturn(true);
return m_busDevices[iDestination]->TransmitKeyRelease(bWait);
}
+const char *CCECProcessor::ToString(const cec_device_type type)
+{
+ switch (type)
+ {
+ case CEC_DEVICE_TYPE_AUDIO_SYSTEM:
+ return "audio system";
+ case CEC_DEVICE_TYPE_PLAYBACK_DEVICE:
+ return "playback device";
+ case CEC_DEVICE_TYPE_RECORDING_DEVICE:
+ return "recording device";
+ case CEC_DEVICE_TYPE_RESERVED:
+ return "reserved";
+ case CEC_DEVICE_TYPE_TUNER:
+ return "tuner";
+ case CEC_DEVICE_TYPE_TV:
+ return "TV";
+ default:
+ return "unknown";
+ }
+}
+
const char *CCECProcessor::ToString(const cec_menu_state state)
{
switch (state)
bool SetLineTimeout(uint8_t iTimeout);
+ const char *ToString(const cec_device_type type);
const char *ToString(const cec_menu_state state);
const char *ToString(const cec_version version);
const char *ToString(const cec_power_status status);
virtual void AddKey(void);
virtual void AddLog(cec_log_level level, const CStdString &strMessage);
+ virtual bool ChangeDeviceType(cec_device_type from, cec_device_type to);
virtual bool FindLogicalAddresses(void);
virtual bool SetAckMask(uint16_t iMask);
if (!MyLogicalAddressContains(m_iLogicalAddress))
{
+ m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestCecVersion(GetMyLogicalAddress(), m_iLogicalAddress);
+ m_handler->MarkReady();
}
return bReturn;
}
if (!MyLogicalAddressContains(m_iLogicalAddress) &&
!IsUnsupportedFeature(CEC_OPCODE_GET_MENU_LANGUAGE))
{
+ m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestMenuLanguage(GetMyLogicalAddress(), m_iLogicalAddress);
+ m_handler->MarkReady();
}
return bReturn;
}
+cec_menu_state CCECBusDevice::GetMenuState(void)
+{
+ CLockObject lock(&m_mutex);
+ return m_menuState;
+}
+
cec_logical_address CCECBusDevice::GetMyLogicalAddress(void) const
{
return m_processor->GetLogicalAddress();
if (!MyLogicalAddressContains(m_iLogicalAddress) &&
!IsUnsupportedFeature(CEC_OPCODE_GIVE_OSD_NAME))
{
+ m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestOSDName(GetMyLogicalAddress(), m_iLogicalAddress);
+ m_handler->MarkReady();
}
return bReturn;
}
if (!MyLogicalAddressContains(m_iLogicalAddress))
{
+ m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting physical address of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestPhysicalAddress(GetMyLogicalAddress(), m_iLogicalAddress);
+ m_handler->MarkReady();
}
return bReturn;
}
if (!MyLogicalAddressContains(m_iLogicalAddress) &&
!IsUnsupportedFeature(CEC_OPCODE_GIVE_DEVICE_POWER_STATUS))
{
+ m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestPowerStatus(GetMyLogicalAddress(), m_iLogicalAddress);
+ m_handler->MarkReady();
}
return bReturn;
}
if (!MyLogicalAddressContains(m_iLogicalAddress))
{
+ m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestVendorId(GetMyLogicalAddress(), m_iLogicalAddress);
+ m_handler->MarkReady();
+
+ ReplaceHandler(true);
}
return bReturn;
}
}
}
-bool CCECBusDevice::ReplaceHandler(bool bInitHandler /* = true */)
+bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */)
{
CLockObject lock(&m_mutex);
CLockObject handlerLock(&m_handlerMutex);
if (m_vendor != m_handler->GetVendorId())
{
+ CStdString strLog;
if (m_handler->InUse())
+ {
+ strLog.Format("handler for device '%s' (%x) is being used. not replacing the command handler", GetLogicalAddressName(), GetLogicalAddress());
+ m_processor->AddLog(CEC_LOG_DEBUG, strLog);
return false;
+ }
+ strLog.Format("replacing the command handler for device '%s' (%x)", GetLogicalAddressName(), GetLogicalAddress());
+ m_processor->AddLog(CEC_LOG_DEBUG, strLog);
delete m_handler;
switch (m_vendor)
break;
}
- if (bInitHandler && m_processor->GetLogicalAddresses().IsSet(m_iLogicalAddress) && m_processor->IsInitialised())
- m_handler->InitHandler();
+ m_handler->InitHandler();
+
+ if (bActivateSource && m_processor->GetLogicalAddresses().IsSet(m_iLogicalAddress) && m_processor->IsInitialised())
+ m_handler->ActivateSource();
}
return true;
}
-bool CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true */)
+bool CCECBusDevice::SetVendorId(uint64_t iVendorId)
{
bool bVendorChanged(false);
CLockObject lock(&m_mutex);
bVendorChanged = (m_vendor != (cec_vendor_id)iVendorId);
m_vendor = (cec_vendor_id)iVendorId;
- ReplaceHandler(bInitHandler);
}
CStdString strLog;
m_unsupportedFeatures.insert(opcode);
}
-bool CCECBusDevice::InitHandler(void)
+bool CCECBusDevice::ActivateSource(void)
{
CLockObject lock(&m_mutex);
- return m_handler->InitHandler();
+ return m_handler->ActivateSource();
}
//@}
virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
virtual const char* GetLogicalAddressName(void) const;
virtual cec_menu_language & GetMenuLanguage(bool bUpdate = false);
+ virtual cec_menu_state GetMenuState(void);
virtual cec_logical_address GetMyLogicalAddress(void) const;
virtual uint16_t GetMyPhysicalAddress(void) const;
virtual CStdString GetOSDName(bool bUpdate = false);
virtual void SetInactiveSource(void);
virtual void SetActiveSource(void);
virtual bool TryLogicalAddress(void);
- virtual bool InitHandler(void);
+ virtual bool ActivateSource(void);
virtual void SetDeviceStatus(const cec_bus_device_status newStatus);
virtual void SetPhysicalAddress(uint16_t iNewAddress);
virtual void SetMenuLanguage(const cec_menu_language &menuLanguage);
virtual void SetOSDName(CStdString strName);
virtual void SetMenuState(const cec_menu_state state);
- virtual bool SetVendorId(uint64_t iVendorId, bool bInitHandler = true);
+ virtual bool SetVendorId(uint64_t iVendorId);
virtual void SetPowerStatus(const cec_power_status powerStatus);
virtual bool TransmitActiveSource(void);
bool CCECCommandHandler::HandleCommand(const cec_command &command)
{
- bool bHandled(true), bHandlerChanged(false);
+ bool bHandled(true);
MarkBusy();
CStdString strLog;
HandleSetMenuLanguage(command);
break;
case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
- HandleGivePhysicalAddress(command);
+ if (m_processor->IsInitialised())
+ HandleGivePhysicalAddress(command);
break;
case CEC_OPCODE_GIVE_OSD_NAME:
- HandleGiveOSDName(command);
+ if (m_processor->IsInitialised())
+ HandleGiveOSDName(command);
break;
case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
- HandleGiveDeviceVendorId(command);
+ if (m_processor->IsInitialised())
+ HandleGiveDeviceVendorId(command);
break;
case CEC_OPCODE_DEVICE_VENDOR_ID:
- bHandlerChanged = HandleDeviceVendorId(command);
+ HandleDeviceVendorId(command);
break;
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
HandleDeviceVendorCommandWithId(command);
break;
case CEC_OPCODE_GIVE_DECK_STATUS:
- HandleGiveDeckStatus(command);
+ if (m_processor->IsInitialised())
+ HandleGiveDeckStatus(command);
break;
case CEC_OPCODE_DECK_CONTROL:
HandleDeckControl(command);
break;
case CEC_OPCODE_MENU_REQUEST:
- HandleMenuRequest(command);
+ if (m_processor->IsInitialised())
+ HandleMenuRequest(command);
break;
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
- HandleGiveDevicePowerStatus(command);
+ if (m_processor->IsInitialised())
+ HandleGiveDevicePowerStatus(command);
break;
case CEC_OPCODE_GET_CEC_VERSION:
- HandleGetCecVersion(command);
+ if (m_processor->IsInitialised())
+ HandleGetCecVersion(command);
break;
case CEC_OPCODE_USER_CONTROL_PRESSED:
- HandleUserControlPressed(command);
+ if (m_processor->IsInitialised())
+ HandleUserControlPressed(command);
break;
case CEC_OPCODE_USER_CONTROL_RELEASE:
- HandleUserControlRelease(command);
+ if (m_processor->IsInitialised())
+ HandleUserControlRelease(command);
break;
case CEC_OPCODE_GIVE_AUDIO_STATUS:
- HandleGiveAudioStatus(command);
+ if (m_processor->IsInitialised())
+ HandleGiveAudioStatus(command);
break;
case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
- HandleGiveSystemAudioModeStatus(command);
+ if (m_processor->IsInitialised())
+ HandleGiveSystemAudioModeStatus(command);
break;
case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
- HandleSystemAudioModeRequest(command);
+ if (m_processor->IsInitialised())
+ HandleSystemAudioModeRequest(command);
break;
case CEC_OPCODE_REPORT_AUDIO_STATUS:
HandleReportAudioStatus(command);
HandleSetSystemAudioMode(command);
break;
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
- HandleRequestActiveSource(command);
+ if (m_processor->IsInitialised())
+ HandleRequestActiveSource(command);
break;
case CEC_OPCODE_SET_STREAM_PATH:
HandleSetStreamPath(command);
HandleRoutingInformation(command);
break;
case CEC_OPCODE_STANDBY:
- HandleStandby(command);
+ if (m_processor->IsInitialised())
+ HandleStandby(command);
break;
case CEC_OPCODE_ACTIVE_SOURCE:
HandleActiveSource(command);
break;
}
- if (bHandled && !bHandlerChanged)
+ if (bHandled)
{
CLockObject lock(&m_receiveMutex);
if (m_expectedResponse == CEC_OPCODE_NONE ||
bool CCECCommandHandler::Transmit(cec_command &command, bool bExpectResponse /* = true */, cec_opcode expectedResponse /* = CEC_OPCODE_NONE */)
{
bool bReturn(false);
+ MarkBusy();
command.transmit_timeout = m_iTransmitTimeout;
{
--m_iUseCounter;
}
+ MarkReady();
return bReturn;
}
-bool CCECCommandHandler::InitHandler(void)
+bool CCECCommandHandler::ActivateSource(void)
{
if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
{
virtual void HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
virtual bool HandleReceiveFailed(void);
- virtual bool InitHandler(void);
+ virtual bool InitHandler(void) { return true; }
+ virtual bool ActivateSource(void);
virtual uint8_t GetTransmitRetries(void) const { return m_iTransmitRetries; }
virtual bool TransmitImageViewOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
/* imitate LG devices */
if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
- primary->SetVendorId(CEC_VENDOR_LG, false);
+ primary->SetVendorId(CEC_VENDOR_LG);
SetLGDeckStatus();
/* LG TVs don't always reply to CEC version requests, so just set it to 1.3a */
return true;
}
+bool CSLCommandHandler::ActivateSource(void)
+{
+ CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+ primary->SetActiveSource();
+ primary->TransmitActiveSource();
+ return true;
+}
+
bool CSLCommandHandler::HandleActiveSource(const cec_command &command)
{
if (command.parameters.size == 2)
virtual void HandlePoll(const cec_logical_address iInitiator, const cec_logical_address iDestination);
virtual bool HandleReceiveFailed(void);
+
virtual bool InitHandler(void);
+ virtual bool ActivateSource(void);
protected:
virtual bool HandleActiveSource(const cec_command &command);
#include "VLCommandHandler.h"
#include "../devices/CECBusDevice.h"
-#include "../util/StdString.h"
+#include "../CECProcessor.h"
using namespace CEC;
CCECCommandHandler(busDevice)
{
}
+
+bool CVLCommandHandler::InitHandler(void)
+{
+ CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+ if (primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
+ {
+ return m_processor->ChangeDeviceType(CEC_DEVICE_TYPE_RECORDING_DEVICE, CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+ }
+ return CCECCommandHandler::InitHandler();
+}
CVLCommandHandler(CCECBusDevice *busDevice);
virtual ~CVLCommandHandler(void) {};
virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_PANASONIC; };
+ virtual bool InitHandler(void);
};
};