*/
virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS) = 0;
+ /*!
+ * @brief Enable physical address detection (if the connected adapter supports this).
+ * @return True when physical address detection was enabled, false otherwise.
+ */
+ virtual bool EnablePhysicalAddressDetection(void) = 0;
+
+ /*!
+ * @brief Changes the active HDMI port.
+ * @param iBaseDevice The device to which this libcec is connected.
+ * @param iPort The new port number.
+ * @return True when changed, false otherwise.
+ */
+ virtual bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort) = 0;
+
/*!
* @brief Power on the connected CEC capable devices.
* @param address The logical address to power on.
*/
virtual bool IsActiveDeviceType(cec_device_type type) = 0;
- /*!
- * @brief Changes the active HDMI port.
- * @param iPort The new port number.
- * @return True when changed, false otherwise.
- */
- virtual bool SetHDMIPort(uint8_t iPort) = 0;
-
/*!
* @brief Sends a volume up keypress to an audiosystem if it's present.
+ * @param bWait Wait for the response of the audiosystem when true.
* @return The new audio status.
*/
- virtual uint8_t VolumeUp(void) = 0;
+ virtual uint8_t VolumeUp(bool bWait = true) = 0;
/*!
* @brief Sends a volume down keypress to an audiosystem if it's present.
+ * @param bWait Wait for the response of the audiosystem when true.
* @return The new audio status.
*/
- virtual uint8_t VolumeDown(void) = 0;
+ virtual uint8_t VolumeDown(bool bWait = true) = 0;
/*!
* @brief Sends a mute keypress to an audiosystem if it's present.
+ * @param bWait Wait for the response of the audiosystem when true.
* @return The new audio status.
*/
- virtual uint8_t MuteAudio(void) = 0;
+ virtual uint8_t MuteAudio(bool bWait = true) = 0;
+
+ /*!
+ * @brief Send a keypress to a device on the CEC bus.
+ * @param iDestination The address to send the message to.
+ * @param key The key to send.
+ * @param bWait True to wait for a response, false otherwise.
+ * @return True when the keypress was acked, false otherwise.
+ */
+ virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = false) = 0;
+
+ /*!
+ * @brief Send a key release to a device on the CEC bus.
+ * @param iDestination The address to send the message to.
+ * @param bWait True to wait for a response, false otherwise.
+ * @return True when the keypress was acked, false otherwise.
+ */
+ virtual bool SendKeyRelease(cec_logical_address iDestination, bool bWait = false) = 0;
+
+ /*!
+ * @brief Get the OSD name of a device on the CEC bus.
+ * @param iAddress The device to get the OSD name for.
+ * @return The OSD name.
+ */
+ virtual cec_osd_name GetOSDName(cec_logical_address iAddress) = 0;
+
+ virtual const char *ToString(const cec_menu_state state) = 0;
+ virtual const char *ToString(const cec_version version) = 0;
+ virtual const char *ToString(const cec_power_status status) = 0;
+ virtual const char *ToString(const cec_logical_address address) = 0;
+ virtual const char *ToString(const cec_deck_control_mode mode) = 0;
+ virtual const char *ToString(const cec_deck_info status) = 0;
+ virtual const char *ToString(const cec_opcode opcode) = 0;
+ virtual const char *ToString(const cec_system_audio_status mode) = 0;
+ virtual const char *ToString(const cec_audio_status status) = 0;
+ virtual const char *ToString(const cec_vendor_id vendor) = 0;
+
};
};
extern DECLSPEC int cec_is_active_device_type(cec_device_type type);
#endif
-extern DECLSPEC int cec_set_hdmi_port(uint8_t iPort);
+#ifdef __cplusplus
+extern DECLSPEC int cec_set_hdmi_port(CEC::cec_logical_address iBaseDevice, uint8_t iPort);
+#else
+extern DECLSPEC int cec_set_hdmi_port(cec_logical_address iBaseDevice, uint8_t iPort);
+#endif
+
+extern DECLSPEC int cec_volume_up(int bWait);
+
+extern DECLSPEC int cec_volume_down(int bWait);
+
+extern DECLSPEC int cec_mute_audio(int bWait);
+
+#ifdef __cplusplus
+extern DECLSPEC int cec_send_keypress(CEC::cec_logical_address iDestination, CEC::cec_user_control_code key, int bWait);
+#else
+extern DECLSPEC int cec_send_keypress(cec_logical_address iDestination, cec_user_control_code key, int bWait);
+#endif
-extern DECLSPEC int cec_volume_up(void);
+#ifdef __cplusplus
+extern DECLSPEC int cec_send_key_release(CEC::cec_logical_address iDestination, int bWait);
+#else
+extern DECLSPEC int cec_send_key_release(cec_logical_address iDestination, int bWait);
+#endif
-extern DECLSPEC int cec_volume_down(void);
+#ifdef __cplusplus
+extern DECLSPEC CEC::cec_osd_name cec_get_osd_name(CEC::cec_logical_address iAddress);
+#else
+extern DECLSPEC cec_osd_name cec_get_osd_name(cec_logical_address iAddress);
+#endif
-extern DECLSPEC int cec_mute_audio(void);
+extern DECLSPEC int cec_enable_physical_address_detection(void);
#ifdef __cplusplus
};
//default physical address 1.0.0.0, HDMI port 1
#define CEC_DEFAULT_PHYSICAL_ADDRESS 0x1000
#define CEC_DEFAULT_HDMI_PORT 1
+#define CEC_DEFAULT_BASE_DEVICE 0
#define MSGSTART 0xFF
#define MSGEND 0xFE
#define MSGESC 0xFD
CEC_VENDOR_PANASONIC = 0x8045,
CEC_VENDOR_PIONEER = 0xE036,
CEC_VENDOR_ONKYO = 0x09B0,
+ CEC_VENDOR_YAMAHA = 0xA0DE,
+ CEC_VENDOR_PHILIPS = 0x903E,
CEC_VENDOR_UNKNOWN = 0
} cec_vendor_id;
cec_logical_address device;
} cec_menu_language;
+typedef struct cec_osd_name
+{
+ char name[14];
+ cec_logical_address device;
+} cec_osd_name;
+
typedef struct cec_log_message
{
char message[1024];
OtherStatus = 0x1F
};
+public enum class CecUserControlCode
+{
+ Select = 0x00,
+ Up = 0x01,
+ Down = 0x02,
+ Left = 0x03,
+ Right = 0x04,
+ RightUp = 0x05,
+ RightDown = 0x06,
+ LeftUp = 0x07,
+ LeftDown = 0x08,
+ RootMenu = 0x09,
+ SetupMenu = 0x0A,
+ ContentsMenu = 0x0B,
+ FavoriteMenu = 0x0C,
+ Exit = 0x0D,
+ Number0 = 0x20,
+ Number1 = 0x21,
+ Number2 = 0x22,
+ Number3 = 0x23,
+ Number4 = 0x24,
+ Number5 = 0x25,
+ Number6 = 0x26,
+ Number7 = 0x27,
+ Number8 = 0x28,
+ Number9 = 0x29,
+ Dot = 0x2A,
+ Enter = 0x2B,
+ Clear = 0x2C,
+ NextFavorite = 0x2F,
+ ChannelUp = 0x30,
+ ChannelDown = 0x31,
+ PreviousChannel = 0x32,
+ SoundSelect = 0x33,
+ InputSelect = 0x34,
+ DisplayInformation = 0x35,
+ Help = 0x36,
+ PageUp = 0x37,
+ PageDown = 0x38,
+ Power = 0x40,
+ VolumeUp = 0x41,
+ VolumeDown = 0x42,
+ Mute = 0x43,
+ Play = 0x44,
+ Stop = 0x45,
+ Pause = 0x46,
+ Record = 0x47,
+ Rewind = 0x48,
+ FastForward = 0x49,
+ Eject = 0x4A,
+ Forward = 0x4B,
+ Backward = 0x4C,
+ StopRecord = 0x4D,
+ PauseRecord = 0x4E,
+ Angle = 0x50,
+ SubPicture = 0x51,
+ VideoOnDemand = 0x52,
+ ElectronicProgramGuide = 0x53,
+ TimerProgramming = 0x54,
+ InitialConfiguration = 0x55,
+ PlayFunction = 0x60,
+ PausePlayFunction = 0x61,
+ RecordFunction = 0x62,
+ PauseRecordFunction = 0x63,
+ StopFunction = 0x64,
+ MuteFunction = 0x65,
+ RestoreVolumeFunction = 0x66,
+ TuneFunction = 0x67,
+ SelectMediaFunction = 0x68,
+ SelectAVInputFunction = 0x69,
+ SelectAudioInputFunction = 0x6A,
+ PowerToggleFunction = 0x6B,
+ PowerOffFunction = 0x6C,
+ PowerOnFunction = 0x6D,
+ F1Blue = 0x71,
+ F2Red = 0X72,
+ F3Green = 0x73,
+ F4Yellow = 0x74,
+ F5 = 0x75,
+ Data = 0x76,
+ Max = 0x76,
+ Unknown
+};
+
public ref class CecAdapter
{
public:
property array<CecDeviceType> ^ Types;
};
+public ref class CecLogicalAddresses
+{
+public:
+ CecLogicalAddresses(void)
+ {
+ Addresses = gcnew array<CecLogicalAddress>(16);
+ for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ Addresses[iPtr] = CecLogicalAddress::Unregistered;
+ }
+
+ property array<CecLogicalAddress> ^ Addresses;
+};
+
public ref class CecDatapacket
{
public:
return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
}
+ CecLogicalAddresses ^ GetActiveDevices(void)
+ {
+ CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
+ unsigned int iDevices = 0;
+
+ cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
+
+ for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+ if (activeDevices[iPtr])
+ retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
+
+ return retVal;
+ }
+
+ bool IsActiveDevice(CecLogicalAddress logicalAddress)
+ {
+ return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
+ }
+
+ bool IsActiveDeviceType(CecDeviceType type)
+ {
+ return m_libCec->IsActiveDeviceType((cec_device_type)type);
+ }
+
+ bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
+ {
+ return m_libCec->SetHDMIPort((cec_logical_address)address, port);
+ }
+
+ uint8_t VolumeUp(bool wait)
+ {
+ return m_libCec->VolumeUp(wait);
+ }
+
+ uint8_t VolumeDown(bool wait)
+ {
+ return m_libCec->VolumeDown(wait);
+ }
+
+ uint8_t MuteAudio(bool wait)
+ {
+ return m_libCec->MuteAudio(wait);
+ }
+
+ bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
+ {
+ return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
+ }
+
+ bool SendKeyRelease(CecLogicalAddress destination, bool wait)
+ {
+ return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
+ }
+
+ String ^ GetOSDName(CecLogicalAddress logicalAddress)
+ {
+ cec_osd_name osd = m_libCec->GetOSDName((cec_logical_address) logicalAddress);
+ return gcnew String(osd.name);
+ }
+
private:
- ICECAdapter * m_libCec;
+ ICECAdapter *m_libCec;
};
void CCECAdapterMessage::push_escaped(uint8_t byte)
{
- if (byte >= MSGESC && byte != MSGSTART)
+ if (byte >= MSGESC)
{
push_back(MSGESC);
push_back(byte - ESCOFFSET);
{
CCECAdapterMessage *msg;
if (m_outBuffer.Pop(msg))
+ SendMessageToAdapter(msg);
+}
+
+void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg)
+{
+ CLockObject lock(&msg->mutex);
+ if (m_port->Write(msg) != (int32_t) msg->size())
{
- CLockObject lock(&msg->mutex);
- if (m_port->Write(msg) != (int32_t) msg->size())
- {
- CStdString strError;
- strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
- m_controller->AddLog(CEC_LOG_ERROR, strError);
- msg->state = ADAPTER_MESSAGE_STATE_ERROR;
- }
- else
- {
- m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
- CCondition::Sleep((uint32_t) msg->size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/ + 10);
- msg->state = ADAPTER_MESSAGE_STATE_SENT;
- }
- msg->condition.Signal();
+ CStdString strError;
+ strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
+ m_controller->AddLog(CEC_LOG_ERROR, strError);
+ msg->state = ADAPTER_MESSAGE_STATE_ERROR;
}
+ else
+ {
+ m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
+ CCondition::Sleep((uint32_t) msg->size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/);
+ msg->state = ADAPTER_MESSAGE_STATE_SENT;
+ }
+ msg->condition.Signal();
}
bool CAdapterCommunication::Write(CCECAdapterMessage *data)
}
else if (buf == MSGSTART) //we found a msgstart before msgend, this is not right, remove
{
- m_controller->AddLog(CEC_LOG_ERROR, "received MSGSTART before MSGEND");
+ m_controller->AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
msg.clear();
bGotStart = true;
}
output->push_escaped(MSGCODE_START_BOOTLOADER);
output->push_back(MSGEND);
- if ((bReturn = Write(output)) == false)
- m_controller->AddLog(CEC_LOG_ERROR, "could not start the bootloader");
-
+ SendMessageToAdapter(output);
+ bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
delete output;
return bReturn;
output->push_escaped(MSGCODE_PING);
output->push_back(MSGEND);
- if ((bReturn = Write(output)) == false)
- m_controller->AddLog(CEC_LOG_ERROR, "could not send ping command");
-
- // TODO check for pong
+ SendMessageToAdapter(output);
+ bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
delete output;
return bReturn;
bool StartBootloader(void);
private:
+ void SendMessageToAdapter(CCECAdapterMessage *msg);
void WriteNextCommand(void);
void AddData(uint8_t *data, uint8_t iLen);
bool ReadFromDevice(uint32_t iTimeout);
CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm, const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS*/) :
m_bStarted(false),
m_iHDMIPort(CEC_DEFAULT_HDMI_PORT),
+ m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
m_strDeviceName(strDeviceName),
m_communication(serComm),
m_controller(controller),
- m_bMonitor(false)
+ m_bMonitor(false),
+ m_busScan(NULL)
{
m_logicalAddresses.Clear();
m_logicalAddresses.Set(iLogicalAddress);
CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm, const char *strDeviceName, const cec_device_type_list &types) :
m_bStarted(false),
m_iHDMIPort(CEC_DEFAULT_HDMI_PORT),
+ m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE),
m_strDeviceName(strDeviceName),
m_types(types),
m_communication(serComm),
CCECProcessor::~CCECProcessor(void)
{
+ if (m_busScan)
+ {
+ m_busScan->StopThread();
+ delete m_busScan;
+ }
+
m_startCondition.Broadcast();
StopThread();
+
m_communication = NULL;
m_controller = NULL;
for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
m_controller->AddLog(CEC_LOG_ERROR, "could not create a processor thread");
return false;
}
- return true;
+
+ lock.Leave();
+ if (SetAckMask(m_logicalAddresses.AckMask()) &&
+ SetHDMIPort(m_iBaseDevice, m_iHDMIPort, true))
+ {
+ m_busScan = new CCECBusScan(this);
+ m_busScan->CreateThread(true);
+ return true;
+ }
}
else
m_controller->AddLog(CEC_LOG_ERROR, "could not create a processor thread");
cec_command command;
CCECAdapterMessage msg;
+ if (m_logicalAddresses.IsEmpty() && !FindLogicalAddresses())
{
- if (m_logicalAddresses.IsEmpty() && !FindLogicalAddresses())
- {
- CLockObject lock(&m_mutex);
- m_controller->AddLog(CEC_LOG_ERROR, "could not detect our logical addresses");
- m_startCondition.Signal();
- return NULL;
- }
-
- SetAckMask(m_logicalAddresses.AckMask());
-
- {
- CLockObject lock(&m_mutex);
- m_bStarted = true;
- lock.Leave();
-
- SetHDMIPort(m_iHDMIPort);
-
- lock.Lock();
- m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started");
- m_startCondition.Signal();
- }
+ CLockObject lock(&m_mutex);
+ m_controller->AddLog(CEC_LOG_ERROR, "could not detect our logical addresses");
+ m_startCondition.Signal();
+ return NULL;
+ }
+ else
+ {
+ CLockObject lock(&m_mutex);
+ m_bStarted = true;
+ m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started");
+ m_startCondition.Signal();
}
while (!IsStopped())
Sleep(5);
m_controller->CheckKeypressTimeout();
-
- for (unsigned int iDevicePtr = 0; iDevicePtr < 16; iDevicePtr++)
- {
- if (!m_logicalAddresses[iDevicePtr])
- m_busDevices[iDevicePtr]->PollVendorId();
- }
-
- Sleep(5);
}
return NULL;
return bReturn;
}
-bool CCECProcessor::SetHDMIPort(uint8_t iPort)
+bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce /* = false */)
{
bool bReturn(false);
CStdString strLog;
- strLog.Format("setting HDMI port to %d", iPort);
+ strLog.Format("setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice);
AddLog(CEC_LOG_DEBUG, strLog);
+ m_iBaseDevice = iBaseDevice;
m_iHDMIPort = iPort;
- if (!m_bStarted)
+ if (!m_bStarted && !bForce)
return true;
uint16_t iPhysicalAddress(0);
- int iPos = 3;
- while(!bReturn && iPos >= 0)
+ iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress();
+ uint16_t iPos = 0;
+ if (iPhysicalAddress == 0)
+ iPos = 0x1000;
+ else if (iPhysicalAddress % 0x1000 == 0)
+ iPos = 0x100;
+ else if (iPhysicalAddress % 0x100 == 0)
+ iPos = 0x10;
+ else if (iPhysicalAddress % 0x10 == 0)
+ iPos = 0x1;
+
+ while(!bReturn && iPos > 0)
{
- iPhysicalAddress += ((uint16_t)iPort * (0x1 << iPos*4));
+ iPhysicalAddress += (uint16_t)(iPort * iPos);
strLog.Format("checking physical address %4x", iPhysicalAddress);
AddLog(CEC_LOG_DEBUG, strLog);
if (CheckPhysicalAddress(iPhysicalAddress))
{
strLog.Format("physical address %4x is in use", iPhysicalAddress);
AddLog(CEC_LOG_DEBUG, strLog);
- iPos--;
+ iPos = (iPos == 1) ? 0 : iPos / 0x10;
}
else
{
bool CCECProcessor::CheckPhysicalAddress(uint16_t iPhysicalAddress)
{
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
{
if (m_busDevices[iPtr]->GetPhysicalAddress(false) == iPhysicalAddress)
return true;
return bReturn;
}
-bool CCECProcessor::SetInactiveView(void)
+bool CCECProcessor::TransmitInactiveSource(void)
{
if (!IsRunning())
return false;
if (!m_logicalAddresses.IsEmpty() && m_busDevices[m_logicalAddresses.primary])
- return m_busDevices[m_logicalAddresses.primary]->TransmitInactiveView();
+ return m_busDevices[m_logicalAddresses.primary]->TransmitInactiveSource();
return false;
}
bool CCECProcessor::PollDevice(cec_logical_address iAddress)
{
if (iAddress != CECDEVICE_UNKNOWN && m_busDevices[iAddress])
- return m_busDevices[m_logicalAddresses.primary]->TransmitPoll(iAddress);
+ {
+ return m_logicalAddresses.primary == CECDEVICE_UNKNOWN ?
+ m_busDevices[iAddress]->TransmitPoll(iAddress) :
+ m_busDevices[m_logicalAddresses.primary]->TransmitPoll(iAddress);
+ }
return false;
}
-uint8_t CCECProcessor::VolumeUp(void)
+uint8_t CCECProcessor::VolumeUp(bool bWait /* = true */)
{
uint8_t status = 0;
if (IsActiveDevice(CECDEVICE_AUDIOSYSTEM))
- status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeUp();
+ status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeUp(bWait);
return status;
}
-uint8_t CCECProcessor::VolumeDown(void)
+uint8_t CCECProcessor::VolumeDown(bool bWait /* = true */)
{
uint8_t status = 0;
if (IsActiveDevice(CECDEVICE_AUDIOSYSTEM))
- status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeDown();
+ status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeDown(bWait);
return status;
}
-uint8_t CCECProcessor::MuteAudio(void)
+uint8_t CCECProcessor::MuteAudio(bool bWait /* = true */)
{
uint8_t status = 0;
if (IsActiveDevice(CECDEVICE_AUDIOSYSTEM))
- status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->MuteAudio();
+ status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->MuteAudio(bWait);
return status;
}
return m_busDevices[iAddress]->GetCecVersion();
}
+cec_osd_name CCECProcessor::GetDeviceOSDName(cec_logical_address iAddress)
+{
+ CStdString strOSDName = m_busDevices[iAddress]->GetOSDName();
+ cec_osd_name retVal;
+
+ snprintf(retVal.name, sizeof(retVal.name), "%s", strOSDName.c_str());
+ retVal.device = iAddress;
+
+ return retVal;
+}
+
bool CCECProcessor::GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language)
{
if (m_busDevices[iAddress])
cec_logical_addresses CCECProcessor::GetActiveDevices(void)
{
cec_logical_addresses addresses;
+ addresses.Clear();
for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
{
if (m_busDevices[iPtr]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
return bReturn;
}
+
+bool CCECProcessor::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = false */)
+{
+ return m_busDevices[iDestination]->SendKeypress(key, bWait);
+}
+
+bool CCECProcessor::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = false */)
+{
+ return m_busDevices[iDestination]->SendKeyRelease(bWait);
+}
+
+const char *CCECProcessor::ToString(const cec_menu_state state)
+{
+ switch (state)
+ {
+ case CEC_MENU_STATE_ACTIVATED:
+ return "activated";
+ case CEC_MENU_STATE_DEACTIVATED:
+ return "deactivated";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_version version)
+{
+ switch (version)
+ {
+ case CEC_VERSION_1_2:
+ return "1.2";
+ case CEC_VERSION_1_2A:
+ return "1.2a";
+ case CEC_VERSION_1_3:
+ return "1.3";
+ case CEC_VERSION_1_3A:
+ return "1.3a";
+ case CEC_VERSION_1_4:
+ return "1.4";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_power_status status)
+{
+ switch (status)
+ {
+ case CEC_POWER_STATUS_ON:
+ return "on";
+ case CEC_POWER_STATUS_STANDBY:
+ return "standby";
+ case CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY:
+ return "in transition from on to standby";
+ case CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON:
+ return "in transition from standby to on";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_logical_address address)
+{
+ switch(address)
+ {
+ case CECDEVICE_AUDIOSYSTEM:
+ return "Audio";
+ case CECDEVICE_BROADCAST:
+ return "Broadcast";
+ case CECDEVICE_FREEUSE:
+ return "Free use";
+ case CECDEVICE_PLAYBACKDEVICE1:
+ return "Playback 1";
+ case CECDEVICE_PLAYBACKDEVICE2:
+ return "Playback 2";
+ case CECDEVICE_PLAYBACKDEVICE3:
+ return "Playback 3";
+ case CECDEVICE_RECORDINGDEVICE1:
+ return "Recorder 1";
+ case CECDEVICE_RECORDINGDEVICE2:
+ return "Recorder 2";
+ case CECDEVICE_RECORDINGDEVICE3:
+ return "Recorder 3";
+ case CECDEVICE_RESERVED1:
+ return "Reserved 1";
+ case CECDEVICE_RESERVED2:
+ return "Reserved 2";
+ case CECDEVICE_TUNER1:
+ return "Tuner 1";
+ case CECDEVICE_TUNER2:
+ return "Tuner 2";
+ case CECDEVICE_TUNER3:
+ return "Tuner 3";
+ case CECDEVICE_TUNER4:
+ return "Tuner 4";
+ case CECDEVICE_TV:
+ return "TV";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_deck_control_mode mode)
+{
+ switch (mode)
+ {
+ case CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND:
+ return "skip forward wind";
+ case CEC_DECK_CONTROL_MODE_EJECT:
+ return "eject";
+ case CEC_DECK_CONTROL_MODE_SKIP_REVERSE_REWIND:
+ return "reverse rewind";
+ case CEC_DECK_CONTROL_MODE_STOP:
+ return "stop";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_deck_info status)
+{
+ switch (status)
+ {
+ case CEC_DECK_INFO_PLAY:
+ return "play";
+ case CEC_DECK_INFO_RECORD:
+ return "record";
+ case CEC_DECK_INFO_PLAY_REVERSE:
+ return "play reverse";
+ case CEC_DECK_INFO_STILL:
+ return "still";
+ case CEC_DECK_INFO_SLOW:
+ return "slow";
+ case CEC_DECK_INFO_SLOW_REVERSE:
+ return "slow reverse";
+ case CEC_DECK_INFO_FAST_FORWARD:
+ return "fast forward";
+ case CEC_DECK_INFO_FAST_REVERSE:
+ return "fast reverse";
+ case CEC_DECK_INFO_NO_MEDIA:
+ return "no media";
+ case CEC_DECK_INFO_STOP:
+ return "stop";
+ case CEC_DECK_INFO_SKIP_FORWARD_WIND:
+ return "info skip forward wind";
+ case CEC_DECK_INFO_SKIP_REVERSE_REWIND:
+ return "info skip reverse rewind";
+ case CEC_DECK_INFO_INDEX_SEARCH_FORWARD:
+ return "info index search forward";
+ case CEC_DECK_INFO_INDEX_SEARCH_REVERSE:
+ return "info index search reverse";
+ case CEC_DECK_INFO_OTHER_STATUS:
+ return "other";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_opcode opcode)
+{
+ switch (opcode)
+ {
+ case CEC_OPCODE_ACTIVE_SOURCE:
+ return "active source";
+ case CEC_OPCODE_IMAGE_VIEW_ON:
+ return "image view on";
+ case CEC_OPCODE_TEXT_VIEW_ON:
+ return "text view on";
+ case CEC_OPCODE_INACTIVE_SOURCE:
+ return "inactive source";
+ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+ return "request active source";
+ case CEC_OPCODE_ROUTING_CHANGE:
+ return "routing change";
+ case CEC_OPCODE_ROUTING_INFORMATION:
+ return "routing information";
+ case CEC_OPCODE_SET_STREAM_PATH:
+ return "set stream path";
+ case CEC_OPCODE_STANDBY:
+ return "standby";
+ case CEC_OPCODE_RECORD_OFF:
+ return "record off";
+ case CEC_OPCODE_RECORD_ON:
+ return "record on";
+ case CEC_OPCODE_RECORD_STATUS:
+ return "record status";
+ case CEC_OPCODE_RECORD_TV_SCREEN:
+ return "record tv screen";
+ case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
+ return "clear analogue timer";
+ case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
+ return "clear digital timer";
+ case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
+ return "clear external timer";
+ case CEC_OPCODE_SET_ANALOGUE_TIMER:
+ return "set analogue timer";
+ case CEC_OPCODE_SET_DIGITAL_TIMER:
+ return "set digital timer";
+ case CEC_OPCODE_SET_EXTERNAL_TIMER:
+ return "set external timer";
+ case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
+ return "set timer program title";
+ case CEC_OPCODE_TIMER_CLEARED_STATUS:
+ return "timer cleared status";
+ case CEC_OPCODE_TIMER_STATUS:
+ return "timer status";
+ case CEC_OPCODE_CEC_VERSION:
+ return "cec version";
+ case CEC_OPCODE_GET_CEC_VERSION:
+ return "get cec version";
+ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+ return "give physical address";
+ case CEC_OPCODE_GET_MENU_LANGUAGE:
+ return "get menu language";
+ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
+ return "report physical address";
+ case CEC_OPCODE_SET_MENU_LANGUAGE:
+ return "set menu language";
+ case CEC_OPCODE_DECK_CONTROL:
+ return "deck control";
+ case CEC_OPCODE_DECK_STATUS:
+ return "deck status";
+ case CEC_OPCODE_GIVE_DECK_STATUS:
+ return "give deck status";
+ case CEC_OPCODE_PLAY:
+ return "play";
+ case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
+ return "give tuner status";
+ case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
+ return "select analogue service";
+ case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
+ return "set digital service";
+ case CEC_OPCODE_TUNER_DEVICE_STATUS:
+ return "tuner device status";
+ case CEC_OPCODE_TUNER_STEP_DECREMENT:
+ return "tuner step decrement";
+ case CEC_OPCODE_TUNER_STEP_INCREMENT:
+ return "tuner step increment";
+ case CEC_OPCODE_DEVICE_VENDOR_ID:
+ return "device vendor id";
+ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
+ return "give device vendor id";
+ case CEC_OPCODE_VENDOR_COMMAND:
+ return "vendor command";
+ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
+ return "vendor command with id";
+ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
+ return "vendor remote button down";
+ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
+ return "vendor remote button up";
+ case CEC_OPCODE_SET_OSD_STRING:
+ return "set osd string";
+ case CEC_OPCODE_GIVE_OSD_NAME:
+ return "give osd name";
+ case CEC_OPCODE_SET_OSD_NAME:
+ return "set osd name";
+ case CEC_OPCODE_MENU_REQUEST:
+ return "menu request";
+ case CEC_OPCODE_MENU_STATUS:
+ return "menu status";
+ case CEC_OPCODE_USER_CONTROL_PRESSED:
+ return "user control pressed";
+ case CEC_OPCODE_USER_CONTROL_RELEASE:
+ return "user control release";
+ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
+ return "give device power status";
+ case CEC_OPCODE_REPORT_POWER_STATUS:
+ return "report power status";
+ case CEC_OPCODE_FEATURE_ABORT:
+ return "feature abort";
+ case CEC_OPCODE_ABORT:
+ return "abort";
+ case CEC_OPCODE_GIVE_AUDIO_STATUS:
+ return "give audio status";
+ case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
+ return "give audio mode status";
+ case CEC_OPCODE_REPORT_AUDIO_STATUS:
+ return "report audio status";
+ case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
+ return "set system audio mode";
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
+ return "system audio mode request";
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
+ return "system audio mode status";
+ case CEC_OPCODE_SET_AUDIO_RATE:
+ return "set audio rate";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_system_audio_status mode)
+{
+ switch(mode)
+ {
+ case CEC_SYSTEM_AUDIO_STATUS_ON:
+ return "on";
+ case CEC_SYSTEM_AUDIO_STATUS_OFF:
+ return "off";
+ default:
+ return "unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_audio_status status)
+{
+ // TODO this is a mask
+ return "TODO";
+}
+
+const char *CCECProcessor::ToString(const cec_vendor_id vendor)
+{
+ switch (vendor)
+ {
+ case CEC_VENDOR_SAMSUNG:
+ return "Samsung";
+ case CEC_VENDOR_LG:
+ return "LG";
+ case CEC_VENDOR_PANASONIC:
+ return "Panasonic";
+ case CEC_VENDOR_PIONEER:
+ return "Pioneer";
+ case CEC_VENDOR_ONKYO:
+ return "Onkyo";
+ case CEC_VENDOR_YAMAHA:
+ return "Yamaha";
+ case CEC_VENDOR_PHILIPS:
+ return "Philips";
+ default:
+ return "Unknown";
+ }
+}
+
+void *CCECBusScan::Process(void)
+{
+ CCECBusDevice *device(NULL);
+ while (!IsStopped())
+ {
+ for (unsigned int iPtr = 0; iPtr < 15 && !IsStopped(); iPtr++)
+ {
+ device = m_processor->m_busDevices[iPtr];
+ if (device && device->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ {
+ if (!IsStopped())
+ device->GetPhysicalAddress(false);
+ Sleep(5);
+
+ if (!IsStopped())
+ device->GetCecVersion();
+ Sleep(5);
+
+ if (!IsStopped())
+ device->GetVendorId();
+ Sleep(5);
+ }
+ }
+ Sleep(1000);
+ }
+ return NULL;
+}
virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress);
virtual bool GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language);
virtual const std::string & GetDeviceName(void) { return m_strDeviceName; }
+ virtual cec_osd_name GetDeviceOSDName(cec_logical_address iAddress);
virtual uint64_t GetDeviceVendorId(cec_logical_address iAddress);
virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress);
virtual cec_logical_address GetLogicalAddress(void) const { return m_logicalAddresses.primary; }
virtual bool SetActiveSource(cec_logical_address iAddress);
virtual bool SetDeckControlMode(cec_deck_control_mode mode, bool bSendUpdate = true);
virtual bool SetDeckInfo(cec_deck_info info, bool bSendUpdate = true);
- virtual bool SetHDMIPort(uint8_t iPort);
- virtual bool SetInactiveView(void);
+ virtual bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce = false);
+ virtual bool TransmitInactiveSource(void);
virtual bool SetLogicalAddress(cec_logical_address iLogicalAddress);
virtual bool SetMenuState(cec_menu_state state, bool bSendUpdate = true);
virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress);
virtual bool SetStreamPath(uint16_t iStreamPath);
virtual bool SwitchMonitoring(bool bEnable);
virtual bool PollDevice(cec_logical_address iAddress);
- virtual uint8_t VolumeUp(void);
- virtual uint8_t VolumeDown(void);
- virtual uint8_t MuteAudio(void);
+ virtual uint8_t VolumeUp(bool bWait = true);
+ virtual uint8_t VolumeDown(bool bWait = true);
+ virtual uint8_t MuteAudio(bool bWait = true);
+ virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = false);
+ virtual bool SendKeyRelease(cec_logical_address iDestination, bool bWait = false);
+ virtual bool EnablePhysicalAddressDetection(void) { return false; };
+
+ const char *ToString(const cec_menu_state state);
+ const char *ToString(const cec_version version);
+ const char *ToString(const cec_power_status status);
+ const char *ToString(const cec_logical_address address);
+ const char *ToString(const cec_deck_control_mode mode);
+ const char *ToString(const cec_deck_info status);
+ const char *ToString(const cec_opcode opcode);
+ const char *ToString(const cec_system_audio_status mode);
+ const char *ToString(const cec_audio_status status);
+ const char *ToString(const cec_vendor_id vendor);
virtual bool Transmit(const cec_command &data);
virtual bool Transmit(CCECAdapterMessage *output);
CCECBusDevice *m_busDevices[16];
private:
+ void ScanCECBus(void);
bool CheckPhysicalAddress(uint16_t iPhysicalAddress);
bool TryLogicalAddress(cec_logical_address address);
bool FindLogicalAddressRecordingDevice(void);
bool m_bStarted;
uint8_t m_iHDMIPort;
+ cec_logical_address m_iBaseDevice;
cec_command m_currentframe;
cec_logical_addresses m_logicalAddresses;
std::string m_strDeviceName;
CLibCEC* m_controller;
bool m_bMonitor;
CecBuffer<cec_command> m_commandBuffer;
+ cec_keypress m_previousKey;
+ CThread * m_busScan;
+ };
+
+ class CCECBusScan : public CThread
+ {
+ public:
+ CCECBusScan(CCECProcessor *processor) { m_processor = processor; }
+ virtual ~CCECBusScan(void) {}
+ virtual void *Process(void);
+
+ private:
+ CCECProcessor *m_processor;
};
};
return m_cec ? m_cec->SetPhysicalAddress(iPhysicalAddress) : false;
}
-bool CLibCEC::SetHDMIPort(uint8_t iPort /* = CEC_DEFAULT_HDMI_PORT */)
+bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort /* = CEC_DEFAULT_HDMI_PORT */)
{
- return m_cec ? m_cec->SetHDMIPort(iPort) : false;
+ return m_cec ? m_cec->SetHDMIPort(iBaseDevice, iPort) : false;
+}
+
+bool CLibCEC::EnablePhysicalAddressDetection(void)
+{
+ return m_cec ? m_cec->EnablePhysicalAddressDetection() : false;
}
bool CLibCEC::PowerOnDevices(cec_logical_address address /* = CECDEVICE_TV */)
bool CLibCEC::SetInactiveView(void)
{
- return m_cec ? m_cec->SetInactiveView() : false;
+ return m_cec ? m_cec->TransmitInactiveSource() : false;
}
bool CLibCEC::SetMenuState(cec_menu_state state, bool bSendUpdate /* = true */)
cec_logical_addresses CLibCEC::GetActiveDevices(void)
{
cec_logical_addresses addresses;
+ addresses.Clear();
if (m_cec)
addresses = m_cec->GetActiveDevices();
return addresses;
return false;
}
-uint8_t CLibCEC::VolumeUp(void)
+uint8_t CLibCEC::VolumeUp(bool bWait /* = true */)
{
if (m_cec)
- return m_cec->VolumeUp();
+ return m_cec->VolumeUp(bWait);
return 0;
}
-uint8_t CLibCEC::VolumeDown(void)
+uint8_t CLibCEC::VolumeDown(bool bWait /* = true */)
{
if (m_cec)
- return m_cec->VolumeDown();
+ return m_cec->VolumeDown(bWait);
return 0;
}
-uint8_t CLibCEC::MuteAudio(void)
+uint8_t CLibCEC::MuteAudio(bool bWait /* = true */)
{
if (m_cec)
- return m_cec->MuteAudio();
+ return m_cec->MuteAudio(bWait);
return 0;
}
+bool CLibCEC::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = false */)
+{
+ if (m_cec)
+ return m_cec->SendKeypress(iDestination, key, bWait);
+ return false;
+}
+
+bool CLibCEC::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = false */)
+{
+ if (m_cec)
+ return m_cec->SendKeyRelease(iDestination, bWait);
+ return false;
+}
+
+cec_osd_name CLibCEC::GetOSDName(cec_logical_address iAddress)
+{
+ cec_osd_name retVal;
+ retVal.device = iAddress;
+ retVal.name[0] = 0;
+
+ if (m_cec)
+ retVal = m_cec->GetDeviceOSDName(iAddress);
+
+ return retVal;
+}
+
void CLibCEC::AddLog(cec_log_level level, const string &strMessage)
{
if (m_cec)
if (lib)
delete lib;
}
+
+const char *CLibCEC::ToString(const cec_menu_state state)
+{
+ return m_cec->ToString(state);
+}
+
+const char *CLibCEC::ToString(const cec_version version)
+{
+ return m_cec->ToString(version);
+}
+
+const char *CLibCEC::ToString(const cec_power_status status)
+{
+ return m_cec->ToString(status);
+}
+
+const char *CLibCEC::ToString(const cec_logical_address address)
+{
+ return m_cec->ToString(address);
+}
+
+const char *CLibCEC::ToString(const cec_deck_control_mode mode)
+{
+ return m_cec->ToString(mode);
+}
+
+const char *CLibCEC::ToString(const cec_deck_info status)
+{
+ return m_cec->ToString(status);
+}
+
+const char *CLibCEC::ToString(const cec_opcode opcode)
+{
+ return m_cec->ToString(opcode);
+}
+
+const char *CLibCEC::ToString(const cec_system_audio_status mode)
+{
+ return m_cec->ToString(mode);
+}
+
+const char *CLibCEC::ToString(const cec_audio_status status)
+{
+ return m_cec->ToString(status);
+}
+
+const char *CLibCEC::ToString(const cec_vendor_id vendor)
+{
+ return m_cec->ToString(vendor);
+}
virtual cec_logical_addresses GetActiveDevices(void);
virtual bool IsActiveDevice(cec_logical_address iAddress);
virtual bool IsActiveDeviceType(cec_device_type type);
- virtual bool SetHDMIPort(uint8_t iPort = CEC_DEFAULT_HDMI_PORT);
- virtual uint8_t VolumeUp(void);
- virtual uint8_t VolumeDown(void);
- virtual uint8_t MuteAudio(void);
+ virtual bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort = CEC_DEFAULT_HDMI_PORT);
+ virtual uint8_t VolumeUp(bool bWait = true);
+ virtual uint8_t VolumeDown(bool bWait = true);
+ virtual uint8_t MuteAudio(bool bWait = true);
+ virtual bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = false);
+ virtual bool SendKeyRelease(cec_logical_address iDestination, bool bWait = false);
+ virtual cec_osd_name GetOSDName(cec_logical_address iAddress);
+ virtual bool EnablePhysicalAddressDetection(void);
+
+ const char *ToString(const cec_menu_state state);
+ const char *ToString(const cec_version version);
+ const char *ToString(const cec_power_status status);
+ const char *ToString(const cec_logical_address address);
+ const char *ToString(const cec_deck_control_mode mode);
+ const char *ToString(const cec_deck_info status);
+ const char *ToString(const cec_opcode opcode);
+ const char *ToString(const cec_system_audio_status mode);
+ const char *ToString(const cec_audio_status status);
+ const char *ToString(const cec_vendor_id vendor);
//@}
virtual void AddLog(cec_log_level level, const std::string &strMessage);
cec_logical_addresses cec_get_active_devices(void)
{
cec_logical_addresses addresses;
+ addresses.Clear();
if (cec_parser)
addresses = cec_parser->GetActiveDevices();
return addresses;
return -1;
}
-int cec_set_hdmi_port(uint8_t iPort)
+int cec_set_hdmi_port(cec_logical_address iBaseDevice, uint8_t iPort)
{
if (cec_parser)
- return cec_parser->SetHDMIPort(iPort) ? 1 : 0;
+ return cec_parser->SetHDMIPort(iBaseDevice, iPort) ? 1 : 0;
return -1;
}
-int cec_volume_up(void)
+int cec_volume_up(int bWait)
{
if (cec_parser)
- return cec_parser->VolumeUp();
+ return cec_parser->VolumeUp(bWait == 1);
return -1;
}
-int cec_volume_down(void)
+int cec_volume_down(int bWait)
{
if (cec_parser)
- return cec_parser->VolumeDown();
+ return cec_parser->VolumeDown(bWait == 1);
return -1;
}
-int cec_mute_audio(void)
+int cec_mute_audio(int bWait)
{
if (cec_parser)
- return cec_parser->MuteAudio();
+ return cec_parser->MuteAudio(bWait == 1);
return -1;
}
+int cec_send_keypress(cec_logical_address iDestination, cec_user_control_code key, int bWait)
+{
+ if (cec_parser)
+ return cec_parser->SendKeypress(iDestination, key, bWait == 1) ? 1 : 0;
+ return -1;
+}
+
+int cec_send_key_release(cec_logical_address iDestination, int bWait)
+{
+ if (cec_parser)
+ return cec_parser->SendKeyRelease(iDestination, bWait == 1) ? 1 : 0;
+ return -1;
+}
+
+cec_osd_name cec_get_osd_name(cec_logical_address iAddress)
+{
+ cec_osd_name retVal;
+ retVal.device = iAddress;
+ retVal.name[0] = 0;
+
+ if (cec_parser)
+ retVal = cec_parser->GetOSDName(iAddress);
+
+ return retVal;
+}
+
+int cec_enable_physical_address_detection(void)
+{
+ return cec_parser ? (cec_parser->EnablePhysicalAddressDetection() ? 1 : 0) : -1;
+}
+
//@}
using namespace CEC;
+#define ToString(p) m_processor->ToString(p)
+
CCECAudioSystem::CCECAudioSystem(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress /* = 0 */) :
CCECBusDevice(processor, address, iPhysicalAddress),
m_systemAudioStatus(CEC_SYSTEM_AUDIO_STATUS_ON),
bool CCECAudioSystem::SetAudioStatus(uint8_t status)
{
+ CLockObject lock(&m_writeMutex);
if (m_audioStatus != status)
{
CStdString strLog;
return false;
}
-bool CCECAudioSystem::SetSystemAudioMode(const cec_system_audio_status mode)
+bool CCECAudioSystem::SetSystemAudioModeStatus(const cec_system_audio_status mode)
{
+ CLockObject lock(&m_writeMutex);
if (m_systemAudioStatus != mode)
{
CStdString strLog;
- strLog.Format(">> %s (%X): system audio mode changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_systemAudioStatus), CCECCommandHandler::ToString(mode));
+ strLog.Format(">> %s (%X): system audio mode status changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_systemAudioStatus), ToString(mode));
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_systemAudioStatus = mode;
return false;
}
-bool CCECAudioSystem::SetSystemAudioMode(const cec_command &command)
-{
- SetSystemAudioMode((command.parameters.size == 0) ?
- CEC_SYSTEM_AUDIO_STATUS_OFF :
- CEC_SYSTEM_AUDIO_STATUS_ON);
-
- return TransmitAudioStatus(command.initiator);
-}
-
bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest)
{
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, m_audioStatus);
AddLog(CEC_LOG_NOTICE, strLog);
return m_processor->Transmit(command);
}
+bool CCECAudioSystem::TransmitSetSystemAudioMode(cec_logical_address dest)
+{
+ CLockObject lock(&m_writeMutex);
+ CStdString strLog;
+ strLog.Format("<< %x -> %x: set system audio mode '%2x'", m_iLogicalAddress, dest, m_audioStatus);
+ AddLog(CEC_LOG_NOTICE, strLog);
+
+ cec_command command;
+ cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_SYSTEM_AUDIO_MODE);
+ command.parameters.PushBack((uint8_t)m_systemAudioStatus);
+
+ return m_processor->Transmit(command);
+}
+
bool CCECAudioSystem::TransmitSystemAudioModeStatus(cec_logical_address dest)
{
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
- strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, CCECCommandHandler::ToString(m_systemAudioStatus));
+ strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, ToString(m_systemAudioStatus));
AddLog(CEC_LOG_NOTICE, strLog);
cec_command command;
return m_processor->Transmit(command);
}
-uint8_t CCECAudioSystem::VolumeUp(void)
+uint8_t CCECAudioSystem::VolumeUp(bool bWait /* = true */)
{
- return SendKey(CEC_USER_CONTROL_CODE_VOLUME_UP);
-}
+ if (SendKeypress(CEC_USER_CONTROL_CODE_VOLUME_UP))
+ SendKeyRelease(bWait);
-uint8_t CCECAudioSystem::VolumeDown(void)
-{
- return SendKey(CEC_USER_CONTROL_CODE_VOLUME_DOWN);
+ CLockObject lock(&m_mutex);
+ return m_audioStatus;
}
-uint8_t CCECAudioSystem::MuteAudio(void)
+uint8_t CCECAudioSystem::VolumeDown(bool bWait /* = true */)
{
- return SendKey(CEC_USER_CONTROL_CODE_MUTE);
+ if (SendKeypress(CEC_USER_CONTROL_CODE_VOLUME_DOWN))
+ SendKeyRelease(bWait);
+
+ CLockObject lock(&m_mutex);
+ return m_audioStatus;
}
-uint8_t CCECAudioSystem::SendKey(cec_user_control_code key)
+uint8_t CCECAudioSystem::MuteAudio(bool bWait /* = true */)
{
- {
- CLockObject lock(&m_transmitMutex);
- cec_command command;
- cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_PRESSED);
- command.parameters.PushBack(key);
- m_processor->Transmit(command);
-
- cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_RELEASE);
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_transmitMutex, 1000);
- }
+ if (SendKeypress(CEC_USER_CONTROL_CODE_MUTE))
+ SendKeyRelease(bWait);
CLockObject lock(&m_mutex);
return m_audioStatus;
virtual ~CCECAudioSystem(void) {};
virtual bool SetAudioStatus(uint8_t status);
- virtual bool SetSystemAudioMode(const cec_system_audio_status mode);
- virtual bool SetSystemAudioMode(const cec_command &command);
+ virtual bool SetSystemAudioModeStatus(const cec_system_audio_status mode);
virtual bool TransmitAudioStatus(cec_logical_address dest);
+ virtual bool TransmitSetSystemAudioMode(cec_logical_address dest);
virtual bool TransmitSystemAudioModeStatus(cec_logical_address dest);
- virtual uint8_t VolumeUp(void);
- virtual uint8_t VolumeDown(void);
- virtual uint8_t MuteAudio(void);
- virtual uint8_t SendKey(cec_user_control_code key);
+ virtual uint8_t VolumeUp(bool bWait = true);
+ virtual uint8_t VolumeDown(bool bWait = true);
+ virtual uint8_t MuteAudio(bool bWait = true);
virtual bool TransmitActiveSource(void) { return false; }
using namespace CEC;
-#define ToString(p) CCECCommandHandler::ToString(p)
+#define ToString(p) m_processor->ToString(p)
CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress) :
m_type(CEC_DEVICE_TYPE_RESERVED),
return true;
}
-void CCECBusDevice::PollVendorId(void)
-{
- CLockObject lock(&m_transmitMutex);
- if (m_iLastActive > 0 && m_iLogicalAddress != CECDEVICE_BROADCAST &&
- m_vendor == CEC_VENDOR_UNKNOWN &&
- GetTimeMs() - m_iLastCommandSent > 5000 &&
- !m_processor->IsMonitoring())
- {
- CStdString strLog;
- strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_NOTICE, strLog);
- m_iLastCommandSent = GetTimeMs();
-
- cec_command command;
- cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
- if (m_processor->Transmit(command))
- m_condition.Wait(&m_transmitMutex, 1000);
- }
-}
-
bool CCECBusDevice::PowerOn(void)
{
- CStdString strLog;
- strLog.Format("<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
- AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ CStdString strLog;
+ strLog.Format("<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_DEBUG, strLog.c_str());
- cec_command command;
- cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_IMAGE_VIEW_ON);
- if (m_processor->Transmit(command))
- {
- GetPowerStatus();
- return true;
+ cec_command command;
+ cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_IMAGE_VIEW_ON);
+ if (m_processor->Transmit(command))
+ {
+ {
+ CLockObject lock(&m_mutex);
+ m_powerStatus = CEC_POWER_STATUS_UNKNOWN;
+ }
+ cec_power_status status = GetPowerStatus();
+ if (status == CEC_POWER_STATUS_STANDBY || status == CEC_POWER_STATUS_UNKNOWN)
+ {
+ SendKeypress(CEC_USER_CONTROL_CODE_POWER, true);
+ return SendKeyRelease(false);
+ }
+ return true;
}
return false;
cec_version CCECBusDevice::GetCecVersion(void)
{
CLockObject lock(&m_mutex);
- if (m_cecVersion == CEC_VERSION_UNKNOWN)
- {
- lock.Leave();
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ m_cecVersion == CEC_VERSION_UNKNOWN)
RequestCecVersion();
- lock.Lock();
- }
return m_cecVersion;
}
return bReturn;
}
+uint64_t CCECBusDevice::GetLastCommandSent(void) const
+{
+ return GetTimeMs() - m_iLastCommandSent;
+}
+
const char* CCECBusDevice::GetLogicalAddressName(void) const
{
return ToString(m_iLogicalAddress);
cec_menu_language &CCECBusDevice::GetMenuLanguage(void)
{
CLockObject lock(&m_mutex);
- if (!strcmp(m_menuLanguage.language, "???"))
- {
- lock.Leave();
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ !strcmp(m_menuLanguage.language, "???"))
RequestMenuLanguage();
- lock.Lock();
- }
+
return m_menuLanguage;
}
return m_processor->GetPhysicalAddress();
}
-uint16_t CCECBusDevice::GetPhysicalAddress(bool bRefresh /* = true */)
+CStdString CCECBusDevice::GetOSDName(void)
+{
+ CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ m_strDeviceName.Equals(ToString(m_iLogicalAddress)))
+ RequestOSDName();
+
+ return m_strDeviceName;
+}
+
+bool CCECBusDevice::RequestOSDName(void)
{
- if (GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bool bReturn(false);
+ if (!MyLogicalAddressContains(m_iLogicalAddress))
{
- CLockObject lock(&m_mutex);
- if (m_iPhysicalAddress == 0xFFFF || bRefresh)
- {
- lock.Leave();
- RequestPhysicalAddress();
- lock.Lock();
- }
+ CStdString strLog;
+ strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
+ AddLog(CEC_LOG_NOTICE, strLog);
+ cec_command command;
+ cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_OSD_NAME);
+ CLockObject lock(&m_transmitMutex);
+ if (m_processor->Transmit(command))
+ bReturn = m_condition.Wait(&m_transmitMutex, 1000);
}
+ return bReturn;
+}
+uint16_t CCECBusDevice::GetPhysicalAddress(bool bRefresh /* = true */)
+{
CLockObject lock(&m_mutex);
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ (m_iPhysicalAddress == 0xFFFF || bRefresh))
+ {
+ if (!RequestPhysicalAddress())
+ AddLog(CEC_LOG_ERROR, "failed to request the physical address");
+ }
+
return m_iPhysicalAddress;
}
cec_power_status CCECBusDevice::GetPowerStatus(void)
{
CLockObject lock(&m_mutex);
- if (m_powerStatus == CEC_POWER_STATUS_UNKNOWN)
- {
- lock.Leave();
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ m_powerStatus == CEC_POWER_STATUS_UNKNOWN)
RequestPowerStatus();
- lock.Lock();
- }
+
return m_powerStatus;
}
cec_vendor_id CCECBusDevice::GetVendorId(void)
{
CLockObject lock(&m_mutex);
- if (m_vendor == CEC_VENDOR_UNKNOWN)
- {
- lock.Leave();
+ if (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
+ m_vendor == CEC_VENDOR_UNKNOWN)
RequestVendorId();
- lock.Lock();
- }
+
return m_vendor;
}
return m_processor->HasLogicalAddress(address);
}
-cec_bus_device_status CCECBusDevice::GetStatus(void)
+bool CCECBusDevice::NeedsPoll(void)
{
- CLockObject lock(&m_mutex);
- if (m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN)
+ bool bSendPoll(false);
+ switch (m_iLogicalAddress)
{
- if (m_processor->PollDevice(m_iLogicalAddress))
- m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
- else
- m_deviceStatus = CEC_DEVICE_STATUS_NOT_PRESENT;
+ case CECDEVICE_PLAYBACKDEVICE3:
+ if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_PLAYBACKDEVICE2:
+ if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_RECORDINGDEVICE3:
+ if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_RECORDINGDEVICE2:
+ if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_TUNER4:
+ if (m_processor->m_busDevices[CECDEVICE_TUNER3]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_TUNER3:
+ if (m_processor->m_busDevices[CECDEVICE_TUNER2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_TUNER2:
+ if (m_processor->m_busDevices[CECDEVICE_TUNER1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
+ bSendPoll = true;
+ break;
+ case CECDEVICE_AUDIOSYSTEM:
+ case CECDEVICE_PLAYBACKDEVICE1:
+ case CECDEVICE_RECORDINGDEVICE1:
+ case CECDEVICE_TUNER1:
+ case CECDEVICE_TV:
+ bSendPoll = true;
+ break;
+ default:
+ break;
+ }
+
+ return bSendPoll;
+}
+
+cec_bus_device_status CCECBusDevice::GetStatus(bool bForcePoll /* = false */)
+{
+ CLockObject lock(&m_writeMutex);
+ if (m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN || bForcePoll)
+ {
+ lock.Leave();
+ bool bPollAcked(false);
+ if (bForcePoll || NeedsPoll())
+ bPollAcked = m_processor->PollDevice(m_iLogicalAddress);
+
+ lock.Lock();
+ m_deviceStatus = bPollAcked ? CEC_DEVICE_STATUS_PRESENT : CEC_DEVICE_STATUS_NOT_PRESENT;
}
return m_deviceStatus;
void CCECBusDevice::SetMenuLanguage(const cec_menu_language &language)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (language.device == m_iLogicalAddress)
{
CStdString strLog;
void CCECBusDevice::SetOSDName(CStdString strName)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (m_strDeviceName != strName)
{
CStdString strLog;
void CCECBusDevice::SetMenuState(const cec_menu_state state)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (m_menuState != state)
{
CStdString strLog;
void CCECBusDevice::SetInactiveDevice(void)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
m_bActiveSource = false;
}
void CCECBusDevice::SetActiveDevice(void)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
for (int iPtr = 0; iPtr < 16; iPtr++)
if (iPtr != m_iLogicalAddress)
void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
switch (newStatus)
{
case CEC_DEVICE_STATUS_UNKNOWN:
void CCECBusDevice::SetPhysicalAddress(uint16_t iNewAddress)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (iNewAddress > 0 && m_iPhysicalAddress != iNewAddress)
{
CStdString strLog;
void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /* = 0 */)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (iNewAddress > 0)
{
CStdString strLog;
void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (m_powerStatus != powerStatus)
{
CStdString strLog;
void CCECBusDevice::SetVendorId(uint64_t iVendorId)
{
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
m_vendor = (cec_vendor_id)iVendorId;
switch (iVendorId)
}
CStdString strLog;
- strLog.Format("%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, GetVendorName(), m_vendor);
+ strLog.Format("%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_vendor), m_vendor);
m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str());
}
//@}
//@{
bool CCECBusDevice::TransmitActiveSource(void)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (m_powerStatus != CEC_POWER_STATUS_ON)
{
CStdString strLog;
bool CCECBusDevice::TransmitCECVersion(cec_logical_address dest)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion));
AddLog(CEC_LOG_NOTICE, strLog);
return m_processor->Transmit(command);
}
-bool CCECBusDevice::TransmitInactiveView(void)
+bool CCECBusDevice::TransmitInactiveSource(void)
{
CStdString strLog;
- strLog.Format("<< %s (%X) -> broadcast (F): inactive view", GetLogicalAddressName(), m_iLogicalAddress);
+ strLog.Format("<< %s (%X) -> broadcast (F): inactive source", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
cec_command command;
- cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_INACTIVE_SOURCE);
+ cec_command::Format(command, m_iLogicalAddress, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE);
command.parameters.PushBack((m_iPhysicalAddress >> 8) & 0xFF);
command.parameters.PushBack(m_iPhysicalAddress & 0xFF);
bool CCECBusDevice::TransmitOSDName(cec_logical_address dest)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str());
AddLog(CEC_LOG_NOTICE, strLog.c_str());
bool CCECBusDevice::TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
strLog.Format("<< %s (%X) -> %s (%X): display OSD message '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, strMessage);
AddLog(CEC_LOG_NOTICE, strLog.c_str());
bool CCECBusDevice::TransmitPhysicalAddress(void)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
strLog.Format("<< %s (%X) -> broadcast (F): physical adddress %4x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
AddLog(CEC_LOG_NOTICE, strLog.c_str());
if (bReturn)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
m_iLastActive = GetTimeMs();
}
bool CCECBusDevice::TransmitPowerState(cec_logical_address dest)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus));
AddLog(CEC_LOG_NOTICE, strLog.c_str());
bool CCECBusDevice::TransmitVendorID(cec_logical_address dest)
{
- CLockObject lock(&m_mutex);
+ CLockObject lock(&m_writeMutex);
if (m_vendor == CEC_VENDOR_UNKNOWN)
{
CStdString strLog;
return m_processor->Transmit(command);
}
}
+
+bool CCECBusDevice::SendKeypress(cec_user_control_code key, bool bWait /* = false */)
+{
+ CLockObject lock(&m_transmitMutex);
+ cec_command command;
+ cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_PRESSED);
+ command.parameters.PushBack((uint8_t)key);
+
+ if (bWait)
+ {
+ if (m_processor->Transmit(command))
+ return m_condition.Wait(&m_transmitMutex, 1000);
+ return false;
+ }
+
+ return m_processor->Transmit(command);
+}
+
+bool CCECBusDevice::SendKeyRelease(bool bWait /* = false */)
+{
+ CLockObject lock(&m_transmitMutex);
+ cec_command command;
+ cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_RELEASE);
+
+ if (bWait)
+ {
+ if (m_processor->Transmit(command))
+ return m_condition.Wait(&m_transmitMutex, 1000);
+ return false;
+ }
+ else
+ {
+ return m_processor->Transmit(command);
+ }
+}
//@}
virtual void AddLog(cec_log_level level, const CStdString &strMessage);
virtual bool HandleCommand(const cec_command &command);
- virtual void PollVendorId(void);
virtual bool PowerOn(void);
virtual bool Standby(void);
virtual cec_version GetCecVersion(void);
virtual CCECCommandHandler * GetHandler(void) const { return m_handler; };
- virtual uint64_t GetCommandSent(void) const { return m_iLastCommandSent; }
+ virtual uint64_t GetLastCommandSent(void) const;
virtual uint64_t GetLastActive(void) const { return m_iLastActive; }
virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
virtual const char* GetLogicalAddressName(void) const;
virtual cec_menu_language & GetMenuLanguage(void);
virtual cec_logical_address GetMyLogicalAddress(void) const;
virtual uint16_t GetMyPhysicalAddress(void) const;
+ virtual CStdString GetOSDName(void);
virtual uint16_t GetPhysicalAddress(bool bRefresh = true);
virtual cec_power_status GetPowerStatus(void);
virtual CCECProcessor * GetProcessor(void) const { return m_processor; }
virtual cec_vendor_id GetVendorId(void);
virtual const char * GetVendorName(void);
virtual bool MyLogicalAddressContains(cec_logical_address address) const;
- virtual cec_bus_device_status GetStatus(void);
+ virtual cec_bus_device_status GetStatus(bool bForcePoll = false);
bool RequestCecVersion(void);
bool RequestMenuLanguage(void);
bool RequestPowerStatus(void);
bool RequestVendorId(void);
bool RequestPhysicalAddress(void);
+ bool RequestOSDName(void);
virtual void SetInactiveDevice(void);
virtual void SetActiveDevice(void);
virtual bool TransmitActiveSource(void);
virtual bool TransmitCECVersion(cec_logical_address dest);
- virtual bool TransmitInactiveView(void);
+ virtual bool TransmitInactiveSource(void);
virtual bool TransmitMenuState(cec_logical_address dest);
virtual bool TransmitOSDName(cec_logical_address dest);
virtual bool TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage);
virtual bool TransmitPowerState(cec_logical_address dest);
virtual bool TransmitPoll(cec_logical_address dest);
virtual bool TransmitVendorID(cec_logical_address dest);
+ virtual bool SendKeypress(cec_user_control_code key, bool bWait = true);
+ virtual bool SendKeyRelease(bool bWait = true);
protected:
+ bool NeedsPoll(void);
+
cec_device_type m_type;
CStdString m_strDeviceName;
uint16_t m_iPhysicalAddress;
cec_version m_cecVersion;
cec_bus_device_status m_deviceStatus;
CMutex m_transmitMutex;
+ CMutex m_writeMutex;
CMutex m_mutex;
CCondition m_condition;
};
using namespace CEC;
+#define ToString(p) m_processor->ToString(p)
+
CCECPlaybackDevice::CCECPlaybackDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress /* = 0 */) :
CCECBusDevice(processor, address, iPhysicalAddress),
m_deckStatus(CEC_DECK_INFO_STOP),
m_type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
}
+cec_deck_info CCECPlaybackDevice::GetDeckStatus(void)
+{
+ CLockObject lock(&m_mutex);
+ return m_deckStatus;
+}
+
void CCECPlaybackDevice::SetDeckStatus(cec_deck_info deckStatus)
{
+ CLockObject lock(&m_writeMutex);
if (m_deckStatus != deckStatus)
{
CStdString strLog;
- strLog.Format(">> %s (%X): deck status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_deckStatus), CCECCommandHandler::ToString(deckStatus));
+ strLog.Format(">> %s (%X): deck status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_deckStatus), ToString(deckStatus));
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_deckStatus = deckStatus;
}
}
+cec_deck_control_mode CCECPlaybackDevice::GetDeckControlMode(void)
+{
+ CLockObject lock(&m_mutex);
+ return m_deckControlMode;
+}
+
void CCECPlaybackDevice::SetDeckControlMode(cec_deck_control_mode mode)
{
+ CLockObject lock(&m_writeMutex);
if (m_deckControlMode != mode)
{
CStdString strLog;
- strLog.Format(">> %s (%X): deck control mode changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_deckControlMode), CCECCommandHandler::ToString(mode));
+ strLog.Format(">> %s (%X): deck control mode changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_deckControlMode), ToString(mode));
AddLog(CEC_LOG_DEBUG, strLog.c_str());
m_deckControlMode = mode;
bool CCECPlaybackDevice::TransmitDeckStatus(cec_logical_address dest)
{
+ CLockObject lock(&m_writeMutex);
CStdString strLog;
- strLog.Format("<< %s (%X) -> %s (%X): deck status '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest, CCECCommandHandler::ToString(m_deckStatus));
+ strLog.Format("<< %s (%X) -> %s (%X): deck status '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_deckStatus));
AddLog(CEC_LOG_NOTICE, strLog);
cec_command command;
CCECPlaybackDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0);
virtual ~CCECPlaybackDevice(void) {};
- virtual cec_deck_info GetDeckStatus(void) const { return m_deckStatus; };
- virtual cec_deck_control_mode GetDeckControlMode(void) const { return m_deckControlMode; };
+ virtual cec_deck_info GetDeckStatus(void);
+ virtual cec_deck_control_mode GetDeckControlMode(void);
virtual void SetDeckStatus(cec_deck_info deckStatus);
virtual void SetDeckControlMode(cec_deck_control_mode mode);
m_type = CEC_DEVICE_TYPE_RECORDING_DEVICE;
}
-cec_deck_info CCECRecordingDevice::GetDeckStatus(void) const
+cec_deck_info CCECRecordingDevice::GetDeckStatus(void)
{
return m_playbackDevice.GetDeckStatus();
}
-cec_deck_control_mode CCECRecordingDevice::GetDeckControlMode(void) const
+cec_deck_control_mode CCECRecordingDevice::GetDeckControlMode(void)
{
return m_playbackDevice.GetDeckControlMode();
}
virtual ~CCECRecordingDevice(void) {};
/* playback device methods */
- virtual cec_deck_info GetDeckStatus(void) const;
- virtual cec_deck_control_mode GetDeckControlMode(void) const;
+ virtual cec_deck_info GetDeckStatus(void);
+ virtual cec_deck_control_mode GetDeckControlMode(void);
virtual void SetDeckStatus(cec_deck_info deckStatus);
virtual void SetDeckControlMode(cec_deck_control_mode mode);
CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice)
{
m_busDevice = busDevice;
+ m_processor = m_busDevice->GetProcessor();
}
bool CCECCommandHandler::HandleCommand(const cec_command &command)
bool bHandled(true);
CStdString strLog;
- strLog.Format(">> %s (%X) -> %s (%X): %s (%2X)", ToString(command.initiator), command.initiator, ToString(command.destination), command.destination, ToString(command.opcode), command.opcode);
+ strLog.Format(">> %s (%X) -> %s (%X): %s (%2X)", m_processor->ToString(command.initiator), command.initiator, m_processor->ToString(command.destination), command.destination, m_processor->ToString(command.opcode), command.opcode);
m_busDevice->AddLog(CEC_LOG_NOTICE, strLog);
switch(command.opcode)
HandleGiveSystemAudioModeStatus(command);
break;
case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
- HandleSetSystemAudioModeRequest(command);
+ HandleSystemAudioModeRequest(command);
+ break;
+ case CEC_OPCODE_REPORT_AUDIO_STATUS:
+ HandleReportAudioStatus(command);//YYY
+ break;
+ case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
+ HandleSystemAudioModeStatus(command);//YYY
+ break;
+ case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
+ HandleSetSystemAudioMode(command);//YYY
break;
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
HandleRequestActiveSource(command);
case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
HandleReportPhysicalAddress(command);
break;
- case CEC_OPCODE_REPORT_AUDIO_STATUS:
- HandleReportAudioStatus(command);
- break;
- case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
- HandleSystemAudioStatus(command);
- break;
case CEC_OPCODE_SET_OSD_NAME:
HandleSetOSDName(command);
break;
break;
}
- if (command.destination == CECDEVICE_BROADCAST || m_busDevice->MyLogicalAddressContains(command.destination))
- m_busDevice->GetProcessor()->AddCommand(command);
-
+ m_processor->AddCommand(command);
return bHandled;
}
if (command.parameters.size == 2)
{
uint16_t iAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
- return m_busDevice->GetProcessor()->SetStreamPath(iAddress);
+ return m_processor->SetStreamPath(iAddress);
}
return true;
bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
{
if (m_busDevice->MyLogicalAddressContains(command.destination))
- m_busDevice->GetProcessor()->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED);
+ m_processor->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED);
return true;
}
bool CCECCommandHandler::HandleImageViewOn(const cec_command &command)
{
- m_busDevice->GetProcessor()->SetActiveSource(command.initiator);
+ m_processor->SetActiveSource(command.initiator);
return true;
}
if (command.parameters.size == 2)
{
uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
- m_busDevice->GetProcessor()->SetStreamPath(iNewAddress);
+ m_processor->SetStreamPath(iNewAddress);
}
return false;
strLog.Format(">> %i sets stream path to physical address %04x", command.initiator, iStreamAddress);
m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
- if (m_busDevice->GetProcessor()->SetStreamPath(iStreamAddress))
+ if (m_processor->SetStreamPath(iStreamAddress))
{
CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress);
if (device)
return false;
}
-bool CCECCommandHandler::HandleSetSystemAudioModeRequest(const cec_command &command)
+bool CCECCommandHandler::HandleSystemAudioModeRequest(const cec_command &command)
{
- if (m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size >= 1)
+ if (m_busDevice->MyLogicalAddressContains(command.destination))
{
CCECBusDevice *device = GetDevice(command.destination);
- if (device&& device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
- return ((CCECAudioSystem *) device)->SetSystemAudioMode(command);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ if (command.parameters.size >= 2)
+ {
+ device->SetPowerStatus(CEC_POWER_STATUS_ON);
+ ((CCECAudioSystem *) device)->SetSystemAudioModeStatus(CEC_SYSTEM_AUDIO_STATUS_ON);
+ uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+ CCECBusDevice *newActiveDevice = GetDeviceByPhysicalAddress(iNewAddress);
+ if (newActiveDevice)
+ m_processor->SetActiveSource(newActiveDevice->GetLogicalAddress());
+ return ((CCECAudioSystem *) device)->TransmitSetSystemAudioMode(command.initiator);
+ }
+ else
+ {
+ ((CCECAudioSystem *) device)->SetSystemAudioModeStatus(CEC_SYSTEM_AUDIO_STATUS_OFF);
+ return ((CCECAudioSystem *) device)->TransmitSetSystemAudioMode(command.initiator);
+ }
+ }
}
return false;
}
return true;
}
-bool CCECCommandHandler::HandleSystemAudioStatus(const cec_command &command)
+bool CCECCommandHandler::HandleSystemAudioModeStatus(const cec_command &command)
{
- CCECBusDevice *device = GetDevice(command.initiator);
- if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ if (command.parameters.size == 1)
{
- ((CCECAudioSystem *)device)->SetSystemAudioMode(command);
- return true;
+ CCECBusDevice *device = GetDevice(command.initiator);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ ((CCECAudioSystem *)device)->SetSystemAudioModeStatus((cec_system_audio_status)command.parameters[0]);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CCECCommandHandler::HandleSetSystemAudioMode(const cec_command &command)
+{
+ if (command.parameters.size == 1)
+ {
+ CCECBusDevice *device = GetDevice(command.initiator);
+ if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM)
+ {
+ ((CCECAudioSystem *)device)->SetSystemAudioModeStatus((cec_system_audio_status)command.parameters[0]);
+ return true;
+ }
}
return false;
bool CCECCommandHandler::HandleTextViewOn(const cec_command &command)
{
- m_busDevice->GetProcessor()->SetActiveSource(command.initiator);
+ m_processor->SetActiveSource(command.initiator);
return true;
}
{
if (m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0)
{
- m_busDevice->GetProcessor()->AddKey();
+ m_processor->AddKey();
if (command.parameters[0] <= CEC_USER_CONTROL_CODE_MAX)
{
device->SetPowerStatus(CEC_POWER_STATUS_ON);
}
- m_busDevice->GetProcessor()->SetCurrentButton((cec_user_control_code) command.parameters[0]);
+ m_processor->SetCurrentButton((cec_user_control_code) command.parameters[0]);
return true;
}
}
bool CCECCommandHandler::HandleUserControlRelease(const cec_command &command)
{
if (m_busDevice->MyLogicalAddressContains(command.destination))
- m_busDevice->GetProcessor()->AddKey();
+ m_processor->AddKey();
return true;
}
{
unsigned int iReturn(0);
- cec_logical_addresses addresses = m_busDevice->GetProcessor()->GetLogicalAddresses();
+ cec_logical_addresses addresses = m_processor->GetLogicalAddresses();
for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
{
if (addresses[iPtr])
CCECBusDevice *device = NULL;
if (iLogicalAddress >= CECDEVICE_TV && iLogicalAddress <= CECDEVICE_BROADCAST)
- device = m_busDevice->GetProcessor()->m_busDevices[iLogicalAddress];
+ device = m_processor->m_busDevices[iLogicalAddress];
return device;
}
CCECBusDevice *CCECCommandHandler::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const
{
- return m_busDevice->GetProcessor()->GetDeviceByPhysicalAddress(iPhysicalAddress);
+ return m_processor->GetDeviceByPhysicalAddress(iPhysicalAddress);
}
CCECBusDevice *CCECCommandHandler::GetDeviceByType(cec_device_type type) const
{
- return m_busDevice->GetProcessor()->GetDeviceByType(type);
+ return m_processor->GetDeviceByType(type);
}
void CCECCommandHandler::SetVendorId(const cec_command &command)
{
if (!m_busDevice->MyLogicalAddressContains(iAddress))
{
- bool bOurAddress(m_busDevice->GetProcessor()->GetPhysicalAddress() == iNewAddress);
+ bool bOurAddress(m_processor->GetPhysicalAddress() == iNewAddress);
GetDevice(iAddress)->SetPhysicalAddress(iNewAddress);
if (bOurAddress)
{
/* another device reported the same physical address as ours
* since we don't have physical address detection yet, we'll just use the
* given address, increased by 0x100 for now */
- m_busDevice->GetProcessor()->SetPhysicalAddress(iNewAddress + 0x100);
+ m_processor->SetPhysicalAddress(iNewAddress + 0x100);
}
}
}
-
-const char *CCECCommandHandler::ToString(const cec_menu_state state)
-{
- switch (state)
- {
- case CEC_MENU_STATE_ACTIVATED:
- return "activated";
- case CEC_MENU_STATE_DEACTIVATED:
- return "deactivated";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_version version)
-{
- switch (version)
- {
- case CEC_VERSION_1_2:
- return "1.2";
- case CEC_VERSION_1_2A:
- return "1.2a";
- case CEC_VERSION_1_3:
- return "1.3";
- case CEC_VERSION_1_3A:
- return "1.3a";
- case CEC_VERSION_1_4:
- return "1.4";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_power_status status)
-{
- switch (status)
- {
- case CEC_POWER_STATUS_ON:
- return "on";
- case CEC_POWER_STATUS_STANDBY:
- return "standby";
- case CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY:
- return "in transition from on to standby";
- case CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON:
- return "in transition from standby to on";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_logical_address address)
-{
- switch(address)
- {
- case CECDEVICE_AUDIOSYSTEM:
- return "Audio";
- case CECDEVICE_BROADCAST:
- return "Broadcast";
- case CECDEVICE_FREEUSE:
- return "Free use";
- case CECDEVICE_PLAYBACKDEVICE1:
- return "Playback 1";
- case CECDEVICE_PLAYBACKDEVICE2:
- return "Playback 2";
- case CECDEVICE_PLAYBACKDEVICE3:
- return "Playback 3";
- case CECDEVICE_RECORDINGDEVICE1:
- return "Recorder 1";
- case CECDEVICE_RECORDINGDEVICE2:
- return "Recorder 2";
- case CECDEVICE_RECORDINGDEVICE3:
- return "Recorder 3";
- case CECDEVICE_RESERVED1:
- return "Reserved 1";
- case CECDEVICE_RESERVED2:
- return "Reserved 2";
- case CECDEVICE_TUNER1:
- return "Tuner 1";
- case CECDEVICE_TUNER2:
- return "Tuner 2";
- case CECDEVICE_TUNER3:
- return "Tuner 3";
- case CECDEVICE_TUNER4:
- return "Tuner 4";
- case CECDEVICE_TV:
- return "TV";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_deck_control_mode mode)
-{
- switch (mode)
- {
- case CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND:
- return "skip forward wind";
- case CEC_DECK_CONTROL_MODE_EJECT:
- return "eject";
- case CEC_DECK_CONTROL_MODE_SKIP_REVERSE_REWIND:
- return "reverse rewind";
- case CEC_DECK_CONTROL_MODE_STOP:
- return "stop";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_deck_info status)
-{
- switch (status)
- {
- case CEC_DECK_INFO_PLAY:
- return "play";
- case CEC_DECK_INFO_RECORD:
- return "record";
- case CEC_DECK_INFO_PLAY_REVERSE:
- return "play reverse";
- case CEC_DECK_INFO_STILL:
- return "still";
- case CEC_DECK_INFO_SLOW:
- return "slow";
- case CEC_DECK_INFO_SLOW_REVERSE:
- return "slow reverse";
- case CEC_DECK_INFO_FAST_FORWARD:
- return "fast forward";
- case CEC_DECK_INFO_FAST_REVERSE:
- return "fast reverse";
- case CEC_DECK_INFO_NO_MEDIA:
- return "no media";
- case CEC_DECK_INFO_STOP:
- return "stop";
- case CEC_DECK_INFO_SKIP_FORWARD_WIND:
- return "info skip forward wind";
- case CEC_DECK_INFO_SKIP_REVERSE_REWIND:
- return "info skip reverse rewind";
- case CEC_DECK_INFO_INDEX_SEARCH_FORWARD:
- return "info index search forward";
- case CEC_DECK_INFO_INDEX_SEARCH_REVERSE:
- return "info index search reverse";
- case CEC_DECK_INFO_OTHER_STATUS:
- return "other";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_opcode opcode)
-{
- switch (opcode)
- {
- case CEC_OPCODE_ACTIVE_SOURCE:
- return "active source";
- case CEC_OPCODE_IMAGE_VIEW_ON:
- return "image view on";
- case CEC_OPCODE_TEXT_VIEW_ON:
- return "text view on";
- case CEC_OPCODE_INACTIVE_SOURCE:
- return "inactive source";
- case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
- return "request active source";
- case CEC_OPCODE_ROUTING_CHANGE:
- return "routing change";
- case CEC_OPCODE_ROUTING_INFORMATION:
- return "routing information";
- case CEC_OPCODE_SET_STREAM_PATH:
- return "set stream path";
- case CEC_OPCODE_STANDBY:
- return "standby";
- case CEC_OPCODE_RECORD_OFF:
- return "record off";
- case CEC_OPCODE_RECORD_ON:
- return "record on";
- case CEC_OPCODE_RECORD_STATUS:
- return "record status";
- case CEC_OPCODE_RECORD_TV_SCREEN:
- return "record tv screen";
- case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
- return "clear analogue timer";
- case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
- return "clear digital timer";
- case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
- return "clear external timer";
- case CEC_OPCODE_SET_ANALOGUE_TIMER:
- return "set analogue timer";
- case CEC_OPCODE_SET_DIGITAL_TIMER:
- return "set digital timer";
- case CEC_OPCODE_SET_EXTERNAL_TIMER:
- return "set external timer";
- case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
- return "set timer program title";
- case CEC_OPCODE_TIMER_CLEARED_STATUS:
- return "timer cleared status";
- case CEC_OPCODE_TIMER_STATUS:
- return "timer status";
- case CEC_OPCODE_CEC_VERSION:
- return "cec version";
- case CEC_OPCODE_GET_CEC_VERSION:
- return "get cec version";
- case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
- return "give physical address";
- case CEC_OPCODE_GET_MENU_LANGUAGE:
- return "get menu language";
- case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
- return "report physical address";
- case CEC_OPCODE_SET_MENU_LANGUAGE:
- return "set menu language";
- case CEC_OPCODE_DECK_CONTROL:
- return "deck control";
- case CEC_OPCODE_DECK_STATUS:
- return "deck status";
- case CEC_OPCODE_GIVE_DECK_STATUS:
- return "give deck status";
- case CEC_OPCODE_PLAY:
- return "play";
- case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
- return "give tuner status";
- case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
- return "select analogue service";
- case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
- return "set digital service";
- case CEC_OPCODE_TUNER_DEVICE_STATUS:
- return "tuner device status";
- case CEC_OPCODE_TUNER_STEP_DECREMENT:
- return "tuner step decrement";
- case CEC_OPCODE_TUNER_STEP_INCREMENT:
- return "tuner step increment";
- case CEC_OPCODE_DEVICE_VENDOR_ID:
- return "device vendor id";
- case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
- return "give device vendor id";
- case CEC_OPCODE_VENDOR_COMMAND:
- return "vendor command";
- case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
- return "vendor command with id";
- case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
- return "vendor remote button down";
- case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
- return "vendor remote button up";
- case CEC_OPCODE_SET_OSD_STRING:
- return "set osd string";
- case CEC_OPCODE_GIVE_OSD_NAME:
- return "give osd name";
- case CEC_OPCODE_SET_OSD_NAME:
- return "set osd name";
- case CEC_OPCODE_MENU_REQUEST:
- return "menu request";
- case CEC_OPCODE_MENU_STATUS:
- return "menu status";
- case CEC_OPCODE_USER_CONTROL_PRESSED:
- return "user control pressed";
- case CEC_OPCODE_USER_CONTROL_RELEASE:
- return "user control release";
- case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
- return "give device power status";
- case CEC_OPCODE_REPORT_POWER_STATUS:
- return "report power status";
- case CEC_OPCODE_FEATURE_ABORT:
- return "feature abort";
- case CEC_OPCODE_ABORT:
- return "abort";
- case CEC_OPCODE_GIVE_AUDIO_STATUS:
- return "give audio status";
- case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
- return "give audio mode status";
- case CEC_OPCODE_REPORT_AUDIO_STATUS:
- return "report audio status";
- case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
- return "set system audio mode";
- case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
- return "system audio mode request";
- case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
- return "system audio mode status";
- case CEC_OPCODE_SET_AUDIO_RATE:
- return "set audio rate";
- default:
- return "UNKNOWN";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_system_audio_status mode)
-{
- switch(mode)
- {
- case CEC_SYSTEM_AUDIO_STATUS_ON:
- return "on";
- case CEC_SYSTEM_AUDIO_STATUS_OFF:
- return "off";
- default:
- return "unknown";
- }
-}
-
-const char *CCECCommandHandler::ToString(const cec_audio_status status)
-{
- // TODO this is a mask
- return "TODO";
-}
-
-const char *CCECCommandHandler::ToString(const cec_vendor_id vendor)
-{
- switch (vendor)
- {
- case CEC_VENDOR_SAMSUNG:
- return "Samsung";
- case CEC_VENDOR_LG:
- return "LG";
- case CEC_VENDOR_PANASONIC:
- return "Panasonic";
- case CEC_VENDOR_PIONEER:
- return "Pioneer";
- case CEC_VENDOR_ONKYO:
- return "Onkyo";
- default:
- return "Unknown";
- }
-}
namespace CEC
{
+ class CCECProcessor;
class CCECBusDevice;
class CCECCommandHandler
virtual bool HandleCommand(const cec_command &command);
virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; };
- static const char *ToString(const cec_menu_state state);
- static const char *ToString(const cec_deck_control_mode mode);
- static const char *ToString(const cec_version version);
- static const char *ToString(const cec_power_status status);
- static const char *ToString(const cec_deck_info status);
- static const char* ToString(const cec_logical_address address);
- static const char* ToString(const cec_opcode opcode);
- static const char *ToString(const cec_system_audio_status mode);
- static const char *ToString(const cec_audio_status status);
- static const char *ToString(const cec_vendor_id vendor);
-
protected:
virtual bool HandleActiveSource(const cec_command &command);
virtual bool HandleDeckControl(const cec_command &command);
virtual bool HandleSetMenuLanguage(const cec_command &command);
virtual bool HandleSetOSDName(const cec_command &command);
virtual bool HandleSetStreamPath(const cec_command &command);
- virtual bool HandleSetSystemAudioModeRequest(const cec_command &command);
+ virtual bool HandleSystemAudioModeRequest(const cec_command &command);
virtual bool HandleStandby(const cec_command &command);
- virtual bool HandleSystemAudioStatus(const cec_command &command);
+ virtual bool HandleSystemAudioModeStatus(const cec_command &command);
+ virtual bool HandleSetSystemAudioMode(const cec_command &command);
virtual bool HandleTextViewOn(const cec_command &command);
virtual bool HandleUserControlPressed(const cec_command &command);
virtual bool HandleUserControlRelease(const cec_command &command);
virtual void SetVendorId(const cec_command &command);
virtual void SetPhysicalAddress(cec_logical_address iAddress, uint16_t iNewAddress);
+ CCECProcessor *m_processor;
CCECBusDevice *m_busDevice;
};
};
#include <sstream>
#include "../lib/platform/threads.h"
#include "../lib/util/StdString.h"
+#include "../lib/implementations/CECCommandHandler.h"
using namespace CEC;
using namespace std;
"[on] {address} power on the device with the given logical address." << endl <<
"[standby] {address} put the device with the given address in standby mode." << endl <<
"[la] {logical address} change the logical address of the CEC adapter." << endl <<
- "[p] {port number} change the HDMI port number of the CEC adapter." << endl <<
+ "[p] {device} {port} change the HDMI port number of the CEC adapter." << endl <<
"[pa] {physical address} change the physical address of the CEC adapter." << endl <<
"[osd] {addr} {string} set OSD message on the specified device." << endl <<
"[ver] {addr} get the CEC version of the specified device." << endl <<
"[ven] {addr} get the vendor ID of the specified device." << endl <<
"[lang] {addr} get the menu language of the specified device." << endl <<
"[pow] {addr} get the power status of the specified device." << endl <<
+ "[name] {addr} get the OSD name of the specified device." << endl <<
"[poll] {addr} poll the specified device." << endl <<
"[lad] lists active devices on the bus" << endl <<
"[ad] {addr} checks whether the specified device is active." << endl <<
"[volup] send a volume up command to the amp if present" << endl <<
"[voldown] send a volume down command to the amp if present" << endl <<
"[mute] send a mute/unmute command to the amp if present" << endl <<
+ "[scan] scan the CEC bus and display device info" << endl <<
"[mon] {1|0} enable or disable CEC bus monitoring." << endl <<
"[log] {1 - 31} change the log level. see cectypes.h for values." << endl <<
"[ping] send a ping command to the CEC adapter." << endl <<
{
if (argc >= iArgPtr + 2)
{
- iHDMIPort= atoi(argv[iArgPtr + 1]);
+ iHDMIPort = (int8_t)atoi(argv[iArgPtr + 1]);
cout << "using HDMI port '" << iHDMIPort << "'" << endl;
++iArgPtr;
}
if (iHDMIPort > 0)
{
- parser->SetHDMIPort((uint8_t)iHDMIPort);
+ parser->SetHDMIPort((cec_logical_address)CEC_DEFAULT_BASE_DEVICE, (uint8_t)iHDMIPort);
FlushLog(parser);
}
}
else if (command == "p")
{
- string strvalue;
- if (GetWord(input, strvalue))
+ string strPort, strDevice;
+ if (GetWord(input, strDevice) && GetWord(input, strPort))
{
- parser->SetHDMIPort(atoi(strvalue.c_str()));
+ parser->SetHDMIPort((cec_logical_address)atoi(strDevice.c_str()), (uint8_t)atoi(strPort.c_str()));
}
}
else if (command == "pa")
}
else if (command == "volup")
{
- parser->VolumeUp();
+ CStdString strLog;
+ strLog.Format("volume up: %2X", parser->VolumeUp());
+ cout << strLog.c_str() << endl;
}
else if (command == "voldown")
{
- parser->VolumeDown();
+ CStdString strLog;
+ strLog.Format("volume up: %2X", parser->VolumeDown());
+ cout << strLog.c_str() << endl;
}
else if (command == "mute")
{
- parser->MuteAudio();
+ CStdString strLog;
+ strLog.Format("mute: %2X", parser->MuteAudio());
+ cout << strLog.c_str() << endl;
}
else if (command == "mon")
{
}
}
}
+ else if (command == "name")
+ {
+ CStdString strDev;
+ if (GetWord(input, strDev))
+ {
+ int iDev = atoi(strDev);
+ if (iDev >= 0 && iDev < 15)
+ {
+ cec_osd_name name = parser->GetOSDName((cec_logical_address)iDev);
+ cout << "OSD name of device " << iDev << " is '" << name.name << "'" << endl;
+ }
+ }
+ }
else if (command == "lad")
{
cout << "listing active devices:" << endl;
cec_logical_addresses addresses = parser->GetActiveDevices();
- for (unsigned iPtr = 0; iPtr < 16; iPtr++)
+ for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
if (addresses[iPtr])
- cout << "logical address " << iPtr << endl;
+ cout << "logical address " << (int)iPtr << endl;
+ }
+ else if (command == "scan")
+ {
+ cout << "CEC bus information" << endl;
+ cout << "===================" << endl;
+ cec_logical_addresses addresses = parser->GetActiveDevices();
+ for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+ if (addresses[iPtr])
+ {
+ uint64_t iVendorId = parser->GetDeviceVendorId((cec_logical_address)iPtr);
+ cec_version iCecVersion = parser->GetDeviceCecVersion((cec_logical_address)iPtr);
+ cec_power_status power = parser->GetDevicePowerStatus((cec_logical_address)iPtr);
+ cec_osd_name osdName = parser->GetOSDName((cec_logical_address)iPtr);
+ cec_menu_language lang;
+ lang.device = CECDEVICE_UNKNOWN;
+ parser->GetDeviceMenuLanguage((cec_logical_address)iPtr, &lang);
+
+ cout << "device #" << (int)iPtr << ": " << parser->ToString((cec_logical_address)iPtr) << endl;
+ cout << "vendor: " << parser->ToString((cec_vendor_id)iVendorId) << endl;
+ cout << "osd string: " << osdName.name << endl;
+ cout << "CEC version: " << parser->ToString(iCecVersion) << endl;
+ cout << "power status: " << parser->ToString(power) << endl;
+ if ((uint8_t)lang.device == iPtr)
+ cout << "language: " << lang.language << endl;
+ cout << endl;
+ }
}
else if (command == "ad")
{