+libcec (2.0.2-1) unstable; urgency=low
+
+ * changed/added:
+ * missing from the previous changelog: added support for the CuBox TDA995x
+ credits: warped-rudi
+ * lower retry timeout for source switches
+ * cec-client: wait for the source switch to finish when cec-client is
+ called with the -s switch
+ * request the power status of the TV directly after registering a new
+ client
+ * fixed:
+ * don't keep trying to send 'image view on' commands to the TV when no TV
+ is connected, and just send the 'set active source' command. fixes source
+ switch and debug log spam for people without a TV connected
+ * don't keep waiting for an updated power status from the TV for Panasonic,
+ but request a status update once every 5 seconds, or we can possibly wait
+ forever for the tv to send it
+ * log what we received exactly when logging FIXME
+ * typo in CVLCommandHandler::VendorPreActivateSourceHook. bugzid: 1087
+ * if we failed to get the physical address of the device that we are
+ connected to in the config, then try to use the address that was
+ persisted in the eeprom before resetting to the default value, 1.0.0.0.
+ closes #50.
+ * don't update the device status of unregistered/broadcast
+ * log all device status changes
+ * CCECClient::IsLibCECActiveSource returns false now while the active
+ source command is pending
+ * log failed acks and other errors in the debug log again
+ * don't send 'image view on' when the TV is already powering up
+ * reset the delayed source switch timeout properly, so we don't spam
+ commands every second
+ * don't change the device status when sending a delayed source switch
+ * don't send out commands to a device that is marked as not present or
+ handled by libCEC
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Thu, 11 Oct 2012 15:48:00 +0100
+
libcec (2.0.1-1) unstable; urgency=low
* changed/added:
+libcec (2.0.2-1) unstable; urgency=low
+
+ * changed/added:
+ * missing from the previous changelog: added support for the CuBox TDA995x
+ credits: warped-rudi
+ * lower retry timeout for source switches
+ * cec-client: wait for the source switch to finish when cec-client is
+ called with the -s switch
+ * request the power status of the TV directly after registering a new
+ client
+ * fixed:
+ * don't keep trying to send 'image view on' commands to the TV when no TV
+ is connected, and just send the 'set active source' command. fixes source
+ switch and debug log spam for people without a TV connected
+ * don't keep waiting for an updated power status from the TV for Panasonic,
+ but request a status update once every 5 seconds, or we can possibly wait
+ forever for the tv to send it
+ * log what we received exactly when logging FIXME
+ * typo in CVLCommandHandler::VendorPreActivateSourceHook. bugzid: 1087
+ * if we failed to get the physical address of the device that we are
+ connected to in the config, then try to use the address that was
+ persisted in the eeprom before resetting to the default value, 1.0.0.0.
+ closes #50.
+ * don't update the device status of unregistered/broadcast
+ * log all device status changes
+ * CCECClient::IsLibCECActiveSource returns false now while the active
+ source command is pending
+ * log failed acks and other errors in the debug log again
+ * don't send 'image view on' when the TV is already powering up
+ * reset the delayed source switch timeout properly, so we don't spam
+ commands every second
+ * don't change the device status when sending a delayed source switch
+ * don't send out commands to a device that is marked as not present or
+ handled by libCEC
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Thu, 11 Oct 2012 15:48:00 +0100
+
libcec (2.0.1-1) unstable; urgency=low
* changed/added:
#include "cectypes.h"
-#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_2_0_0
+#define LIBCEC_VERSION_CURRENT CEC_SERVER_VERSION_2_0_1
namespace CEC
{
/*!
* wait this amount of milliseconds before retrying when libCEC failed to make itself the active source
*/
-#define CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS 5000
+#define CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS 1000
/*!
* don't forward any power off command to the client application for this amount of milliseconds after sending a power off command
CEC_CLIENT_VERSION_1_9_0 = 0x1900,
CEC_CLIENT_VERSION_1_99_0 = 0x1990,
CEC_CLIENT_VERSION_2_0_0 = 0x2000,
+ CEC_CLIENT_VERSION_2_0_1 = 0x2001,
} cec_client_version;
typedef enum cec_server_version
CEC_SERVER_VERSION_1_9_0 = 0x1900,
CEC_SERVER_VERSION_1_99_0 = 0x1990,
CEC_SERVER_VERSION_2_0_0 = 0x2000,
+ CEC_SERVER_VERSION_2_0_1 = 0x2001,
} cec_server_version;
struct libcec_configuration
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyVersion("2.0.1.0")]
+[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
-[assembly:AssemblyVersionAttribute("2.0.0.0")];
+[assembly:AssemblyVersionAttribute("2.0.1.0")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
/// <summary>
/// v2.0.0
/// </summary>
- Version2_0_0 = 0x2000
+ Version2_0_0 = 0x2000,
+ /// <summary>
+ /// v2.0.1
+ /// </summary>
+ Version2_0_1 = 0x2001
};
/// <summary>
/// <summary>
/// v2.0.0
/// </summary>
- Version2_0_0 = 0x2000
+ Version2_0_0 = 0x2000,
+ /// <summary>
+ /// v2.0.1
+ /// </summary>
+ Version2_0_1 = 0x2001
};
/// <summary>
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.7.2.0")]
-[assembly: AssemblyFileVersion("1.7.2.0")]
+[assembly: AssemblyVersion("2.0.1.0")]
+[assembly: AssemblyFileVersion("2.0.1.0")]
// set the default address when something went wrong
if (!bReturn)
{
- LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
- iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+ uint16_t iEepromAddress = m_processor->GetPhysicalAddressFromEeprom();
+ if (CLibCEC::IsValidPhysicalAddress(iEepromAddress))
+ {
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the value that was persisted in the eeprom, %04X", iPhysicalAddress, iEepromAddress);
+ iPhysicalAddress = iEepromAddress;
+ bReturn = true;
+ }
+ else
+ {
+ LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
+ iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+ }
}
// and set the address
cec_logical_address activeSource = m_processor->GetActiveSource();
CCECBusDevice *device = m_processor->GetDevice(activeSource);
if (device)
- bReturn = device->IsHandledByLibCEC();
+ bReturn = device->IsHandledByLibCEC() && !device->GetHandler()->ActiveSourcePending();
}
return bReturn;
}
return true;
}
+uint16_t CCECProcessor::GetPhysicalAddressFromEeprom(void)
+{
+ libcec_configuration config; config.Clear();
+ if (m_communication)
+ m_communication->GetConfiguration(config);
+ return config.iPhysicalAddress;
+}
+
bool CCECProcessor::RegisterClient(CCECClient *client)
{
if (!client)
// ensure that controlled mode is enabled
m_communication->SetControlledMode(true);
+ // source logical address for requests
+ cec_logical_address sourceAddress(CECDEVICE_UNREGISTERED);
+ if (!m_communication->SupportsSourceLogicalAddress(CECDEVICE_UNREGISTERED))
+ {
+ if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE))
+ sourceAddress = CECDEVICE_FREEUSE;
+ else
+ {
+ m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: both unregistered and free use are not supported by the device");
+ return false;
+ }
+ }
+
// ensure that we know the vendor id of the TV
CCECBusDevice *tv = GetTV();
- cec_vendor_id tvVendor = CEC_VENDOR_UNKNOWN;
- if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_UNREGISTERED))
- tvVendor = tv->GetVendorId(CECDEVICE_UNREGISTERED);
- else if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE))
- tvVendor = tv->GetVendorId(CECDEVICE_FREEUSE);
+ cec_vendor_id tvVendor(tv->GetVendorId(sourceAddress));
// wait until the handler is replaced, to avoid double registrations
if (tvVendor != CEC_VENDOR_UNKNOWN &&
// mark the client as registered
client->SetRegistered(true);
+ sourceAddress = client->GetPrimaryLogicalAdddress();
+
// initialise the client
bool bReturn = client->OnRegister();
GetTV()->MarkHandlerReady();
}
+ // request the power status of the TV
+ tv->RequestPowerStatus(sourceAddress, true);
+
return bReturn;
}
bool RegisterClient(CCECClient *client);
bool UnregisterClient(CCECClient *client);
void UnregisterClients(void);
+ uint16_t GetPhysicalAddressFromEeprom(void);
CCECClient *GetPrimaryClient(void);
CCECClient *GetClient(const cec_logical_address address);
return "2.0.0-pre";
case CEC_CLIENT_VERSION_2_0_0:
return "2.0.0";
+ case CEC_CLIENT_VERSION_2_0_1:
+ return "2.0.1";
default:
return "Unknown";
}
return "2.0.0-pre";
case CEC_CLIENT_VERSION_2_0_0:
return "2.0.0";
+ case CEC_CLIENT_VERSION_2_0_1:
+ return "2.0.1";
default:
return "Unknown";
}
if (!m_message->IsTranmission())
{
- m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_WARNING, "FIXME! not a transmission");
+ m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_WARNING, "FIXME! not a transmission: %s", msg.ToString().c_str());
return false;
}
CLockObject lock(m_mutex);
#ifdef CEC_DEBUGGING
m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_DEBUG, "%s - received response - %s", ToString(), message.ToString().c_str());
+#else
+ if (message.IsError())
+ m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_DEBUG, "%s - received response - %s", ToString(), message.ToString().c_str());
#endif
m_message->response = message.packet;
if (m_message->IsTranmission())
m_messages.erase(iEntryId);
}
- if (msg->ReplyIsError())
+ if (msg->ReplyIsError() && msg->state != ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED)
msg->state = ADAPTER_MESSAGE_STATE_ERROR;
delete entry;
{
CLockObject lock(m_mutex);
m_iLastActive = GetTimeMs();
-
- /* don't call GetStatus() here, just read the value with the mutex locked */
- if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC && command.opcode_set == 1)
- m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
-
MarkBusy();
}
void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus, cec_version libCECSpecVersion /* = CEC_VERSION_1_4 */)
{
+ if (m_iLogicalAddress == CECDEVICE_UNREGISTERED)
+ return;
+
{
CLockObject lock(m_mutex);
switch (newStatus)
if (bReturn)
{
m_iLastActive = GetTimeMs();
- destDevice->m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
+ SetDeviceStatus(CEC_DEVICE_STATUS_PRESENT);
}
else
- destDevice->m_deviceStatus = CEC_DEVICE_STATUS_NOT_PRESENT;
+ SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
MarkReady();
return bReturn;
return bReturn;
}
+ // check whether the destination is not marked as not present or handled by libCEC
+ if (command.destination != CECDEVICE_BROADCAST && command.opcode_set)
+ {
+ CCECBusDevice* destinationDevice = m_processor->GetDevice(command.destination);
+ cec_bus_device_status status = destinationDevice ? destinationDevice->GetStatus() : CEC_DEVICE_STATUS_NOT_PRESENT;
+ if (status == CEC_DEVICE_STATUS_NOT_PRESENT)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "not sending command '%s': destination device '%s' marked as not present", ToString(command.opcode),ToString(command.destination));
+ return bReturn;
+ }
+ else if (status == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "not sending command '%s': destination device '%s' marked as handled by libCEC", ToString(command.opcode),ToString(command.destination));
+ return bReturn;
+ }
+ }
+
{
uint8_t iTries(0), iMaxTries(!command.opcode_set ? 1 : m_iTransmitRetries + 1);
while (!bReturn && ++iTries <= iMaxTries && !m_busDevice->IsUnsupportedFeature(command.opcode))
}
// update the power state and menu state
- m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
- m_busDevice->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+ if (!bTransmitDelayedCommandsOnly)
+ {
+ m_busDevice->SetPowerStatus(CEC_POWER_STATUS_ON);
+ m_busDevice->SetMenuState(CEC_MENU_STATE_ACTIVATED);
+ }
// vendor specific hook
VendorPreActivateSourceHook();
// power on the TV
- bool bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
+ CCECBusDevice* tv = m_processor->GetDevice(CECDEVICE_TV);
+ bool bTvPresent = (tv && tv->GetStatus() == CEC_DEVICE_STATUS_PRESENT);
+ bool bActiveSourceFailed(false);
+ if (bTvPresent)
+ {
+ if (tv->GetCurrentPowerStatus() != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON)
+ bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
+ }
+ else
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV not present, not sending 'image view on'");
// check if we're allowed to switch sources
bool bSourceSwitchAllowed = SourceSwitchAllowed();
// switch sources (if allowed)
if (!bActiveSourceFailed && bSourceSwitchAllowed)
{
- bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false) ||
- !m_busDevice->TransmitMenuState(CECDEVICE_TV, false);
+ bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false);
+ if (bTvPresent && !bActiveSourceFailed)
+ bActiveSourceFailed = !m_busDevice->TransmitMenuState(CECDEVICE_TV, false);
// update the deck status for playback devices
- if (!bActiveSourceFailed)
+ if (bTvPresent && !bActiveSourceFailed)
{
CCECPlaybackDevice *playbackDevice = m_busDevice->AsPlaybackDevice();
if (playbackDevice && SendDeckStatusUpdateOnActiveSource())
if (bActiveSourceFailed || !bSourceSwitchAllowed)
{
LIB_CEC->AddLog(CEC_LOG_DEBUG, "failed to make '%s' the active source. will retry later", m_busDevice->GetLogicalAddressName());
+ int64_t now(GetTimeMs());
CLockObject lock(m_mutex);
- if (m_iActiveSourcePending == 0)
- m_iActiveSourcePending = GetTimeMs() + (int64_t)CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS;
+ if (m_iActiveSourcePending == 0 || m_iActiveSourcePending < now)
+ m_iActiveSourcePending = now + (int64_t)CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS;
return false;
}
else
virtual bool SupportsDeviceType(const cec_device_type UNUSED(type)) const { return true; };
virtual cec_device_type GetReplacementDeviceType(const cec_device_type type) const { return type; }
+ virtual bool ActiveSourcePending(void) const { return m_iActiveSourcePending != 0; }
protected:
virtual int HandleActiveSource(const cec_command &command);
#define VL_POWERED_DOWN 0x01
#define VL_UNKNOWN1 0x06
+#define VL_REQUEST_POWER_STATUS_TIMEOUT 5000
+
using namespace CEC;
using namespace PLATFORM;
CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending),
m_iPowerUpEventReceived(0),
m_bCapabilitiesSent(false),
- m_bPowerStatusRequested(false)
+ m_iPowerStatusRequested(0)
{
m_vendorId = CEC_VENDOR_PANASONIC;
}
if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV)
{
+ CCECBusDevice* tv = m_processor->GetTV();
+ if (tv && tv->GetStatus() != CEC_DEVICE_STATUS_PRESENT)
+ return true;
+
// get the status from the TV
- CCECBusDevice *tv = m_processor->GetTV();
if (tv && tv->GetCurrentVendorId() == CEC_VENDOR_PANASONIC)
{
CVLCommandHandler *handler = static_cast<CVLCommandHandler *>(tv->GetHandler());
bool bTransmit(false);
{
CLockObject lock(m_mutex);
- bTransmit = m_bCapabilitiesSent;
+ bTransmit = !m_bCapabilitiesSent;
}
if (bTransmit)
SendVendorCommandCapabilities(m_processor->GetLogicalAddress(), CECDEVICE_TV);
bool CVLCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse /* = true */)
{
- m_bPowerStatusRequested = true;
+ m_iPowerStatusRequested = GetTimeMs();
return CCECCommandHandler::TransmitRequestPowerStatus(iInitiator, iDestination, bWaitForResponse);
}
bool CVLCommandHandler::SourceSwitchAllowed(void)
{
- if (!PowerUpEventReceived() && !m_bPowerStatusRequested)
+ int64_t now(GetTimeMs());
+ if (!PowerUpEventReceived() && now - m_iPowerStatusRequested > VL_REQUEST_POWER_STATUS_TIMEOUT)
TransmitRequestPowerStatus(m_processor->GetPrimaryDevice()->GetLogicalAddress(), CECDEVICE_TV, false);
return PowerUpEventReceived();
PLATFORM::CMutex m_mutex;
uint64_t m_iPowerUpEventReceived;
bool m_bCapabilitiesSent;
- bool m_bPowerStatusRequested;
+ int64_t m_iPowerStatusRequested;
};
};
using namespace std;
using namespace PLATFORM;
-#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_2_0_0;
+#define CEC_CONFIG_VERSION CEC_CLIENT_VERSION_2_0_1;
#include "../../include/cecloader.h"
if (command == "as")
{
parser->SetActiveSource();
+ // wait for the source switch to finish for 15 seconds tops
+ if (g_bSingleCommand)
+ {
+ CTimeout timeout(15000);
+ bool bActiveSource(false);
+ while (timeout.TimeLeft() > 0 && !bActiveSource)
+ {
+ bActiveSource = parser->IsLibCECActiveSource();
+ if (!bActiveSource)
+ CEvent::Sleep(100);
+ }
+ }
return true;
}