From: Lars Op den Kamp Date: Thu, 6 Dec 2012 20:18:49 +0000 (+0100) Subject: Merge branch 'master' into release X-Git-Tag: upstream/2.2.0~1^2~9 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=e1599e03160b77d26f8f0ab70c6bdb3c3597d5b9;hp=178d498b825f815a2b9f1aaab1d6f5d41b3cd414;p=deb_libcec.git Merge branch 'master' into release --- diff --git a/ChangeLog b/ChangeLog index a1ccd68..d284eda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +libcec (2.0.5-1) unstable; urgency=low + + * changed: + * also try polls at least twice when it failed + * added methods to get the audiostatus and toggle the mute status from the + amplifier (if connected) + * added comboKey and iComboKeyTimeoutMs to libcec_configuration + * force cec_user_control_code_unknown to 0xFF + * fixed: + * check unsupported features properly + * only send an active source message when the stream path changed and we + weren't the active source yet + * don't mark as inactive source on routing changes + * press & hold + * never mark user control opcodes as unsupported + * report our OSD name to the TV, since some TVs don't request it + * initial audiostatus value + * don't log a no longer relevant FIXME + + -- Pulse-Eight Packaging Thu, 6 Dec 2012 20:58:00 +0100 + libcec (2.0.4-1) unstable; urgency=low * changed: diff --git a/debian/changelog b/debian/changelog index a1ccd68..d284eda 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,24 @@ +libcec (2.0.5-1) unstable; urgency=low + + * changed: + * also try polls at least twice when it failed + * added methods to get the audiostatus and toggle the mute status from the + amplifier (if connected) + * added comboKey and iComboKeyTimeoutMs to libcec_configuration + * force cec_user_control_code_unknown to 0xFF + * fixed: + * check unsupported features properly + * only send an active source message when the stream path changed and we + weren't the active source yet + * don't mark as inactive source on routing changes + * press & hold + * never mark user control opcodes as unsupported + * report our OSD name to the TV, since some TVs don't request it + * initial audiostatus value + * don't log a no longer relevant FIXME + + -- Pulse-Eight Packaging Thu, 6 Dec 2012 20:58:00 +0100 + libcec (2.0.4-1) unstable; urgency=low * changed: diff --git a/include/cec.h b/include/cec.h index c68bba8..0245033 100644 --- a/include/cec.h +++ b/include/cec.h @@ -251,6 +251,7 @@ namespace CEC virtual uint8_t VolumeDown(bool bSendRelease = true) = 0; /*! + * @deprecated Use AudioToggleMute() instead * @brief Sends a mute keypress to an audiosystem if it's present. * @param bSendRelease Send a key release after the keypress. * @return The new audio status. @@ -421,6 +422,30 @@ namespace CEC virtual const char *ToString(const cec_server_version version) = 0; virtual const char *ToString(const cec_user_control_code key) = 0; virtual const char *ToString(const cec_adapter_type type) = 0; + + /*! + * @brief Toggle the mute status of the AVR (if present) + * @return The new audio status. + */ + virtual uint8_t AudioToggleMute(void) = 0; + + /*! + * @brief Mute the AVR (if present) + * @return The new audio status. + */ + virtual uint8_t AudioMute(void) = 0; + + /*! + * @brief Mute the AVR (if connected) + * @return The new audio status. + */ + virtual uint8_t AudioUnmute(void) = 0; + + /*! + * @brief Get the current audio status (if an AVR is connected) + * @return The current audio status, or cec_audio_status if unknown. + */ + virtual uint8_t AudioStatus(void) = 0; }; }; diff --git a/include/cecc.h b/include/cecc.h index a4892c4..2e1f9a8 100644 --- a/include/cecc.h +++ b/include/cecc.h @@ -276,6 +276,14 @@ extern DECLSPEC uint16_t cec_get_adapter_vendor_id(void); extern DECLSPEC uint16_t cec_get_adapter_product_id(void); +extern DECLSPEC uint8_t cec_audio_toggle_mute(void); + +extern DECLSPEC uint8_t cec_audio_mute(void); + +extern DECLSPEC uint8_t cec_audio_unmute(void); + +extern DECLSPEC uint8_t cec_audio_status(void); + #ifdef __cplusplus }; #endif diff --git a/include/cectypes.h b/include/cectypes.h index dfcebfe..e85bcfa 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -264,6 +264,11 @@ namespace CEC { */ #define CEC_FORWARD_STANDBY_MIN_INTERVAL 10000 +/*! + * default timeout in milliseconds for combo keys + */ +#define CEC_DEFAULT_COMBO_TIMEOUT_MS 1000 + /*! * the virtual device path to use for the Raspberry Pi's CEC wire */ @@ -309,6 +314,8 @@ namespace CEC { #define MSGESC 0xFD #define ESCOFFSET 3 +// defines to make compile time checks for certain features easy +#define CEC_FEATURE_CONFIGURABLE_COMBO_KEY 1 typedef enum cec_abort_reason { @@ -691,7 +698,7 @@ typedef enum cec_user_control_code CEC_USER_CONTROL_CODE_AN_RETURN = 0x91, CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST = 0x96, CEC_USER_CONTROL_CODE_MAX = 0x96, - CEC_USER_CONTROL_CODE_UNKNOWN + CEC_USER_CONTROL_CODE_UNKNOWN = 0xFF } cec_user_control_code; typedef enum cec_logical_address @@ -1379,7 +1386,8 @@ typedef enum cec_client_version CEC_CLIENT_VERSION_2_0_2 = 0x2002, CEC_CLIENT_VERSION_2_0_3 = 0x2003, CEC_CLIENT_VERSION_2_0_4 = 0x2004, - CEC_CLIENT_VERSION_CURRENT = 0x2004 + CEC_CLIENT_VERSION_2_0_5 = 0x2005, + CEC_CLIENT_VERSION_CURRENT = 0x2005 } cec_client_version; typedef enum cec_server_version @@ -1406,7 +1414,8 @@ typedef enum cec_server_version CEC_SERVER_VERSION_2_0_2 = 0x2002, CEC_SERVER_VERSION_2_0_3 = 0x2003, CEC_SERVER_VERSION_2_0_4 = 0x2004, - CEC_SERVER_VERSION_CURRENT = 0x2004 + CEC_SERVER_VERSION_2_0_5 = 0x2005, + CEC_SERVER_VERSION_CURRENT = 0x2005 } cec_server_version; struct libcec_configuration @@ -1445,6 +1454,8 @@ struct libcec_configuration cec_version cecVersion; /*!< CEC spec version to use by libCEC. defaults to v1.4. added in 1.8.0 */ cec_adapter_type adapterType; /*!< type of the CEC adapter that we're connected to. added in 1.8.2 */ uint8_t iDoubleTapTimeoutMs; /*!< prevent double taps withing this timeout. defaults to 200ms. added in 2.0.0 */ + cec_user_control_code comboKey; /*!< key code that initiates combo keys. defaults to CEC_USER_CONTROL_CODE_F1_BLUE. CEC_USER_CONTROL_CODE_UNKNOWN to disable. added in 2.0.5 */ + uint32_t iComboKeyTimeoutMs; /*!< timeout until the combo key is sent as normal keypress */ #ifdef __cplusplus libcec_configuration(void) { Clear(); } @@ -1478,7 +1489,9 @@ struct libcec_configuration bMonitorOnly == other.bMonitorOnly && cecVersion == other.cecVersion && adapterType == other.adapterType && - iDoubleTapTimeoutMs == other.iDoubleTapTimeoutMs); + iDoubleTapTimeoutMs == other.iDoubleTapTimeoutMs && + (other.clientVersion <= CEC_CLIENT_VERSION_2_0_4 || comboKey == other.comboKey) && + (other.clientVersion <= CEC_CLIENT_VERSION_2_0_4 || iComboKeyTimeoutMs == other.iComboKeyTimeoutMs)); } bool operator!=(const libcec_configuration &other) const @@ -1495,8 +1508,8 @@ struct libcec_configuration baseDevice = (cec_logical_address)CEC_DEFAULT_BASE_DEVICE; iHDMIPort = CEC_DEFAULT_HDMI_PORT; tvVendor = (uint64_t)CEC_VENDOR_UNKNOWN; - clientVersion = (uint32_t)CEC_CLIENT_VERSION_2_0_0; - serverVersion = (uint32_t)CEC_SERVER_VERSION_2_0_0; + clientVersion = (uint32_t)CEC_CLIENT_VERSION_CURRENT; + serverVersion = (uint32_t)CEC_SERVER_VERSION_CURRENT; bAutodetectAddress = 0; bGetSettingsFromROM = CEC_DEFAULT_SETTING_GET_SETTINGS_FROM_ROM; bUseTVMenuLanguage = CEC_DEFAULT_SETTING_USE_TV_MENU_LANGUAGE; @@ -1513,6 +1526,8 @@ struct libcec_configuration cecVersion = (cec_version)CEC_DEFAULT_SETTING_CEC_VERSION; adapterType = ADAPTERTYPE_UNKNOWN; iDoubleTapTimeoutMs = CEC_DOUBLE_TAP_TIMEOUT_MS; + comboKey = CEC_USER_CONTROL_CODE_STOP; + iComboKeyTimeoutMs = CEC_DEFAULT_COMBO_TIMEOUT_MS; memset(strDeviceName, 0, 13); deviceTypes.Clear(); diff --git a/project/libCEC.nsi b/project/libCEC.nsi index 8f665f2..635df7a 100644 --- a/project/libCEC.nsi +++ b/project/libCEC.nsi @@ -7,7 +7,7 @@ !include "LogicLib.nsh" !include "x64.nsh" -Name "Pulse-Eight libCEC version 2.0.4" +Name "Pulse-Eight libCEC version 2.0.5" OutFile "..\build\libCEC-installer.exe" XPStyle on diff --git a/project/libcec.rc b/project/libcec.rc index 2f70b2f..0b1ebe1 100644 Binary files a/project/libcec.rc and b/project/libcec.rc differ diff --git a/project/testclient.rc b/project/testclient.rc index b2ba0e2..1f44a18 100644 Binary files a/project/testclient.rc and b/project/testclient.rc differ diff --git a/src/CecSharpTester/CecSharpClient.cs b/src/CecSharpTester/CecSharpClient.cs index d1c6c3e..0e8f460 100644 --- a/src/CecSharpTester/CecSharpClient.cs +++ b/src/CecSharpTester/CecSharpClient.cs @@ -43,7 +43,7 @@ namespace CecSharpClient Config = new LibCECConfiguration(); Config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice; Config.DeviceName = "CEC Tester"; - Config.ClientVersion = CecClientVersion.Version2_0_4; + Config.ClientVersion = CecClientVersion.Version2_0_5; Config.SetCallbacks(this); LogLevel = (int)CecLogLevel.All; diff --git a/src/CecSharpTester/Properties/AssemblyInfo.cs b/src/CecSharpTester/Properties/AssemblyInfo.cs index 1270401..d49913b 100644 --- a/src/CecSharpTester/Properties/AssemblyInfo.cs +++ b/src/CecSharpTester/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.4.0")] -[assembly: AssemblyFileVersion("2.0.4.0")] +[assembly: AssemblyVersion("2.0.5.0")] +[assembly: AssemblyFileVersion("2.0.5.0")] diff --git a/src/LibCecSharp/AssemblyInfo.cpp b/src/LibCecSharp/AssemblyInfo.cpp index d5d229f..8e4ecb8 100644 --- a/src/LibCecSharp/AssemblyInfo.cpp +++ b/src/LibCecSharp/AssemblyInfo.cpp @@ -13,7 +13,7 @@ using namespace System::Security::Permissions; [assembly:AssemblyTrademarkAttribute("")]; [assembly:AssemblyCultureAttribute("")]; -[assembly:AssemblyVersionAttribute("2.0.4.0")]; +[assembly:AssemblyVersionAttribute("2.0.5.0")]; [assembly:ComVisible(false)]; [assembly:CLSCompliantAttribute(true)]; diff --git a/src/LibCecSharp/CecSharpTypes.h b/src/LibCecSharp/CecSharpTypes.h index a6fc2d4..a75a762 100644 --- a/src/LibCecSharp/CecSharpTypes.h +++ b/src/LibCecSharp/CecSharpTypes.h @@ -1179,7 +1179,11 @@ namespace CecSharp /// /// v2.0.4 /// - Version2_0_4 = 0x2004 + Version2_0_4 = 0x2004, + /// + /// v2.0.5 + /// + Version2_0_5 = 0x2005 }; /// @@ -1274,7 +1278,11 @@ namespace CecSharp /// /// v2.0.4 /// - Version2_0_4 = 0x2004 + Version2_0_4 = 0x2004, + /// + /// v2.0.5 + /// + Version2_0_5 = 0x2005 }; /// diff --git a/src/LibCecTray/Properties/AssemblyInfo.cs b/src/LibCecTray/Properties/AssemblyInfo.cs index bccd9c7..3f09c27 100644 --- a/src/LibCecTray/Properties/AssemblyInfo.cs +++ b/src/LibCecTray/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.4.0")] -[assembly: AssemblyFileVersion("2.0.4.0")] +[assembly: AssemblyVersion("2.0.5.0")] +[assembly: AssemblyFileVersion("2.0.5.0")] diff --git a/src/LibCecTray/controller/CECController.cs b/src/LibCecTray/controller/CECController.cs index b54ecdd..751330f 100644 --- a/src/LibCecTray/controller/CECController.cs +++ b/src/LibCecTray/controller/CECController.cs @@ -438,7 +438,7 @@ namespace LibCECTray.controller { if (_config == null) { - _config = new LibCECConfiguration { DeviceName = "CEC Tray", ClientVersion = CecClientVersion.Version2_0_4 }; + _config = new LibCECConfiguration { DeviceName = "CEC Tray", ClientVersion = CecClientVersion.Version2_0_5 }; _config.DeviceTypes.Types[0] = CecDeviceType.RecordingDevice; _config.SetCallbacks(this); diff --git a/src/lib/CECClient.cpp b/src/lib/CECClient.cpp index 9d814cd..d069913 100644 --- a/src/lib/CECClient.cpp +++ b/src/lib/CECClient.cpp @@ -47,9 +47,6 @@ using namespace PLATFORM; #define LIB_CEC m_processor->GetLib() #define ToString(x) CCECTypeUtils::ToString(x) -#define COMBO_KEY CEC_USER_CONTROL_CODE_STOP -#define COMBO_TIMEOUT_MS 1000 - CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration &configuration) : m_processor(processor), m_bInitialised(false), @@ -748,6 +745,45 @@ uint8_t CCECClient::SendMuteAudio(void) (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; } +uint8_t CCECClient::AudioToggleMute(void) +{ + CCECBusDevice *device = GetPrimaryDevice(); + CCECAudioSystem *audio = m_processor->GetAudioSystem(); + + return device && audio && audio->IsPresent() ? + audio->MuteAudio(device->GetLogicalAddress()) : + (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t CCECClient::AudioMute(void) +{ + CCECBusDevice *device = GetPrimaryDevice(); + CCECAudioSystem *audio = m_processor->GetAudioSystem(); + uint8_t iStatus = device && audio && audio->IsPresent() ? audio->GetAudioStatus(device->GetLogicalAddress()) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; + if ((iStatus & CEC_AUDIO_MUTE_STATUS_MASK) != CEC_AUDIO_MUTE_STATUS_MASK) + iStatus = audio->MuteAudio(device->GetLogicalAddress()); + + return iStatus; +} + +uint8_t CCECClient::AudioUnmute(void) +{ + CCECBusDevice *device = GetPrimaryDevice(); + CCECAudioSystem *audio = m_processor->GetAudioSystem(); + uint8_t iStatus = device && audio && audio->IsPresent() ? audio->GetAudioStatus(device->GetLogicalAddress()) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; + if ((iStatus & CEC_AUDIO_MUTE_STATUS_MASK) == CEC_AUDIO_MUTE_STATUS_MASK) + iStatus = audio->MuteAudio(device->GetLogicalAddress()); + + return iStatus; +} + +uint8_t CCECClient::AudioStatus(void) +{ + CCECBusDevice *device = GetPrimaryDevice(); + CCECAudioSystem *audio = m_processor->GetAudioSystem(); + return device && audio && audio->IsPresent() ? audio->GetAudioStatus(device->GetLogicalAddress()) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + bool CCECClient::SendKeypress(const cec_logical_address iDestination, const cec_user_control_code key, bool bWait /* = true */) { CCECBusDevice *dest = m_processor->GetDevice(iDestination); @@ -803,6 +839,7 @@ bool CCECClient::GetCurrentConfiguration(libcec_configuration &configuration) bool CCECClient::SetConfiguration(const libcec_configuration &configuration) { + libcec_configuration defaultSettings; bool bIsRunning(m_processor && m_processor->CECInitialised()); CCECBusDevice *primary = bIsRunning ? GetPrimaryDevice() : NULL; uint16_t iPA = primary ? primary->GetCurrentPhysicalAddress() : CEC_INVALID_PHYSICAL_ADDRESS; @@ -838,7 +875,19 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) m_configuration.bMonitorOnly = configuration.bMonitorOnly; m_configuration.cecVersion = configuration.cecVersion; m_configuration.adapterType = configuration.adapterType; - m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE); + m_configuration.iDoubleTapTimeoutMs = configuration.iDoubleTapTimeoutMs; + m_configuration.deviceTypes.Add(configuration.deviceTypes[0]); + + if (m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5) + { + m_configuration.comboKey = configuration.comboKey; + m_configuration.iComboKeyTimeoutMs = configuration.iComboKeyTimeoutMs; + } + else + { + m_configuration.comboKey = defaultSettings.comboKey; + m_configuration.iComboKeyTimeoutMs = defaultSettings.iComboKeyTimeoutMs; + } } bool bNeedReinit(false); @@ -918,7 +967,10 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */) { key.duration = (unsigned int) (GetTimeMs() - m_buttontime); - if (key.duration > COMBO_TIMEOUT_MS || m_iCurrentButton != COMBO_KEY || bSendComboKey) + cec_user_control_code comboKey(m_configuration.comboKey); + uint32_t iTimeoutMs(m_configuration.iComboKeyTimeoutMs); + + if (key.duration > iTimeoutMs || m_iCurrentButton != comboKey || bSendComboKey) { key.keycode = m_iCurrentButton; @@ -937,18 +989,21 @@ void CCECClient::AddKey(bool bSendComboKey /* = false */) void CCECClient::AddKey(const cec_keypress &key) { - // send back the previous key if there is one - AddKey(); - if (key.keycode > CEC_USER_CONTROL_CODE_MAX && key.keycode < CEC_USER_CONTROL_CODE_SELECT) + { + // send back the previous key if there is one + AddKey(); return; + } cec_keypress transmitKey(key); + cec_user_control_code comboKey(m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5 ? + m_configuration.comboKey : CEC_USER_CONTROL_CODE_STOP); { CLockObject lock(m_mutex); - if (m_iCurrentButton == COMBO_KEY && key.duration == 0) + if (m_iCurrentButton == comboKey && key.duration == 0) { // stop + ok -> exit if (key.keycode == CEC_USER_CONTROL_CODE_SELECT) @@ -964,14 +1019,22 @@ void CCECClient::AddKey(const cec_keypress &key) AddKey(true); } - if (key.duration == 0) + if (m_iCurrentButton == key.keycode) + { + m_buttontime = GetTimeMs(); + } + else { - m_iCurrentButton = transmitKey.keycode; - m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs(); + AddKey(); + if (key.duration == 0) + { + m_iCurrentButton = transmitKey.keycode; + m_buttontime = m_iCurrentButton == CEC_USER_CONTROL_CODE_UNKNOWN || key.duration > 0 ? 0 : GetTimeMs(); + } } } - if (key.keycode != COMBO_KEY || key.duration > 0) + if (key.keycode != comboKey || key.duration > 0) { LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %s (%1x)", ToString(transmitKey.keycode), transmitKey.keycode); CallbackAddKey(transmitKey); @@ -995,10 +1058,14 @@ void CCECClient::CheckKeypressTimeout(void) { CLockObject lock(m_mutex); uint64_t iNow = GetTimeMs(); + cec_user_control_code comboKey(m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5 ? + m_configuration.comboKey : CEC_USER_CONTROL_CODE_STOP); + uint32_t iTimeoutMs(m_configuration.clientVersion >= CEC_CLIENT_VERSION_2_0_5 ? + m_configuration.iComboKeyTimeoutMs : CEC_DEFAULT_COMBO_TIMEOUT_MS); if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && - ((m_iCurrentButton == COMBO_KEY && iNow - m_buttontime > COMBO_TIMEOUT_MS) || - (m_iCurrentButton != COMBO_KEY && iNow - m_buttontime > CEC_BUTTON_TIMEOUT))) + ((m_iCurrentButton == comboKey && iNow - m_buttontime > iTimeoutMs) || + (m_iCurrentButton != comboKey && iNow - m_buttontime > CEC_BUTTON_TIMEOUT))) { key.duration = (unsigned int) (iNow - m_buttontime); key.keycode = m_iCurrentButton; diff --git a/src/lib/CECClient.h b/src/lib/CECClient.h index 11a6504..adeaf73 100644 --- a/src/lib/CECClient.h +++ b/src/lib/CECClient.h @@ -152,6 +152,10 @@ namespace CEC virtual uint8_t SendVolumeUp(bool bSendRelease = true); virtual uint8_t SendVolumeDown(bool bSendRelease = true); virtual uint8_t SendMuteAudio(void); + virtual uint8_t AudioToggleMute(void); + virtual uint8_t AudioMute(void); + virtual uint8_t AudioUnmute(void); + virtual uint8_t AudioStatus(void); virtual bool SendKeypress(const cec_logical_address iDestination, const cec_user_control_code key, bool bWait = true); virtual bool SendKeyRelease(const cec_logical_address iDestination, bool bWait = true); virtual cec_osd_name GetDeviceOSDName(const cec_logical_address iAddress); diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index e432033..707b8eb 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -839,6 +839,9 @@ bool CCECProcessor::RegisterClient(CCECClient *client) GetTV()->MarkHandlerReady(); } + // report our OSD name to the TV, since some TVs don't request it + client->GetPrimaryDevice()->TransmitOSDName(CECDEVICE_TV, false); + // request the power status of the TV tv->RequestPowerStatus(sourceAddress, true); diff --git a/src/lib/CECTypeUtils.h b/src/lib/CECTypeUtils.h index 7699b89..b3e209b 100644 --- a/src/lib/CECTypeUtils.h +++ b/src/lib/CECTypeUtils.h @@ -565,6 +565,8 @@ namespace CEC return "2.0.3"; case CEC_CLIENT_VERSION_2_0_4: return "2.0.4"; + case CEC_CLIENT_VERSION_2_0_5: + return "2.0.5"; default: return "Unknown"; } @@ -618,6 +620,8 @@ namespace CEC return "2.0.3"; case CEC_SERVER_VERSION_2_0_4: return "2.0.4"; + case CEC_SERVER_VERSION_2_0_5: + return "2.0.5"; default: return "Unknown"; } diff --git a/src/lib/LibCEC.cpp b/src/lib/LibCEC.cpp index 2cb5b2f..a27ad9d 100644 --- a/src/lib/LibCEC.cpp +++ b/src/lib/LibCEC.cpp @@ -280,6 +280,7 @@ uint8_t CLibCEC::VolumeDown(bool bSendRelease /* = true */) uint8_t CLibCEC::MuteAudio(bool UNUSED(bSendRelease) /* = true */) { + AddLog(CEC_LOG_WARNING, "deprecated function called: %s", __FUNCTION__); return m_client ? m_client->SendMuteAudio() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; } @@ -538,3 +539,23 @@ uint16_t CLibCEC::GetAdapterProductId(void) const { return m_cec && m_cec->IsRunning() ? m_cec->GetAdapterProductId() : 0; } + +uint8_t CLibCEC::AudioToggleMute(void) +{ + return m_client ? m_client->AudioToggleMute() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t CLibCEC::AudioMute(void) +{ + return m_client ? m_client->AudioMute() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t CLibCEC::AudioUnmute(void) +{ + return m_client ? m_client->AudioUnmute() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t CLibCEC::AudioStatus(void) +{ + return m_client ? m_client->AudioStatus() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} diff --git a/src/lib/LibCEC.h b/src/lib/LibCEC.h index 56a112b..f65b818 100644 --- a/src/lib/LibCEC.h +++ b/src/lib/LibCEC.h @@ -132,6 +132,11 @@ namespace CEC uint16_t GetAdapterVendorId(void) const; uint16_t GetAdapterProductId(void) const; + uint8_t AudioToggleMute(void); + uint8_t AudioMute(void); + uint8_t AudioUnmute(void); + uint8_t AudioStatus(void); + CCECProcessor * m_cec; protected: diff --git a/src/lib/LibCECC.cpp b/src/lib/LibCECC.cpp index 153668d..b53dc05 100644 --- a/src/lib/LibCECC.cpp +++ b/src/lib/LibCECC.cpp @@ -388,4 +388,24 @@ uint16_t cec_get_adapter_product_id(void) return cec_parser ? cec_parser->GetAdapterProductId() : 0; } +uint8_t cec_audio_toggle_mute(void) +{ + return cec_parser ? cec_parser->AudioToggleMute() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t cec_audio_mute(void) +{ + return cec_parser ? cec_parser->AudioMute() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t cec_audio_unmute(void) +{ + return cec_parser ? cec_parser->AudioUnmute() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + +uint8_t cec_audio_status(void) +{ + return cec_parser ? cec_parser->AudioStatus() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} + //@} diff --git a/src/lib/adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp b/src/lib/adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp index 4e4c2cb..a9913ab 100644 --- a/src/lib/adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp +++ b/src/lib/adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp @@ -169,10 +169,7 @@ bool CCECAdapterMessageQueueEntry::IsResponse(const CCECAdapterMessage &msg) return thisMsgCode == msgResponse; if (!m_message->IsTranmission()) - { - m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_WARNING, "FIXME! not a transmission: %s", msg.ToString().c_str()); return false; - } return ((msgCode == MSGCODE_COMMAND_ACCEPTED || msgCode == MSGCODE_COMMAND_REJECTED) && (msgResponse == MSGCODE_TRANSMIT_ACK_POLARITY || msgResponse == MSGCODE_TRANSMIT || msgResponse == MSGCODE_TRANSMIT_EOM)) || diff --git a/src/lib/devices/CECAudioSystem.cpp b/src/lib/devices/CECAudioSystem.cpp index add3e6f..1dc2bdc 100644 --- a/src/lib/devices/CECAudioSystem.cpp +++ b/src/lib/devices/CECAudioSystem.cpp @@ -47,7 +47,7 @@ using namespace PLATFORM; CCECAudioSystem::CCECAudioSystem(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress /* = CEC_INVALID_PHYSICAL_ADDRESS */) : CCECBusDevice(processor, address, iPhysicalAddress), m_systemAudioStatus(CEC_SYSTEM_AUDIO_STATUS_ON), - m_audioStatus(CEC_AUDIO_MUTE_STATUS_MASK) + m_audioStatus(CEC_AUDIO_VOLUME_STATUS_UNKNOWN) { m_type = CEC_DEVICE_TYPE_AUDIO_SYSTEM; } @@ -139,6 +139,40 @@ uint8_t CCECAudioSystem::MuteAudio(const cec_logical_address source) TransmitKeypress(source, CEC_USER_CONTROL_CODE_MUTE); TransmitKeyRelease(source); + return GetAudioStatus(source, true); +} + +bool CCECAudioSystem::RequestAudioStatus(const cec_logical_address initiator, bool bWaitForResponse /* = true */) +{ + bool bReturn(false); + + if (!IsHandledByLibCEC() && + !IsUnsupportedFeature(CEC_OPCODE_GIVE_AUDIO_STATUS)) + { + MarkBusy(); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< requesting audio status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress); + bReturn = m_handler->TransmitRequestAudioStatus(initiator, m_iLogicalAddress, bWaitForResponse); + MarkReady(); + } + return bReturn; +} + +uint8_t CCECAudioSystem::GetAudioStatus(const cec_logical_address initiator, bool bUpdate /* = false */) +{ + bool bIsPresent(GetStatus() == CEC_DEVICE_STATUS_PRESENT); + bool bRequestUpdate(false); + { + CLockObject lock(m_mutex); + bRequestUpdate = bIsPresent && + (bUpdate || m_audioStatus == CEC_AUDIO_VOLUME_STATUS_UNKNOWN); + } + + if (bRequestUpdate) + { + CheckVendorIdRequested(initiator); + RequestAudioStatus(initiator); + } + CLockObject lock(m_mutex); return m_audioStatus; } diff --git a/src/lib/devices/CECAudioSystem.h b/src/lib/devices/CECAudioSystem.h index 7950311..8ab055e 100644 --- a/src/lib/devices/CECAudioSystem.h +++ b/src/lib/devices/CECAudioSystem.h @@ -50,10 +50,13 @@ namespace CEC uint8_t VolumeUp(const cec_logical_address source, bool bSendRelease = true); uint8_t VolumeDown(const cec_logical_address source, bool bSendRelease = true); uint8_t MuteAudio(const cec_logical_address source); + uint8_t GetAudioStatus(const cec_logical_address initiator, bool bUpdate = false); bool TransmitActiveSource(void) { return false; } protected: + bool RequestAudioStatus(const cec_logical_address initiator, bool bWaitForResponse = true); + cec_system_audio_status m_systemAudioStatus; uint8_t m_audioStatus; }; diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index 7733cfb..fa063f4 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -227,7 +227,9 @@ void CCECBusDevice::SetUnsupportedFeature(cec_opcode opcode) opcode == CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP || opcode == CEC_OPCODE_ABORT || opcode == CEC_OPCODE_FEATURE_ABORT || - opcode == CEC_OPCODE_NONE) + opcode == CEC_OPCODE_NONE || + opcode == CEC_OPCODE_USER_CONTROL_PRESSED || + opcode == CEC_OPCODE_USER_CONTROL_RELEASE) return; { @@ -1133,21 +1135,7 @@ void CCECBusDevice::SetActiveRoute(uint16_t iRoute) CCECBusDevice* newRoute = m_processor->GetDeviceByPhysicalAddress(iRoute, true); if (newRoute && newRoute->IsHandledByLibCEC()) - { newRoute->ActivateSource(); - return; - } - - CECDEVICEVEC devices; - m_processor->GetDevices()->GetChildrenOf(devices, this); - - for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++) - { - if ((*it)->GetCurrentPhysicalAddress() == iRoute && (*it)->IsHandledByLibCEC()) - (*it)->ActivateSource(); - else if (!CCECTypeUtils::PhysicalAddressIsIncluded(iRoute, (*it)->GetCurrentPhysicalAddress())) - (*it)->MarkAsInactiveSource(); - } } void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /* = CEC_INVALID_PHYSICAL_ADDRESS */) diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index e4a7995..174275c 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -577,7 +577,7 @@ int CCECCommandHandler::HandleSetStreamPath(const cec_command &command) CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamAddress); if (device) { - if (device->IsHandledByLibCEC()) + if (device->IsHandledByLibCEC() && !device->IsActiveSource()) device->ActivateSource(); else device->MarkAsActiveSource(); @@ -898,6 +898,14 @@ bool CCECCommandHandler::TransmitRequestOSDName(const cec_logical_address iIniti return Transmit(command, !bWaitForResponse, false); } +bool CCECCommandHandler::TransmitRequestAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse /* = true */) +{ + cec_command command; + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_AUDIO_STATUS); + + return Transmit(command, !bWaitForResponse, false); +} + bool CCECCommandHandler::TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse /* = true */) { cec_command command; @@ -1142,11 +1150,15 @@ bool CCECCommandHandler::Transmit(cec_command &command, bool bSuppressWait, bool LIB_CEC->AddLog(CEC_LOG_DEBUG, "not sending command '%s': destination device '%s' marked as handled by libCEC", ToString(command.opcode),ToString(command.destination)); return bReturn; } + else if (destinationDevice->IsUnsupportedFeature(command.opcode)) + { + return true; + } } { - uint8_t iTries(0), iMaxTries(!command.opcode_set ? 1 : m_iTransmitRetries + 1); - while (!bReturn && ++iTries <= iMaxTries && !m_busDevice->IsUnsupportedFeature(command.opcode)) + uint8_t iTries(0), iMaxTries(m_iTransmitRetries + 1); + while (!bReturn && ++iTries <= iMaxTries) { if ((bReturn = m_processor->Transmit(command, bIsReply)) == true) { diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index c8430ec..4a8dacb 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -70,6 +70,7 @@ namespace CEC virtual bool TransmitRequestCecVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true); virtual bool TransmitRequestMenuLanguage(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true); virtual bool TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true); + virtual bool TransmitRequestAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true); virtual bool TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true); virtual bool TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true); virtual bool TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true);