#include "implementations/CECCommandHandler.h"
#include "LibCEC.h"
#include "CECClient.h"
+#include "CECTypeUtils.h"
#include "platform/util/timeutils.h"
+#include "platform/util/util.h"
using namespace CEC;
using namespace std;
using namespace PLATFORM;
#define CEC_PROCESSOR_SIGNAL_WAIT_TIME 1000
+#define ACTIVE_SOURCE_CHECK_TIMEOUT 10000
-#define ToString(x) m_libcec->ToString(x)
+#define ToString(x) CCECTypeUtils::ToString(x)
CCECProcessor::CCECProcessor(CLibCEC *libcec) :
m_bInitialised(false),
m_communication(NULL),
m_libcec(libcec),
- m_bMonitor(false),
- m_iPreviousAckMask(0),
m_iStandardLineTimeout(3),
m_iRetryLineTimeout(3),
m_iLastTransmission(0)
CCECProcessor::~CCECProcessor(void)
{
Close();
- delete m_busDevices;
+ DELETE_AND_NULL(m_busDevices);
}
bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = CEC_SERIAL_DEFAULT_BAUDRATE */, uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
// create the processor thread
if (!IsRunning())
{
- if (CreateThread())
- m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
- else
+ if (!CreateThread())
{
m_libcec->AddLog(CEC_LOG_ERROR, "could not create a processor thread");
return false;
}
}
- // mark as initialised
- SetCECInitialised(true);
-
return true;
}
StopThread();
// close the connection
- if (m_communication)
- {
- delete m_communication;
- m_communication = NULL;
- }
+ DELETE_AND_NULL(m_communication);
}
void CCECProcessor::ResetMembers(void)
{
// close the connection
- if (m_communication)
- {
- delete m_communication;
- m_communication = NULL;
- }
+ DELETE_AND_NULL(m_communication);
// reset the other members to the initial state
- m_bMonitor = false;
- m_iPreviousAckMask = 0;
m_iStandardLineTimeout = 3;
m_iRetryLineTimeout = 3;
m_iLastTransmission = 0;
m_libcec->AddLog(CEC_LOG_NOTICE, "connection opened");
+ // mark as initialised
+ SetCECInitialised(true);
+
return bReturn;
}
it->second->ReplaceHandler(true);
}
+void CCECProcessor::CheckPendingActiveSource(void)
+{
+ if (!CECInitialised())
+ return;
+
+ // check each device
+ for (CECDEVICEMAP::iterator it = m_busDevices->Begin(); it != m_busDevices->End(); it++)
+ {
+ if (it->second->GetHandler()->ActiveSourcePending())
+ it->second->ActivateSource();
+ }
+}
+
bool CCECProcessor::OnCommandReceived(const cec_command &command)
{
return m_inBuffer.Push(command);
m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
cec_command command;
+ CTimeout activeSourceCheck(ACTIVE_SOURCE_CHECK_TIMEOUT);
// as long as we're not being stopped and the connection is open
while (!IsStopped() && m_communication->IsOpen())
// check if we need to replace handlers
ReplaceHandlers();
+
+ // check whether we need to activate a source, if it failed before
+ if (activeSourceCheck.TimeLeft() == 0)
+ {
+ CheckPendingActiveSource();
+ activeSourceCheck.Init(ACTIVE_SOURCE_CHECK_TIMEOUT);
+ }
}
}
m_libcec->AddLog(CEC_LOG_TRAFFIC, strTx.c_str());
}
-bool CCECProcessor::SwitchMonitoring(bool bEnable)
-{
- m_libcec->AddLog(CEC_LOG_NOTICE, "== %s monitoring mode ==", bEnable ? "enabling" : "disabling");
-
- {
- CLockObject lock(m_mutex);
- // switch to monitoring mode, which will stop processing of incoming messages
- m_bMonitor = bEnable;
- // and store the current ackmask
- m_iPreviousAckMask = m_communication->GetAckMask();
- }
-
- // set the mask to 0 when enabling monitor mode
- if (bEnable)
- return SetAckMask(0);
- // and restore the previous mask otherwise
- else
- return SetAckMask(m_iPreviousAckMask);
-}
-
bool CCECProcessor::PollDevice(cec_logical_address iAddress)
{
// try to find the primary device
dataStr.AppendFormat(":%02x", (unsigned int)command.parameters[iPtr]);
m_libcec->AddLog(CEC_LOG_TRAFFIC, dataStr.c_str());
- // if we're not in monitor mode
- if (!m_bMonitor)
- {
- // find the initiator
- CCECBusDevice *device = m_busDevices->At(command.initiator);
- // and "handle" the command
- if (device)
- device->HandleCommand(command);
- }
+ // find the initiator
+ CCECBusDevice *device = m_busDevices->At(command.initiator);
+
+ if (device)
+ device->HandleCommand(command);
}
bool CCECProcessor::IsPresentDevice(cec_logical_address address)
if (comm->IsOpen())
{
bReturn = comm->StartBootloader();
- delete comm;
+ DELETE_AND_NULL(comm);
}
return bReturn;
}
if (!client)
return false;
+ libcec_configuration &configuration = *client->GetConfiguration();
+
+ if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_3 && configuration.bMonitorOnly == 1)
+ return true;
+
+ if (!CECInitialised())
+ {
+ m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: CEC processor is not initialised");
+ return false;
+ }
+
+ // ensure that we know the vendor id of the TV
+ GetTV()->GetVendorId(CECDEVICE_UNREGISTERED);
+
// unregister the client first if it's already been marked as registered
if (client->IsRegistered())
UnregisterClient(client);
// get the configuration from the client
- libcec_configuration &configuration = *client->GetConfiguration();
m_libcec->AddLog(CEC_LOG_NOTICE, "registering new CEC client - v%s", ToString((cec_client_version)configuration.clientVersion));
// mark as uninitialised and unregistered
client->Alert(CEC_ALERT_SERVICE_DEVICE, param);
}
+ // ensure that the command handler for the TV is initialised
+ if (bReturn)
+ {
+ CCECCommandHandler *handler = GetTV()->GetHandler();
+ if (handler)
+ handler->InitHandler();
+ }
+
return bReturn;
}
-void CCECProcessor::UnregisterClient(CCECClient *client)
+bool CCECProcessor::UnregisterClient(CCECClient *client)
{
if (!client)
- return;
+ return false;
- m_libcec->AddLog(CEC_LOG_NOTICE, "unregistering client: %s", client->GetConnectionInfo().c_str());
+ if (client->IsRegistered())
+ m_libcec->AddLog(CEC_LOG_NOTICE, "unregistering client: %s", client->GetConnectionInfo().c_str());
// notify the client that it will be unregistered
client->OnUnregister();
}
// set the new ackmask
- SetAckMask(GetLogicalAddresses().AckMask());
+ return SetAckMask(GetLogicalAddresses().AckMask());
}
void CCECProcessor::UnregisterClients(void)