X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2FCECProcessor.cpp;h=9ed9b23b8405c63b811bb2d065cad7a26a8698b9;hb=4fe8d858f161384e8f808751c47d0e7e541b3adb;hp=6af06649d708a87a3cfe2bfbf129c5fdb6cb4fd8;hpb=591170fd731645adaa8b2f84ffc27d81d3eff4bc;p=deb_libcec.git diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 6af0664..9ed9b23 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -41,11 +41,10 @@ #include "devices/CECTV.h" #include "implementations/CECCommandHandler.h" #include "LibCEC.h" -#include "util/StdString.h" -#include "platform/timeutils.h" using namespace CEC; using namespace std; +using namespace PLATFORM; CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS*/) : m_bStarted(false), @@ -134,7 +133,7 @@ bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */, bool bReturn(false); { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); /* check for an already opened connection */ if (!m_communication || m_communication->IsOpen()) @@ -151,7 +150,7 @@ bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */, } /* create the processor thread */ - if (!CreateThread() || !m_startCondition.Wait(&m_mutex) || !m_bStarted) + if (!CreateThread() || !m_startCondition.Wait(m_mutex) || !m_bStarted) { m_controller->AddLog(CEC_LOG_ERROR, "could not create a processor thread"); return bReturn; @@ -170,22 +169,15 @@ bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */, m_busDevices[m_logicalAddresses.primary]->m_strDeviceName = m_strDeviceName; /* get the vendor id from the TV, so we are using the correct handler */ - m_busDevices[CECDEVICE_TV]->GetVendorId(); + m_busDevices[CECDEVICE_TV]->RequestVendorId(); ReplaceHandlers(); bReturn = SetHDMIPort(m_iBaseDevice, m_iHDMIPort, true); } - /* make the primary device the active source */ if (bReturn) { m_bInitialised = true; - m_busDevices[m_logicalAddresses.primary]->m_bActiveSource = true; - bReturn = m_busDevices[CECDEVICE_TV]->InitHandler(); - } - - if (bReturn) - { m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started"); } else @@ -239,6 +231,85 @@ bool CCECProcessor::FindLogicalAddressAudioSystem(void) return TryLogicalAddress(CECDEVICE_AUDIOSYSTEM); } +bool CCECProcessor::ChangeDeviceType(cec_device_type from, cec_device_type to) +{ + bool bChanged(false); + + CStdString strLog; + strLog.Format("changing device type '%s' into '%s'", ToString(from), ToString(to)); + AddLog(CEC_LOG_NOTICE, strLog); + + CLockObject lock(m_mutex); + CCECBusDevice *previousDevice = GetDeviceByType(from); + m_logicalAddresses.primary = CECDEVICE_UNKNOWN; + + for (unsigned int iPtr = 0; iPtr < 5; iPtr++) + { + if (m_types.types[iPtr] == CEC_DEVICE_TYPE_RESERVED) + continue; + + if (m_types.types[iPtr] == from) + { + bChanged = true; + m_types.types[iPtr] = to; + } + else if (m_types.types[iPtr] == to && bChanged) + { + m_types.types[iPtr] = CEC_DEVICE_TYPE_RESERVED; + } + } + + if (bChanged) + { + FindLogicalAddresses(); + + CCECBusDevice *newDevice = GetDeviceByType(to); + if (previousDevice && newDevice) + { + newDevice->SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC); + previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_UNKNOWN); + + newDevice->SetCecVersion(previousDevice->GetCecVersion(false)); + previousDevice->SetCecVersion(CEC_VERSION_UNKNOWN); + + newDevice->SetMenuLanguage(previousDevice->GetMenuLanguage(false)); + cec_menu_language lang; + lang.device = previousDevice->GetLogicalAddress(); + for (unsigned int iPtr = 0; iPtr < 4; iPtr++) + lang.language[iPtr] = '?'; + lang.language[3] = 0; + previousDevice->SetMenuLanguage(lang); + + newDevice->SetMenuState(previousDevice->GetMenuState()); + previousDevice->SetMenuState(CEC_MENU_STATE_DEACTIVATED); + + newDevice->SetOSDName(previousDevice->GetOSDName(false)); + previousDevice->SetOSDName(ToString(previousDevice->GetLogicalAddress())); + + newDevice->SetPhysicalAddress(previousDevice->GetPhysicalAddress(false)); + previousDevice->SetPhysicalAddress(0xFFFF); + + newDevice->SetPowerStatus(previousDevice->GetPowerStatus(false)); + previousDevice->SetPowerStatus(CEC_POWER_STATUS_UNKNOWN); + + newDevice->SetVendorId(previousDevice->GetVendorId(false)); + previousDevice->SetVendorId(CEC_VENDOR_UNKNOWN); + + if ((from == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || from == CEC_DEVICE_TYPE_RECORDING_DEVICE) && + (to == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || to == CEC_DEVICE_TYPE_RECORDING_DEVICE)) + { + ((CCECPlaybackDevice *) newDevice)->SetDeckControlMode(((CCECPlaybackDevice *) previousDevice)->GetDeckControlMode()); + ((CCECPlaybackDevice *) previousDevice)->SetDeckControlMode(CEC_DECK_CONTROL_MODE_STOP); + + ((CCECPlaybackDevice *) newDevice)->SetDeckStatus(((CCECPlaybackDevice *) previousDevice)->GetDeckStatus()); + ((CCECPlaybackDevice *) previousDevice)->SetDeckStatus(CEC_DECK_INFO_STOP); + } + } + } + + return true; +} + bool CCECProcessor::FindLogicalAddresses(void) { bool bReturn(true); @@ -282,7 +353,7 @@ void *CCECProcessor::Process(void) CCECAdapterMessage msg; { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); m_bStarted = true; m_controller->AddLog(CEC_LOG_DEBUG, "processor thread started"); m_startCondition.Signal(); @@ -295,7 +366,7 @@ void *CCECProcessor::Process(void) msg.clear(); { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); if (m_commandBuffer.Pop(command)) { bParseFrame = true; @@ -349,7 +420,8 @@ bool CCECProcessor::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RE bReturn = m_busDevices[addr]->TransmitActiveSource(); if (bReturn && (m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || - m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)) + m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE) && + m_busDevices[addr]->GetHandler()->SendDeckStatusUpdateOnActiveSource()) { bReturn = ((CCECPlaybackDevice *)m_busDevices[addr])->TransmitDeckStatus(CECDEVICE_TV); } @@ -374,13 +446,13 @@ bool CCECProcessor::SetActiveSource(uint16_t iStreamPath) void CCECProcessor::SetStandardLineTimeout(uint8_t iTimeout) { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); m_iStandardLineTimeout = iTimeout; } void CCECProcessor::SetRetryLineTimeout(uint8_t iTimeout) { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); m_iRetryLineTimeout = iTimeout; } @@ -424,14 +496,12 @@ bool CCECProcessor::SetDeckInfo(cec_deck_info info, bool bSendUpdate /* = true * bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce /* = false */) { bool bReturn(false); - { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); - m_iBaseDevice = iBaseDevice; - m_iHDMIPort = iPort; - if (!m_bStarted && !bForce) - return true; - } + m_iBaseDevice = iBaseDevice; + m_iHDMIPort = iPort; + if (!m_bStarted && !bForce) + return true; CStdString strLog; strLog.Format("setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice); @@ -439,7 +509,11 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, uint16_t iPhysicalAddress(0); if (iBaseDevice > CECDEVICE_TV) + { + lock.Unlock(); iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress(); + lock.Lock(); + } if (iPhysicalAddress < 0xffff) { @@ -452,12 +526,16 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, else if (iPhysicalAddress % 0x10 == 0) iPhysicalAddress += iPort; - SetPhysicalAddress(iPhysicalAddress); bReturn = true; } if (!bReturn) m_controller->AddLog(CEC_LOG_ERROR, "failed to set the physical address"); + else + { + lock.Unlock(); + SetPhysicalAddress(iPhysicalAddress); + } return bReturn; } @@ -496,7 +574,7 @@ void CCECProcessor::LogOutput(const cec_command &data) bool CCECProcessor::SetLogicalAddress(cec_logical_address iLogicalAddress) { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); if (m_logicalAddresses.primary != iLogicalAddress) { CStdString strLog; @@ -524,21 +602,40 @@ bool CCECProcessor::SetMenuState(cec_menu_state state, bool bSendUpdate /* = tru return true; } -bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress) +bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress, bool bSendUpdate /* = true */) { - CLockObject lock(&m_mutex); - if (!m_logicalAddresses.IsEmpty()) + bool bSendActiveView(false); + bool bReturn(false); + cec_logical_addresses sendUpdatesTo; + { - for (uint8_t iPtr = 0; iPtr < 15; iPtr++) - if (m_logicalAddresses[iPtr]) - { - m_busDevices[iPtr]->SetInactiveSource(); - m_busDevices[iPtr]->SetPhysicalAddress(iPhysicalAddress); - m_busDevices[iPtr]->TransmitPhysicalAddress(); - } - return SetActiveView(); + CLockObject lock(m_mutex); + if (!m_logicalAddresses.IsEmpty()) + { + bool bWasActiveSource(false); + for (uint8_t iPtr = 0; iPtr < 15; iPtr++) + if (m_logicalAddresses[iPtr]) + { + bWasActiveSource |= m_busDevices[iPtr]->IsActiveSource(); + m_busDevices[iPtr]->SetInactiveSource(); + m_busDevices[iPtr]->SetPhysicalAddress(iPhysicalAddress); + if (bSendUpdate) + sendUpdatesTo.Set((cec_logical_address)iPtr); + } + + bSendActiveView = bWasActiveSource && bSendUpdate; + bReturn = true; + } } - return false; + + for (uint8_t iPtr = 0; iPtr < 15; iPtr++) + if (sendUpdatesTo[iPtr]) + m_busDevices[iPtr]->TransmitPhysicalAddress(); + + if (bSendActiveView) + SetActiveView(); + + return bReturn; } bool CCECProcessor::SwitchMonitoring(bool bEnable) @@ -548,7 +645,7 @@ bool CCECProcessor::SwitchMonitoring(bool bEnable) m_controller->AddLog(CEC_LOG_NOTICE, strLog.c_str()); { - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); m_bMonitor = bEnable; } @@ -729,7 +826,7 @@ bool CCECProcessor::Transmit(const cec_command &data) bool CCECProcessor::Transmit(CCECAdapterMessage *output) { bool bReturn(false); - CLockObject lock(&m_mutex); + CLockObject lock(m_mutex); { m_iLastTransmission = GetTimeMs(); m_communication->SetLineTimeout(m_iStandardLineTimeout); @@ -740,12 +837,12 @@ bool CCECProcessor::Transmit(CCECAdapterMessage *output) if (output->tries > 0) m_communication->SetLineTimeout(m_iRetryLineTimeout); - CLockObject msgLock(&output->mutex); + CLockObject msgLock(output->mutex); if (!m_communication || !m_communication->Write(output)) return bReturn; else { - output->condition.Wait(&output->mutex); + output->condition.Wait(output->mutex); if (output->state != ADAPTER_MESSAGE_STATE_SENT) { m_controller->AddLog(CEC_LOG_ERROR, "command was not sent"); @@ -1005,6 +1102,27 @@ bool CCECProcessor::TransmitKeyRelease(cec_logical_address iDestination, bool bW return m_busDevices[iDestination]->TransmitKeyRelease(bWait); } +const char *CCECProcessor::ToString(const cec_device_type type) +{ + switch (type) + { + case CEC_DEVICE_TYPE_AUDIO_SYSTEM: + return "audio system"; + case CEC_DEVICE_TYPE_PLAYBACK_DEVICE: + return "playback device"; + case CEC_DEVICE_TYPE_RECORDING_DEVICE: + return "recording device"; + case CEC_DEVICE_TYPE_RESERVED: + return "reserved"; + case CEC_DEVICE_TYPE_TUNER: + return "tuner"; + case CEC_DEVICE_TYPE_TV: + return "TV"; + default: + return "unknown"; + } +} + const char *CCECProcessor::ToString(const cec_menu_state state) { switch (state) @@ -1297,7 +1415,7 @@ const char *CCECProcessor::ToString(const cec_system_audio_status mode) } } -const char *CCECProcessor::ToString(const cec_audio_status status) +const char *CCECProcessor::ToString(const cec_audio_status UNUSED(status)) { // TODO this is a mask return "TODO"; @@ -1321,6 +1439,8 @@ const char *CCECProcessor::ToString(const cec_vendor_id vendor) return "Yamaha"; case CEC_VENDOR_PHILIPS: return "Philips"; + case CEC_VENDOR_SONY: + return "Sony"; default: return "Unknown"; }