X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2FCECProcessor.cpp;h=373c6f3322e995a226c914ed719873c9b4e52671;hb=8354f74710bf154d9b31335958b0189f10d6a408;hp=8f2ea98f24ac4529bca5339717e4a90ad1e3b0cb;hpb=04e637f9e37a0bcbd6aacc51746bb548293007ef;p=deb_libcec.git diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 8f2ea98..373c6f3 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -50,10 +50,12 @@ using namespace std; 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); @@ -65,6 +67,7 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm 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), @@ -107,8 +110,15 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *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++) @@ -131,7 +141,15 @@ bool CCECProcessor::Start(void) 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"); @@ -220,28 +238,19 @@ void *CCECProcessor::Process(void) 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()) @@ -270,14 +279,6 @@ void *CCECProcessor::Process(void) 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; @@ -350,30 +351,41 @@ bool CCECProcessor::SetDeckInfo(cec_deck_info info, bool bSendUpdate /* = true * 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 { @@ -387,7 +399,7 @@ bool CCECProcessor::SetHDMIPort(uint8_t iPort) 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; @@ -409,13 +421,13 @@ bool CCECProcessor::SetStreamPath(uint16_t iStreamPath) 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; } @@ -488,33 +500,37 @@ bool CCECProcessor::SwitchMonitoring(bool bEnable) 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; } @@ -558,6 +574,17 @@ cec_version CCECProcessor::GetDeviceCecVersion(cec_logical_address iAddress) 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]) @@ -735,6 +762,7 @@ void CCECProcessor::ParseCommand(cec_command &command) 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) @@ -813,3 +841,362 @@ bool CCECProcessor::SetAckMask(uint16_t iMask) 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; +}