diff --git a/packages/mediacenter/xbmc-pvr-theme-Confluence/patches/xbmc-pvr-theme-Confluence-11.0.1-801.04-cec-PR887.patch b/packages/mediacenter/xbmc-pvr-theme-Confluence/patches/xbmc-pvr-theme-Confluence-11.0.1-801.04-cec-PR887.patch new file mode 100644 index 0000000000..ee93a64678 --- /dev/null +++ b/packages/mediacenter/xbmc-pvr-theme-Confluence/patches/xbmc-pvr-theme-Confluence-11.0.1-801.04-cec-PR887.patch @@ -0,0 +1,62 @@ +From 3e1367b680b26123e9e1aa09f8caf2a932d47572 Mon Sep 17 00:00:00 2001 +From: Lars Op den Kamp +Date: Tue, 17 Apr 2012 01:57:43 +0200 +Subject: [PATCH 2/2] cec: libCEC 1.6 support and fixes. libCEC 1.6+ is needed + when using firmware v2 on the CEC adapter, which adds + wake over CEC * added a new setting to control + whether to put the TV in standby when the player is put + in standby. * added some button mappings: all menu + related buttons -> menu, previous channel -> teletext, + added support for the channels list on samsung, mapped + next fav -> menu (when available) * display the + firmware version in the peripheral manager (if + available) * handle the new CEC alert callback + (libCEC 1.6+) * replaced 'Put this PC in standby mode + when the TV is switched off' with an enum that allows + the user to chose between 'Ignore', 'Suspend' and + 'Shutdown' * fixed - crash when changing settings + without libCEC started. * fixed - range of wake and + power-off devices * fixed - update the correct + standby device setting ('standby_devices' not + 'wake_devices') * fixed - don't get the settings from + the eeprom, but always use the settings provided in + xbmc + +--- + .../720p/DialogPeripheralManager.xml | 4 +- + configure.in | 2 +- + language/English/strings.xml | 5 +- + project/BuildDependencies/scripts/libcec_d.txt | 2 +- + system/peripherals.xml | 15 +- + tools/darwin/depends/libcec/Makefile | 2 +- + xbmc/peripherals/bus/PeripheralBus.cpp | 1 + + xbmc/peripherals/devices/Peripheral.h | 2 + + xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 160 ++++++++++++++++---- + xbmc/peripherals/devices/PeripheralCecAdapter.h | 4 + + 10 files changed, 152 insertions(+), 45 deletions(-) + +diff --git a/720p/DialogPeripheralManager.xml b/720p/DialogPeripheralManager.xml +index 07954d0..5717017 100644 +--- a/720p/DialogPeripheralManager.xml ++++ b/720p/DialogPeripheralManager.xml +@@ -117,7 +117,7 @@ + 50 + 520 + 20 +- ++ + left + center + font12 +@@ -173,7 +173,7 @@ + 50 + 520 + 20 +- ++ + left + center + font12 +-- +1.7.5.4 + diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801-cec-PR570.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801-cec-PR570.patch deleted file mode 100644 index 6d3087d8fd..0000000000 --- a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801-cec-PR570.patch +++ /dev/null @@ -1,3265 +0,0 @@ -From d9fce0781e61c46f70f19532b968485ffc70806a Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Thu, 12 Jan 2012 22:16:49 +0100 -Subject: [PATCH 01/18] cec: added volume control on a CEC enabled amplifier - when one is found - ---- - xbmc/Application.cpp | 64 +++++++++ - xbmc/Application.h | 1 + - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 145 ++++++++++++++++++++- - xbmc/peripherals/devices/PeripheralCecAdapter.h | 17 +++ - 4 files changed, 225 insertions(+), 2 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index df7de6e..c09c6d9 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -2583,6 +2583,26 @@ bool CApplication::OnAction(const CAction &action) - // Check for global volume control - if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN)) - { -+ /* try to set the volume on a connected amp */ -+ #ifdef HAVE_LIBCEC -+ vector peripherals; -+ if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) -+ { -+ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) -+ { -+ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); -+ if (cecDevice && cecDevice->HasConnectedAudioSystem()) -+ { -+ if (action.GetID() == ACTION_VOLUME_UP) -+ cecDevice->ScheduleVolumeUp(); -+ else -+ cecDevice->ScheduleVolumeDown(); -+ return true; -+ } -+ } -+ } -+ #endif -+ - if (!m_pPlayer || !m_pPlayer->IsPassthrough()) - { - // increase or decrease the volume -@@ -5027,11 +5047,49 @@ void CApplication::ShowVolumeBar(const CAction *action) - - bool CApplication::IsMuted() const - { -+ /* try to set the mute setting on a connected amp */ -+#ifdef HAVE_LIBCEC -+ vector peripherals; -+ if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) -+ { -+ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) -+ { -+ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); -+ if (cecDevice && cecDevice->HasConnectedAudioSystem()) -+ return false; -+ } -+ } -+#endif - return g_settings.m_bMute; - } - -+bool CApplication::CecMute(void) -+{ -+ /* try to set the mute setting on a connected amp */ -+#ifdef HAVE_LIBCEC -+ vector peripherals; -+ if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) -+ { -+ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) -+ { -+ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); -+ if (cecDevice && cecDevice->HasConnectedAudioSystem()) -+ { -+ cecDevice->ScheduleMute(); -+ return true; -+ } -+ } -+ } -+#endif -+ -+ return false; -+} -+ - void CApplication::ToggleMute(void) - { -+ if (CecMute()) -+ return; -+ - if (g_settings.m_bMute) - UnMute(); - else -@@ -5040,6 +5098,9 @@ void CApplication::ToggleMute(void) - - void CApplication::Mute() - { -+ if (CecMute()) -+ return; -+ - g_settings.m_iPreMuteVolumeLevel = GetVolume(); - SetVolume(0); - g_settings.m_bMute = true; -@@ -5047,6 +5108,9 @@ void CApplication::Mute() - - void CApplication::UnMute() - { -+ if (CecMute()) -+ return; -+ - SetVolume(g_settings.m_iPreMuteVolumeLevel); - g_settings.m_iPreMuteVolumeLevel = 0; - g_settings.m_bMute = false; -diff --git a/xbmc/Application.h b/xbmc/Application.h -index 6e6a005..2fd09aa 100644 ---- a/xbmc/Application.h -+++ b/xbmc/Application.h -@@ -167,6 +167,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs - void SetVolume(long iValue, bool isPercentage = true); - bool IsMuted() const; - void ToggleMute(void); -+ bool CecMute(void); - void ShowVolumeBar(const CAction *action = NULL); - int GetPlaySpeed() const; - int GetSubtitleDelay() const; -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index b169c5c..88477df 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -31,6 +31,7 @@ - #include "peripherals/Peripherals.h" - #include "peripherals/bus/PeripheralBus.h" - #include "settings/GUISettings.h" -+#include "settings/Settings.h" - #include "utils/log.h" - - #include -@@ -43,6 +44,8 @@ - - /* time in seconds to ignore standby commands from devices after the screensaver has been activated */ - #define SCREENSAVER_TIMEOUT 10 -+#define VOLUME_CHANGE_TIMEOUT 250 -+#define VOLUME_REFRESH_TIMEOUT 100 - - class DllLibCECInterface - { -@@ -72,7 +75,8 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface - m_bHasButton(false), - m_bIsReady(false), - m_strMenuLanguage("???"), -- m_lastKeypress(0) -+ m_lastKeypress(0), -+ m_lastChange(VOLUME_CHANGE_NONE) - { - m_button.iButton = 0; - m_button.iDuration = 0; -@@ -273,8 +277,24 @@ void CPeripheralCecAdapter::Process(void) - SetMenuLanguage(language.language); - } - -+ CStdString strNotification; -+ cec_osd_name tvName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); -+ strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name); -+ -+ /* disable the mute setting when an amp is found, because the amp handles the mute setting and -+ set PCM output to 100% */ -+ if (HasConnectedAudioSystem()) -+ { -+ cec_osd_name ampName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); -+ CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); -+ strNotification.AppendFormat(" - %s", ampName.name); -+ -+ g_settings.m_bMute = false; -+ g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; -+ } -+ - m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); -- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(36016)); -+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); - - while (!m_bStop) - { -@@ -282,6 +302,8 @@ void CPeripheralCecAdapter::Process(void) - if (!m_bStop) - ProcessNextCommand(); - if (!m_bStop) -+ ProcessVolumeChange(); -+ if (!m_bStop) - Sleep(5); - } - -@@ -343,6 +365,125 @@ bool CPeripheralCecAdapter::SetHdmiPort(int iHdmiPort) - return bReturn; - } - -+bool CPeripheralCecAdapter::HasConnectedAudioSystem(void) -+{ -+ return m_cecAdapter && m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM); -+} -+ -+void CPeripheralCecAdapter::ScheduleVolumeUp(void) -+{ -+ { -+ CSingleLock lock(m_critSection); -+ m_volumeChangeQueue.push(VOLUME_CHANGE_UP); -+ } -+ Sleep(5); -+} -+ -+void CPeripheralCecAdapter::ScheduleVolumeDown(void) -+{ -+ { -+ CSingleLock lock(m_critSection); -+ m_volumeChangeQueue.push(VOLUME_CHANGE_DOWN); -+ } -+ Sleep(5); -+} -+ -+void CPeripheralCecAdapter::ScheduleMute(void) -+{ -+ { -+ CSingleLock lock(m_critSection); -+ m_volumeChangeQueue.push(VOLUME_CHANGE_MUTE); -+ } -+ Sleep(5); -+} -+ -+void CPeripheralCecAdapter::ProcessVolumeChange(void) -+{ -+ bool bSendRelease(false); -+ CecVolumeChange pendingVolumeChange = VOLUME_CHANGE_NONE; -+ { -+ CSingleLock lock(m_critSection); -+ if (m_volumeChangeQueue.size() > 0) -+ { -+ /* get the first change from the queue */ -+ pendingVolumeChange = m_volumeChangeQueue.front(); -+ m_volumeChangeQueue.pop(); -+ -+ /* remove all dupe entries */ -+ while (m_volumeChangeQueue.size() > 0 && m_volumeChangeQueue.front() == pendingVolumeChange) -+ m_volumeChangeQueue.pop(); -+ -+ /* send another keypress after VOLUME_REFRESH_TIMEOUT ms */ -+ bool bRefresh(m_lastKeypress + VOLUME_REFRESH_TIMEOUT < XbmcThreads::SystemClockMillis()); -+ -+ /* only send the keypress when it hasn't been sent yet */ -+ if (pendingVolumeChange != m_lastChange) -+ { -+ m_lastKeypress = XbmcThreads::SystemClockMillis(); -+ m_lastChange = pendingVolumeChange; -+ } -+ else if (bRefresh) -+ { -+ m_lastKeypress = XbmcThreads::SystemClockMillis(); -+ pendingVolumeChange = m_lastChange; -+ } -+ else -+ pendingVolumeChange = VOLUME_CHANGE_NONE; -+ } -+ else if (m_lastKeypress > 0 && m_lastKeypress + VOLUME_CHANGE_TIMEOUT < XbmcThreads::SystemClockMillis()) -+ { -+ /* send a key release */ -+ m_lastKeypress = 0; -+ bSendRelease = true; -+ m_lastChange = VOLUME_CHANGE_NONE; -+ } -+ } -+ -+ switch (pendingVolumeChange) -+ { -+ case VOLUME_CHANGE_UP: -+ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_VOLUME_UP, false); -+ break; -+ case VOLUME_CHANGE_DOWN: -+ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_VOLUME_DOWN, false); -+ break; -+ case VOLUME_CHANGE_MUTE: -+ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_MUTE, false); -+ break; -+ case VOLUME_CHANGE_NONE: -+ if (bSendRelease) -+ m_cecAdapter->SendKeyRelease(CECDEVICE_AUDIOSYSTEM, false); -+ break; -+ } -+} -+ -+void CPeripheralCecAdapter::VolumeUp(void) -+{ -+ if (HasConnectedAudioSystem()) -+ { -+ CSingleLock lock(m_critSection); -+ m_volumeChangeQueue.push(VOLUME_CHANGE_UP); -+ } -+} -+ -+void CPeripheralCecAdapter::VolumeDown(void) -+{ -+ if (HasConnectedAudioSystem()) -+ { -+ CSingleLock lock(m_critSection); -+ m_volumeChangeQueue.push(VOLUME_CHANGE_DOWN); -+ } -+} -+ -+void CPeripheralCecAdapter::Mute(void) -+{ -+ if (HasConnectedAudioSystem()) -+ { -+ CSingleLock lock(m_critSection); -+ m_volumeChangeQueue.push(VOLUME_CHANGE_MUTE); -+ } -+} -+ - void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage) - { - if (m_strMenuLanguage.Equals(strLanguage)) -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index 2fcbb1d..e1e302d 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -49,6 +49,13 @@ - unsigned int iDuration; - } CecButtonPress; - -+ typedef enum -+ { -+ VOLUME_CHANGE_NONE, -+ VOLUME_CHANGE_UP, -+ VOLUME_CHANGE_DOWN, -+ VOLUME_CHANGE_MUTE -+ } CecVolumeChange; - - class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread - { -@@ -59,6 +66,13 @@ - virtual void Announce(ANNOUNCEMENT::EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); - virtual bool PowerOnCecDevices(CEC::cec_logical_address iLogicalAddress); - virtual bool StandbyCecDevices(CEC::cec_logical_address iLogicalAddress); -+ virtual bool HasConnectedAudioSystem(void); -+ virtual void ScheduleVolumeUp(void); -+ virtual void VolumeUp(void); -+ virtual void ScheduleVolumeDown(void); -+ virtual void VolumeDown(void); -+ virtual void ScheduleMute(void); -+ virtual void Mute(void); - - virtual bool SendPing(void); - virtual bool SetHdmiPort(int iHdmiPort); -@@ -77,6 +91,7 @@ - virtual bool InitialiseFeature(const PeripheralFeature feature); - virtual void Process(void); - virtual void ProcessNextCommand(void); -+ virtual void ProcessVolumeChange(void); - virtual void SetMenuLanguage(const char *strLanguage); - static bool FindConfigLocation(CStdString &strString); - static bool TranslateComPort(CStdString &strPort); -@@ -90,7 +105,9 @@ - CDateTime m_screensaverLastActivated; - CecButtonPress m_button; - std::queue m_buttonQueue; -+ std::queue m_volumeChangeQueue; - unsigned int m_lastKeypress; -+ CecVolumeChange m_lastChange; - CCriticalSection m_critSection; - }; - } --- -1.7.5.4 - - -From abc71c1114a9f493ba89e5346e5c0749338ff0d3 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Thu, 12 Jan 2012 22:18:31 +0100 -Subject: [PATCH 02/18] cec: set the HDMI port and the device to which the CEC - adapter was connected, to be able to determine the - correct physical address. this is a work around, - until the CEC adapter's firmware supports physical - address detection, but is needed for people who have - connected XBMC to something else than the TV - ---- - language/Dutch/strings.xml | 3 ++- - language/English/strings.xml | 1 + - system/peripherals.xml | 1 + - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 13 +++++++------ - xbmc/peripherals/devices/PeripheralCecAdapter.h | 2 +- - 5 files changed, 12 insertions(+), 8 deletions(-) - -diff --git a/language/Dutch/strings.xml b/language/Dutch/strings.xml -index f1e3419..fd86371 100644 -\ No newline at end of file -diff --git a/language/English/strings.xml b/language/English/strings.xml -index ca2ac4d..fb5b8fb 100644 ---- a/language/English/strings.xml -+++ b/language/English/strings.xml -@@ -2404,4 +2404,5 @@ - Connected - Adapter found, but libcec is not available - Use the TV's language setting -+ Connected to HDMI device - -diff --git a/system/peripherals.xml b/system/peripherals.xml -index f5cf50d..94b9d85 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -18,5 +18,6 @@ - - - -+ - - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 88477df..6f7e1f5 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -239,8 +239,9 @@ void CPeripheralCecAdapter::Process(void) - return; - - // set correct physical address from peripheral settings -+ int iDevice = GetSettingInt("connected_device"); - int iHdmiPort = GetSettingInt("cec_hdmi_port"); -- SetHdmiPort(iHdmiPort); -+ m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort); - FlushLog(); - - // open the CEC adapter -@@ -351,15 +352,15 @@ bool CPeripheralCecAdapter::SendPing(void) - return bReturn; - } - --bool CPeripheralCecAdapter::SetHdmiPort(int iHdmiPort) -+bool CPeripheralCecAdapter::SetHdmiPort(int iDevice, int iHdmiPort) - { - bool bReturn(false); - if (m_cecAdapter && m_bIsReady) - { - if (iHdmiPort <= 0 || iHdmiPort > 16) - iHdmiPort = 1; -- CLog::Log(LOGDEBUG, "%s - changing active HDMI port to %d", __FUNCTION__, iHdmiPort); -- bReturn = m_cecAdapter->SetPhysicalAddress(iHdmiPort << 12); -+ CLog::Log(LOGDEBUG, "%s - changing active HDMI port to %d on device %d", __FUNCTION__, iHdmiPort, iDevice); -+ bReturn = m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort); - } - - return bReturn; -@@ -867,9 +868,9 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting - else if (bEnabled && !m_cecAdapter && m_bStarted) - InitialiseFeature(FEATURE_CEC); - } -- else if (strChangedSetting.Equals("cec_hdmi_port")) -+ else if (strChangedSetting.Equals("connected_device") || strChangedSetting.Equals("cec_hdmi_port")) - { -- SetHdmiPort(GetSettingInt("cec_hdmi_port")); -+ SetHdmiPort(GetSettingInt("connected_device"), GetSettingInt("cec_hdmi_port")); - } - } - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index e1e302d..768e38a 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -75,7 +75,7 @@ - virtual void Mute(void); - - virtual bool SendPing(void); -- virtual bool SetHdmiPort(int iHdmiPort); -+ virtual bool SetHdmiPort(int iDevice, int iHdmiPort); - - virtual void OnSettingChanged(const CStdString &strChangedSetting); - --- -1.7.5.4 - - -From 7ec1b7548f84b663ea6952d9952a90812ec523fb Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Tue, 3 Jan 2012 20:40:19 +0100 -Subject: [PATCH 03/18] cec: also mark XBMC as active source when powering up - devices - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 6f7e1f5..bc04f58 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -268,6 +268,7 @@ void CPeripheralCecAdapter::Process(void) - if (GetSettingBool("cec_power_on_startup")) - { - PowerOnCecDevices(CECDEVICE_TV); -+ m_cecAdapter->SetActiveSource(); - FlushLog(); - } - --- -1.7.5.4 - - -From 4eb02842120d960c78c95b67898bb3166b789259 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Wed, 11 Jan 2012 00:09:02 +0100 -Subject: [PATCH 04/18] cec: some TVs don't like us querying it while - activating sources. moved the queries to a background - thread, and only query after the TV reports power - state active. - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 102 +++++++++++++++------ - xbmc/peripherals/devices/PeripheralCecAdapter.h | 46 +++++++--- - 2 files changed, 108 insertions(+), 40 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index bc04f58..97cb1d8 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -261,9 +261,8 @@ void CPeripheralCecAdapter::Process(void) - return; - } - -+ CAnnouncementManager::AddAnnouncer(m_cecAdapter); - CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); -- m_bIsReady = true; -- CAnnouncementManager::AddAnnouncer(this); - - if (GetSettingBool("cec_power_on_startup")) - { -@@ -272,31 +271,8 @@ void CPeripheralCecAdapter::Process(void) - FlushLog(); - } - -- if (GetSettingBool("use_tv_menu_language")) -- { -- cec_menu_language language; -- if (m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) -- SetMenuLanguage(language.language); -- } -- -- CStdString strNotification; -- cec_osd_name tvName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); -- strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name); -- -- /* disable the mute setting when an amp is found, because the amp handles the mute setting and -- set PCM output to 100% */ -- if (HasConnectedAudioSystem()) -- { -- cec_osd_name ampName = m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); -- CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); -- strNotification.AppendFormat(" - %s", ampName.name); -- -- g_settings.m_bMute = false; -- g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; -- } -- -- m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); -- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); -+ m_queryThread = new CPeripheralCecAdapterQueryThread(this); -+ m_queryThread->Create(false); - - while (!m_bStop) - { -@@ -305,10 +281,12 @@ void CPeripheralCecAdapter::Process(void) - ProcessNextCommand(); - if (!m_bStop) - ProcessVolumeChange(); -+ - if (!m_bStop) - Sleep(5); - } - -+ delete m_queryThread; - m_cecAdapter->Close(); - - CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__); -@@ -610,6 +588,15 @@ void CPeripheralCecAdapter::ProcessNextCommand(void) - } - } - break; -+ case CEC_OPCODE_REPORT_POWER_STATUS: -+ if (command.initiator == CECDEVICE_TV && -+ command.parameters.size == 1 && -+ command.parameters[0] == CEC_POWER_STATUS_ON && -+ m_queryThread) -+ { -+ m_queryThread->Signal(); -+ } -+ break; - default: - break; - } -@@ -917,4 +904,65 @@ bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation) - - return false; - } -+ -+CPeripheralCecAdapterQueryThread::CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter) : -+ CThread("CEC Adapter Query Thread"), -+ m_adapter(adapter) -+{ -+ m_event.Reset(); -+} -+ -+CPeripheralCecAdapterQueryThread::~CPeripheralCecAdapterQueryThread(void) -+{ -+ m_event.Set(); -+ StopThread(true); -+} -+ -+void CPeripheralCecAdapterQueryThread::Signal(void) -+{ -+ m_event.Set(); -+} -+ -+void CPeripheralCecAdapterQueryThread::Process(void) -+{ -+ bool bContinue(false); -+ do -+ { -+ m_event.WaitMSec(5000); -+ if (m_adapter->m_bStop) -+ return; -+ -+ if (m_adapter->m_cecAdapter->GetDevicePowerStatus(CECDEVICE_TV) == CEC_POWER_STATUS_ON) -+ bContinue = true; -+ }while(!bContinue); -+ -+ if (m_adapter->GetSettingBool("use_tv_menu_language")) -+ { -+ cec_menu_language language; -+ if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) -+ m_adapter->SetMenuLanguage(language.language); -+ } -+ -+ CStdString strNotification; -+ cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); -+ strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name); -+ -+ /* disable the mute setting when an amp is found, because the amp handles the mute setting and -+ set PCM output to 100% */ -+ if (m_adapter->HasConnectedAudioSystem()) -+ { -+ cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); -+ CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); -+ strNotification.AppendFormat(" - %s", ampName.name); -+ -+ g_settings.m_bMute = false; -+ g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; -+ } -+ -+ m_adapter->m_bIsReady = true; -+ -+ m_adapter->m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); -+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); -+} -+ - #endif -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index 768e38a..f10f2ea 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -43,6 +43,8 @@ - - namespace PERIPHERALS - { -+ class CPeripheralCecAdapterQueryThread; -+ - typedef struct - { - WORD iButton; -@@ -59,6 +61,8 @@ - - class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread - { -+ friend class CPeripheralCecAdapterQueryThread; -+ - public: - CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); - virtual ~CPeripheralCecAdapter(void); -@@ -96,19 +100,35 @@ - static bool FindConfigLocation(CStdString &strString); - static bool TranslateComPort(CStdString &strPort); - -- DllLibCEC* m_dll; -- CEC::ICECAdapter* m_cecAdapter; -- bool m_bStarted; -- bool m_bHasButton; -- bool m_bIsReady; -- CStdString m_strMenuLanguage; -- CDateTime m_screensaverLastActivated; -- CecButtonPress m_button; -- std::queue m_buttonQueue; -- std::queue m_volumeChangeQueue; -- unsigned int m_lastKeypress; -- CecVolumeChange m_lastChange; -- CCriticalSection m_critSection; -+ DllLibCEC* m_dll; -+ CEC::ICECAdapter* m_cecAdapter; -+ bool m_bStarted; -+ bool m_bHasButton; -+ bool m_bIsReady; -+ CStdString m_strMenuLanguage; -+ CDateTime m_screensaverLastActivated; -+ CecButtonPress m_button; -+ std::queue m_buttonQueue; -+ std::queue m_volumeChangeQueue; -+ unsigned int m_lastKeypress; -+ CecVolumeChange m_lastChange; -+ CPeripheralCecAdapterQueryThread *m_queryThread; -+ CCriticalSection m_critSection; -+ }; -+ -+ class CPeripheralCecAdapterQueryThread : public CThread -+ { -+ public: -+ CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter); -+ virtual ~CPeripheralCecAdapterQueryThread(void); -+ -+ virtual void Signal(void); -+ -+ protected: -+ virtual void Process(void); -+ -+ CPeripheralCecAdapter *m_adapter; -+ CEvent m_event; - }; - } - --- -1.7.5.4 - - -From 2ccef5513bec1a5ddfe50470a7f1aee30d5b509d Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Thu, 12 Jan 2012 22:22:17 +0100 -Subject: [PATCH 05/18] cec: use callback methods instead of constant polling. - this requires libCEC 1.4.0 or higher - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 123 ++++++++++++--------- - xbmc/peripherals/devices/PeripheralCecAdapter.h | 10 +- - 2 files changed, 76 insertions(+), 57 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 97cb1d8..0565836 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -121,7 +121,6 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface - - if (m_dll && m_cecAdapter) - { -- FlushLog(); - m_dll->CECDestroy(m_cecAdapter); - m_cecAdapter = NULL; - delete m_dll; -@@ -170,7 +169,6 @@ void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, - if (!m_cecAdapter->Open(strPort.c_str(), 10000)) - { - CLog::Log(LOGERROR, "%s - failed to reconnect to the CEC adapter", __FUNCTION__); -- FlushLog(); - m_bStop = true; - } - else -@@ -238,11 +236,12 @@ void CPeripheralCecAdapter::Process(void) - if (strPort.empty()) - return; - -+ EnableCallbacks(); -+ - // set correct physical address from peripheral settings - int iDevice = GetSettingInt("connected_device"); - int iHdmiPort = GetSettingInt("cec_hdmi_port"); - m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort); -- FlushLog(); - - // open the CEC adapter - CLog::Log(LOGDEBUG, "%s - opening a connection to the CEC adapter: %s", __FUNCTION__, strPort.c_str()); -@@ -254,21 +253,19 @@ void CPeripheralCecAdapter::Process(void) - - if (!m_cecAdapter->Open(strPort.c_str(), 10000)) - { -- FlushLog(); - CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__); - CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); - m_bStarted = false; - return; - } - -- CAnnouncementManager::AddAnnouncer(m_cecAdapter); -+ CAnnouncementManager::AddAnnouncer(this); - CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); - - if (GetSettingBool("cec_power_on_startup")) - { - PowerOnCecDevices(CECDEVICE_TV); - m_cecAdapter->SetActiveSource(); -- FlushLog(); - } - - m_queryThread = new CPeripheralCecAdapterQueryThread(this); -@@ -276,9 +273,6 @@ void CPeripheralCecAdapter::Process(void) - - while (!m_bStop) - { -- FlushLog(); -- if (!m_bStop) -- ProcessNextCommand(); - if (!m_bStop) - ProcessVolumeChange(); - -@@ -525,10 +519,13 @@ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage) - CLog::Log(LOGWARNING, "%s - TV menu language set to unknown value '%s'", __FUNCTION__, strLanguage); - } - --void CPeripheralCecAdapter::ProcessNextCommand(void) -+int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command) - { -- cec_command command; -- if (m_cecAdapter && m_bIsReady && m_cecAdapter->GetNextCommand(&command)) -+ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; -+ if (!adapter) -+ return 0; -+ -+ if (adapter->m_bIsReady) - { - CLog::Log(LOGDEBUG, "%s - processing command: initiator=%1x destination=%1x opcode=%02x", __FUNCTION__, command.initiator, command.destination, command.opcode); - -@@ -537,21 +534,21 @@ void CPeripheralCecAdapter::ProcessNextCommand(void) - case CEC_OPCODE_STANDBY: - /* a device was put in standby mode */ - CLog::Log(LOGDEBUG, "%s - device %1x was put in standby mode", __FUNCTION__, command.initiator); -- if (command.initiator == CECDEVICE_TV && GetSettingBool("standby_pc_on_tv_standby") && -- (!m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT))) -+ if (command.initiator == CECDEVICE_TV && adapter->GetSettingBool("standby_pc_on_tv_standby") && -+ (!adapter->m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT))) - { -- m_bStarted = false; -+ adapter->m_bStarted = false; - g_application.getApplicationMessenger().Suspend(); - } - break; - case CEC_OPCODE_SET_MENU_LANGUAGE: -- if (GetSettingBool("use_tv_menu_language") && command.initiator == CECDEVICE_TV && command.parameters.size == 3) -+ if (adapter->GetSettingBool("use_tv_menu_language") && command.initiator == CECDEVICE_TV && command.parameters.size == 3) - { - char strNewLanguage[4]; - for (int iPtr = 0; iPtr < 3; iPtr++) - strNewLanguage[iPtr] = command.parameters[iPtr]; - strNewLanguage[3] = 0; -- SetMenuLanguage(strNewLanguage); -+ adapter->SetMenuLanguage(strNewLanguage); - } - break; - case CEC_OPCODE_DECK_CONTROL: -@@ -559,11 +556,11 @@ void CPeripheralCecAdapter::ProcessNextCommand(void) - command.parameters.size == 1 && - command.parameters[0] == CEC_DECK_CONTROL_MODE_STOP) - { -- CSingleLock lock(m_critSection); -+ CSingleLock lock(adapter->m_critSection); - cec_keypress key; - key.duration = 500; - key.keycode = CEC_USER_CONTROL_CODE_STOP; -- m_buttonQueue.push(key); -+ adapter->m_buttonQueue.push(key); - } - break; - case CEC_OPCODE_PLAY: -@@ -572,19 +569,19 @@ void CPeripheralCecAdapter::ProcessNextCommand(void) - { - if (command.parameters[0] == CEC_PLAY_MODE_PLAY_FORWARD) - { -- CSingleLock lock(m_critSection); -+ CSingleLock lock(adapter->m_critSection); - cec_keypress key; - key.duration = 500; - key.keycode = CEC_USER_CONTROL_CODE_PLAY; -- m_buttonQueue.push(key); -+ adapter->m_buttonQueue.push(key); - } - else if (command.parameters[0] == CEC_PLAY_MODE_PLAY_STILL) - { -- CSingleLock lock(m_critSection); -+ CSingleLock lock(adapter->m_critSection); - cec_keypress key; - key.duration = 500; - key.keycode = CEC_USER_CONTROL_CODE_PAUSE; -- m_buttonQueue.push(key); -+ adapter->m_buttonQueue.push(key); - } - } - break; -@@ -592,15 +589,27 @@ void CPeripheralCecAdapter::ProcessNextCommand(void) - if (command.initiator == CECDEVICE_TV && - command.parameters.size == 1 && - command.parameters[0] == CEC_POWER_STATUS_ON && -- m_queryThread) -+ adapter->m_queryThread) - { -- m_queryThread->Signal(); -+ adapter->m_queryThread->Signal(); - } - break; - default: - break; - } - } -+ return 1; -+} -+ -+int CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress &key) -+{ -+ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; -+ if (!adapter) -+ return 0; -+ -+ CSingleLock lock(adapter->m_critSection); -+ adapter->m_buttonQueue.push(key); -+ return 1; - } - - bool CPeripheralCecAdapter::GetNextCecKey(cec_keypress &key) -@@ -613,10 +622,6 @@ bool CPeripheralCecAdapter::GetNextCecKey(cec_keypress &key) - m_buttonQueue.pop(); - bReturn = true; - } -- else if (m_cecAdapter->GetNextKeypress(&key)) -- { -- bReturn = true; -- } - - return bReturn; - } -@@ -862,35 +867,37 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting - } - } - --void CPeripheralCecAdapter::FlushLog(void) -+int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message &message) - { -- cec_log_message message; -- while (m_cecAdapter && m_cecAdapter->GetNextLogMessage(&message)) -+ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; -+ if (!adapter) -+ return 0; -+ -+ int iLevel = -1; -+ switch (message.level) - { -- int iLevel = -1; -- switch (message.level) -- { -- case CEC_LOG_ERROR: -- iLevel = LOGERROR; -- break; -- case CEC_LOG_WARNING: -- iLevel = LOGWARNING; -- break; -- case CEC_LOG_NOTICE: -+ case CEC_LOG_ERROR: -+ iLevel = LOGERROR; -+ break; -+ case CEC_LOG_WARNING: -+ iLevel = LOGWARNING; -+ break; -+ case CEC_LOG_NOTICE: -+ iLevel = LOGDEBUG; -+ break; -+ case CEC_LOG_TRAFFIC: -+ case CEC_LOG_DEBUG: -+ if (adapter->GetSettingBool("cec_debug_logging")) - iLevel = LOGDEBUG; -- break; -- case CEC_LOG_TRAFFIC: -- case CEC_LOG_DEBUG: -- if (GetSettingBool("cec_debug_logging")) -- iLevel = LOGDEBUG; -- break; -- default: -- break; -- } -- -- if (iLevel >= 0) -- CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message); -+ break; -+ default: -+ break; - } -+ -+ if (iLevel >= 0) -+ CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message); -+ -+ return 1; - } - - bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation) -@@ -965,4 +972,12 @@ void CPeripheralCecAdapterQueryThread::Process(void) - CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); - } - -+void CPeripheralCecAdapter::EnableCallbacks(void) -+{ -+ m_callbacks.CBCecLogMessage = &CecLogMessage; -+ m_callbacks.CBCecKeyPress = &CecKeyPress; -+ m_callbacks.CBCecCommand = &CecCommand; -+ m_cecAdapter->EnableCallbacks(this, &m_callbacks); -+} -+ - #endif -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index f10f2ea..085b683 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -89,12 +89,15 @@ - virtual CStdString GetComPort(void); - - protected: -- virtual void FlushLog(void); -- virtual bool GetNextCecKey(CEC::cec_keypress &key); -+ virtual void EnableCallbacks(void); -+ static int CecKeyPress(void *cbParam, const CEC::cec_keypress &key); -+ static int CecLogMessage(void *cbParam, const CEC::cec_log_message &message); -+ static int CecCommand(void *cbParam, const CEC::cec_command &command); -+ - virtual bool GetNextKey(void); -+ virtual bool GetNextCecKey(CEC::cec_keypress &key); - virtual bool InitialiseFeature(const PeripheralFeature feature); - virtual void Process(void); -- virtual void ProcessNextCommand(void); - virtual void ProcessVolumeChange(void); - virtual void SetMenuLanguage(const char *strLanguage); - static bool FindConfigLocation(CStdString &strString); -@@ -113,6 +116,7 @@ - unsigned int m_lastKeypress; - CecVolumeChange m_lastChange; - CPeripheralCecAdapterQueryThread *m_queryThread; -+ CEC::ICECCallbacks m_callbacks; - CCriticalSection m_critSection; - }; - --- -1.7.5.4 - - -From 19e321b92bd480bcd6028c093071ae248f52dfab Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Wed, 25 Jan 2012 16:11:57 +0100 -Subject: [PATCH 06/18] cec: only send an inactive source messages when not - sending a power off command, or AVR devices will - power up again - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 0565836..867085b 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -132,9 +132,10 @@ void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, - { - if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit") && m_bIsReady) - { -- m_cecAdapter->SetInactiveView(); - if (GetSettingBool("cec_power_off_shutdown")) - m_cecAdapter->StandbyDevices(); -+ else -+ m_cecAdapter->SetInactiveView(); - } - else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && GetSettingBool("cec_standby_screensaver") && m_bIsReady) - { --- -1.7.5.4 - - -From e41eab29179fb54d82b429c9a17f4b4c9f3529a1 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Wed, 25 Jan 2012 16:31:14 +0100 -Subject: [PATCH 07/18] cec: removed the cec_debug_logging setting. always - show cec debug logging when debugging in XBMC is - enabled - ---- - system/peripherals.xml | 1 - - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 3 +-- - 2 files changed, 1 insertions(+), 3 deletions(-) - -diff --git a/system/peripherals.xml b/system/peripherals.xml -index 94b9d85..72042ec 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -16,7 +16,6 @@ - - - -- - - - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 867085b..b42e064 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -888,8 +888,7 @@ int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message &m - break; - case CEC_LOG_TRAFFIC: - case CEC_LOG_DEBUG: -- if (adapter->GetSettingBool("cec_debug_logging")) -- iLevel = LOGDEBUG; -+ iLevel = LOGDEBUG; - break; - default: - break; --- -1.7.5.4 - - -From 46c0c583637744c4b8c52c6c450dbf29c9998362 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Sun, 29 Jan 2012 19:06:24 +0100 -Subject: [PATCH 08/18] cec: don't call libCEC directly from the GUI thread - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 13 +++++++++++-- - xbmc/peripherals/devices/PeripheralCecAdapter.h | 2 ++ - 2 files changed, 13 insertions(+), 2 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index b42e064..a686def 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -74,6 +74,7 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface - m_bStarted(false), - m_bHasButton(false), - m_bIsReady(false), -+ m_bHasConnectedAudioSystem(false), - m_strMenuLanguage("???"), - m_lastKeypress(0), - m_lastChange(VOLUME_CHANGE_NONE) -@@ -342,7 +343,14 @@ bool CPeripheralCecAdapter::SetHdmiPort(int iDevice, int iHdmiPort) - - bool CPeripheralCecAdapter::HasConnectedAudioSystem(void) - { -- return m_cecAdapter && m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM); -+ CSingleLock lock(m_critSection); -+ return m_bHasConnectedAudioSystem; -+} -+ -+void CPeripheralCecAdapter::SetAudioSystemConnected(bool bSetTo) -+{ -+ CSingleLock lock(m_critSection); -+ m_bHasConnectedAudioSystem = bSetTo; - } - - void CPeripheralCecAdapter::ScheduleVolumeUp(void) -@@ -956,12 +964,13 @@ void CPeripheralCecAdapterQueryThread::Process(void) - - /* disable the mute setting when an amp is found, because the amp handles the mute setting and - set PCM output to 100% */ -- if (m_adapter->HasConnectedAudioSystem()) -+ if (m_adapter->m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM)) - { - cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); - CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); - strNotification.AppendFormat(" - %s", ampName.name); - -+ m_adapter->SetAudioSystemConnected(true); - g_settings.m_bMute = false; - g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; - } -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index 085b683..54eef5f 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -71,6 +71,7 @@ - virtual bool PowerOnCecDevices(CEC::cec_logical_address iLogicalAddress); - virtual bool StandbyCecDevices(CEC::cec_logical_address iLogicalAddress); - virtual bool HasConnectedAudioSystem(void); -+ virtual void SetAudioSystemConnected(bool bSetTo); - virtual void ScheduleVolumeUp(void); - virtual void VolumeUp(void); - virtual void ScheduleVolumeDown(void); -@@ -108,6 +109,7 @@ - bool m_bStarted; - bool m_bHasButton; - bool m_bIsReady; -+ bool m_bHasConnectedAudioSystem; - CStdString m_strMenuLanguage; - CDateTime m_screensaverLastActivated; - CecButtonPress m_button; --- -1.7.5.4 - - -From cd3e1b4dfc7296332b4272ceac9a871796a5927c Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Thu, 26 Jan 2012 21:28:53 +0100 -Subject: [PATCH 09/18] peripherals: added an optional order to settings - ---- - system/peripherals.xml | 28 ++++++++++---------- - xbmc/peripherals/Peripherals.cpp | 23 ++++++++++++++++ - xbmc/peripherals/devices/Peripheral.cpp | 25 +++++++++++++++--- - xbmc/peripherals/devices/Peripheral.h | 2 + - .../dialogs/GUIDialogPeripheralSettings.cpp | 17 +++++------- - 5 files changed, 67 insertions(+), 28 deletions(-) - -diff --git a/system/peripherals.xml b/system/peripherals.xml -index 72042ec..6c91e49 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -1,22 +1,22 @@ - - -- -+ - -- -- -- -- -+ -+ -+ -+ - - - -- -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ - - -diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp -index 53ce5c2..7b24cd5 100644 ---- a/xbmc/peripherals/Peripherals.cpp -+++ b/xbmc/peripherals/Peripherals.cpp -@@ -447,6 +447,8 @@ bool CPeripherals::LoadMappings(void) - void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map &m_settings) - { - TiXmlElement *currentNode = xmlNode->FirstChildElement("setting"); -+ int iMaxOrder(0); -+ - while (currentNode) - { - CSetting *setting = NULL; -@@ -492,10 +494,31 @@ void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, mapSetVisible(bConfigurable); -+ -+ /* set the order */ -+ int iOrder(0); -+ currentNode->Attribute("order", &iOrder); -+ if (iOrder < 0) -+ iOrder = 0; -+ setting->SetOrder(iOrder); -+ if (iOrder > iMaxOrder) -+ iMaxOrder = iOrder; -+ -+ /* and add this new setting */ - m_settings[strKey] = setting; -+ - currentNode = currentNode->NextSiblingElement("setting"); - } -+ -+ /* add the settings without an order attribute set at the end */ -+ for (map::iterator it = m_settings.begin(); it != m_settings.end(); it++) -+ { -+ if (it->second->GetOrder() == 0) -+ it->second->SetOrder(++iMaxOrder); -+ } - } - - void CPeripherals::GetDirectory(const CStdString &strPath, CFileItemList &items) const -diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp -index d07acaf..ab14e6c 100644 ---- a/xbmc/peripherals/devices/Peripheral.cpp -+++ b/xbmc/peripherals/devices/Peripheral.cpp -@@ -30,6 +30,14 @@ - using namespace PERIPHERALS; - using namespace std; - -+struct SortBySettingsOrder -+{ -+ bool operator()(const CSetting *left, const CSetting *right) -+ { -+ return left->GetOrder() < right->GetOrder(); -+ } -+}; -+ - CPeripheral::CPeripheral(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : - m_type(type), - m_busType(busType), -@@ -168,6 +176,15 @@ bool CPeripheral::IsMultiFunctional(void) const - return m_subDevices.size() > 0; - } - -+vector CPeripheral::GetSettings(void) const -+{ -+ vector settings; -+ for (map::const_iterator it = m_settings.begin(); it != m_settings.end(); it++) -+ settings.push_back(it->second); -+ sort(settings.begin(), settings.end(), SortBySettingsOrder()); -+ return settings; -+} -+ - void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) - { - if (!setting) -@@ -183,7 +200,7 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) - case SETTINGS_TYPE_BOOL: - { - const CSettingBool *mappedSetting = (const CSettingBool *) setting; -- CSettingBool *boolSetting = new CSettingBool(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->GetControlType()); -+ CSettingBool *boolSetting = new CSettingBool(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->GetControlType()); - if (boolSetting) - { - boolSetting->SetVisible(mappedSetting->IsVisible()); -@@ -194,7 +211,7 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) - case SETTINGS_TYPE_INT: - { - const CSettingInt *mappedSetting = (const CSettingInt *) setting; -- CSettingInt *intSetting = new CSettingInt(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); -+ CSettingInt *intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); - if (intSetting) - { - intSetting->SetVisible(mappedSetting->IsVisible()); -@@ -205,7 +222,7 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) - case SETTINGS_TYPE_FLOAT: - { - const CSettingFloat *mappedSetting = (const CSettingFloat *) setting; -- CSettingFloat *floatSetting = new CSettingFloat(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_fMin, mappedSetting->m_fStep, mappedSetting->m_fMax, mappedSetting->GetControlType()); -+ CSettingFloat *floatSetting = new CSettingFloat(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_fMin, mappedSetting->m_fStep, mappedSetting->m_fMax, mappedSetting->GetControlType()); - if (floatSetting) - { - floatSetting->SetVisible(mappedSetting->IsVisible()); -@@ -216,7 +233,7 @@ void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) - case SETTINGS_TYPE_STRING: - { - const CSettingString *mappedSetting = (const CSettingString *) setting; -- CSettingString *stringSetting = new CSettingString(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData().c_str(), mappedSetting->GetControlType(), mappedSetting->m_bAllowEmpty, mappedSetting->m_iHeadingString); -+ CSettingString *stringSetting = new CSettingString(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData().c_str(), mappedSetting->GetControlType(), mappedSetting->m_bAllowEmpty, mappedSetting->m_iHeadingString); - if (stringSetting) - { - stringSetting->SetVisible(mappedSetting->IsVisible()); -diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h -index 7851554..00375bc 100644 ---- a/xbmc/peripherals/devices/Peripheral.h -+++ b/xbmc/peripherals/devices/Peripheral.h -@@ -142,6 +142,8 @@ - virtual void LoadPersistedSettings(void); - virtual void ResetDefaultSettings(void); - -+ virtual std::vector GetSettings(void) const; -+ - virtual bool ErrorOccured(void) const { return m_bError; } - - protected: -diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp -index c79f961..cc801ef 100644 ---- a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp -+++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp -@@ -66,17 +66,15 @@ void CGUIDialogPeripheralSettings::CreateSettings() - - if (m_item) - { -- int iIndex = 1; - CPeripheral *peripheral = g_peripherals.GetByPath(m_item->GetPath()); - if (peripheral) - { -- map::iterator it = peripheral->m_settings.begin(); -- while (it != peripheral->m_settings.end()) -+ vector settings = peripheral->GetSettings(); -+ for (size_t iPtr = 0; iPtr < settings.size(); iPtr++) - { -- CSetting *setting = (*it).second; -+ CSetting *setting = settings[iPtr]; - if (!setting->IsVisible()) - { -- ++it; - CLog::Log(LOGDEBUG, "%s - invisible", __FUNCTION__); - continue; - } -@@ -89,7 +87,7 @@ void CGUIDialogPeripheralSettings::CreateSettings() - if (boolSetting) - { - m_boolSettings.insert(make_pair(CStdString(boolSetting->GetSetting()), boolSetting->GetData())); -- AddBool(iIndex++, boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetSetting()], true); -+ AddBool(boolSetting->GetOrder(), boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetSetting()], true); - } - } - break; -@@ -99,7 +97,7 @@ void CGUIDialogPeripheralSettings::CreateSettings() - if (intSetting) - { - m_intSettings.insert(make_pair(CStdString(intSetting->GetSetting()), (float) intSetting->GetData())); -- AddSlider(iIndex++, intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); -+ AddSlider(intSetting->GetOrder(), intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); - } - } - break; -@@ -109,7 +107,7 @@ void CGUIDialogPeripheralSettings::CreateSettings() - if (floatSetting) - { - m_floatSettings.insert(make_pair(CStdString(floatSetting->GetSetting()), floatSetting->GetData())); -- AddSlider(iIndex++, floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetSetting()], floatSetting->m_fMin, floatSetting->m_fStep, floatSetting->m_fMax, CGUIDialogVideoSettings::FormatFloat, false); -+ AddSlider(floatSetting->GetOrder(), floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetSetting()], floatSetting->m_fMin, floatSetting->m_fStep, floatSetting->m_fMax, CGUIDialogVideoSettings::FormatFloat, false); - } - } - break; -@@ -119,7 +117,7 @@ void CGUIDialogPeripheralSettings::CreateSettings() - if (stringSetting) - { - m_stringSettings.insert(make_pair(CStdString(stringSetting->GetSetting()), stringSetting->GetData())); -- AddString(iIndex, stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetSetting()]); -+ AddString(stringSetting->GetOrder(), stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetSetting()]); - } - } - break; -@@ -128,7 +126,6 @@ void CGUIDialogPeripheralSettings::CreateSettings() - CLog::Log(LOGDEBUG, "%s - unknown type", __FUNCTION__); - break; - } -- ++it; - } - } - else --- -1.7.5.4 - - -From 97953270d4f2a49e1e19a09c49ddd805fcc61f0e Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Fri, 27 Jan 2012 16:09:18 +0100 -Subject: [PATCH 10/18] peripherals: change the 'keymap_enabled' setting for - HID devices into 'do_not_use_custom_keymap', and hide - the setting when the keymap is not configurable - ---- - language/English/strings.xml | 1 + - system/peripherals.xml | 2 +- - xbmc/peripherals/devices/Peripheral.cpp | 15 +++++++++++++++ - xbmc/peripherals/devices/Peripheral.h | 2 ++ - xbmc/peripherals/devices/PeripheralHID.cpp | 9 ++++++--- - 5 files changed, 25 insertions(+), 4 deletions(-) - -diff --git a/language/English/strings.xml b/language/English/strings.xml -index fb5b8fb..9c7caaf 100644 ---- a/language/English/strings.xml -+++ b/language/English/strings.xml -@@ -2378,6 +2378,7 @@ - Device removed - Keymap to use for this device - Keymap enabled -+ Do not use the custom keymap for this device - - Location - Class -diff --git a/system/peripherals.xml b/system/peripherals.xml -index 6c91e49..4e2142d 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -1,6 +1,6 @@ - - -- -+ - - - -diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp -index ab14e6c..11ec8b0 100644 ---- a/xbmc/peripherals/devices/Peripheral.cpp -+++ b/xbmc/peripherals/devices/Peripheral.cpp -@@ -377,6 +377,21 @@ void CPeripheral::SetSetting(const CStdString &strKey, float fValue) - } - } - -+void CPeripheral::SetSettingVisible(const CStdString &strKey, bool bSetTo) -+{ -+ map::iterator it = m_settings.find(strKey); -+ if (it != m_settings.end()) -+ (*it).second->SetVisible(bSetTo); -+} -+ -+bool CPeripheral::IsSettingVisible(const CStdString &strKey) const -+{ -+ map::const_iterator it = m_settings.find(strKey); -+ if (it != m_settings.end()) -+ return (*it).second->IsVisible(); -+ return false; -+} -+ - void CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValue) - { - map::iterator it = m_settings.find(strKey); -diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h -index 00375bc..237cd62 100644 ---- a/xbmc/peripherals/devices/Peripheral.h -+++ b/xbmc/peripherals/devices/Peripheral.h -@@ -128,6 +128,8 @@ - */ - virtual const CStdString GetSettingString(const CStdString &strKey) const; - virtual void SetSetting(const CStdString &strKey, const CStdString &strValue); -+ virtual void SetSettingVisible(const CStdString &strKey, bool bSetTo); -+ virtual bool IsSettingVisible(const CStdString &strKey) const; - - virtual int GetSettingInt(const CStdString &strKey) const; - virtual void SetSetting(const CStdString &strKey, int iValue); -diff --git a/xbmc/peripherals/devices/PeripheralHID.cpp b/xbmc/peripherals/devices/PeripheralHID.cpp -index ec0250d..48469cc 100644 ---- a/xbmc/peripherals/devices/PeripheralHID.cpp -+++ b/xbmc/peripherals/devices/PeripheralHID.cpp -@@ -37,7 +37,7 @@ - - CPeripheralHID::~CPeripheralHID(void) - { -- if (!m_strKeymap.IsEmpty() && GetSettingBool("keymap_enabled")) -+ if (!m_strKeymap.IsEmpty() && !GetSettingBool("do_not_use_custom_keymap")) - { - CLog::Log(LOGDEBUG, "%s - switching active keymapping to: default", __FUNCTION__); - CButtonTranslator::GetInstance().RemoveDevice(m_strKeymap); -@@ -59,9 +59,12 @@ bool CPeripheralHID::InitialiseFeature(const PeripheralFeature feature) - SetSetting("keymap", m_strKeymap); - } - -+ if (!IsSettingVisible("keymap")) -+ SetSettingVisible("do_not_use_custom_keymap", false); -+ - if (!m_strKeymap.IsEmpty()) - { -- bool bKeymapEnabled(GetSettingBool("keymap_enabled")); -+ bool bKeymapEnabled(!GetSettingBool("do_not_use_custom_keymap")); - if (bKeymapEnabled) - { - CLog::Log(LOGDEBUG, "%s - adding keymapping for: %s", __FUNCTION__, m_strKeymap.c_str()); -@@ -82,7 +85,7 @@ bool CPeripheralHID::InitialiseFeature(const PeripheralFeature feature) - - void CPeripheralHID::OnSettingChanged(const CStdString &strChangedSetting) - { -- if (m_bInitialised && ((strChangedSetting.Equals("keymap") && GetSettingBool("keymap_enabled")) || strChangedSetting.Equals("keymap_enabled"))) -+ if (m_bInitialised && ((strChangedSetting.Equals("keymap") && !GetSettingBool("do_not_use_custom_keymap")) || strChangedSetting.Equals("keymap_enabled"))) - { - m_bInitialised = false; - InitialiseFeature(FEATURE_HID); --- -1.7.5.4 - - -From 5c86d3ce71842b1b293c8aaccc046dd732a733f0 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Fri, 17 Feb 2012 12:48:41 +0100 -Subject: [PATCH 11/18] peripherals: use std::set for changed settings instead - of std::vector - ---- - xbmc/peripherals/devices/Peripheral.cpp | 12 ++++++------ - xbmc/peripherals/devices/Peripheral.h | 4 ++-- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp -index 11ec8b0..3d9a238 100644 ---- a/xbmc/peripherals/devices/Peripheral.cpp -+++ b/xbmc/peripherals/devices/Peripheral.cpp -@@ -340,7 +340,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, bool bValue) - bool bChanged(boolSetting->GetData() != bValue); - boolSetting->SetData(bValue); - if (bChanged && m_bInitialised) -- m_changedSettings.push_back(strKey); -+ m_changedSettings.insert(strKey); - } - } - } -@@ -356,7 +356,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, int iValue) - bool bChanged(intSetting->GetData() != iValue); - intSetting->SetData(iValue); - if (bChanged && m_bInitialised) -- m_changedSettings.push_back(strKey); -+ m_changedSettings.insert(strKey); - } - } - } -@@ -372,7 +372,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, float fValue) - bool bChanged(floatSetting->GetData() != fValue); - floatSetting->SetData(fValue); - if (bChanged && m_bInitialised) -- m_changedSettings.push_back(strKey); -+ m_changedSettings.insert(strKey); - } - } - } -@@ -405,7 +405,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValu - bool bChanged(!stringSetting->GetData().Equals(strValue)); - stringSetting->SetData(strValue); - if (bChanged && m_bInitialised) -- m_changedSettings.push_back(strKey); -+ m_changedSettings.insert(strKey); - } - } - else if ((*it).second->GetType() == SETTINGS_TYPE_INT) -@@ -468,7 +468,7 @@ void CPeripheral::PersistSettings(bool bExiting /* = false */) - - if (!bExiting) - { -- for (vector::iterator it = m_changedSettings.begin(); it != m_changedSettings.end(); it++) -+ for (set::const_iterator it = m_changedSettings.begin(); it != m_changedSettings.end(); it++) - OnSettingChanged(*it); - } - m_changedSettings.clear(); -@@ -499,7 +499,7 @@ void CPeripheral::ResetDefaultSettings(void) - map::iterator it = m_settings.begin(); - while (it != m_settings.end()) - { -- m_changedSettings.push_back((*it).first); -+ m_changedSettings.insert((*it).first); - ++it; - } - -diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h -index 237cd62..1c6ca71b 100644 ---- a/xbmc/peripherals/devices/Peripheral.h -+++ b/xbmc/peripherals/devices/Peripheral.h -@@ -20,7 +20,7 @@ - * - */ - --#include -+#include - #include "utils/StdString.h" - #include "peripherals/PeripheralTypes.h" - -@@ -167,6 +167,6 @@ - std::vector m_features; - std::vector m_subDevices; - std::map m_settings; -- std::vector m_changedSettings; -+ std::set m_changedSettings; - }; - } --- -1.7.5.4 - - -From 878c1e79ecc0e69e2fd587bbac1ac05872fee0ce Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Mon, 19 Mar 2012 16:45:55 +0100 -Subject: [PATCH 12/18] cec: updated to libCEC 1.5. uses struct - libcec_configuration to get and set the config in - libCEC. - ---- - configure.in | 2 +- - language/Dutch/strings.xml | 13 +- - language/English/strings.xml | 13 +- - lib/libcec/Makefile | 2 +- - project/BuildDependencies/scripts/libcec_d.bat | 3 +- - project/BuildDependencies/scripts/libcec_d.txt | 2 +- - system/peripherals.xml | 24 +- - tools/darwin/depends/libcec/Makefile | 2 +- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 422 ++++++++++++++------- - xbmc/peripherals/devices/PeripheralCecAdapter.h | 17 +- - 10 files changed, 321 insertions(+), 179 deletions(-) - -diff --git a/configure.in b/configure.in -index bca9239..e6f04df 100755 ---- a/configure.in -+++ b/configure.in -@@ -1173,7 +1173,7 @@ if test "x$use_libcec" != "xno"; then - - # libcec is dyloaded, so we need to check for its headers and link any depends. - if test "x$use_libcec" != "xno"; then -- PKG_CHECK_MODULES([CEC],[libcec >= 1.1.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) -+ PKG_CHECK_MODULES([CEC],[libcec >= 1.5.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) - - if test "x$use_libcec" != "xno"; then - INCLUDES="$INCLUDES $CEC_CFLAGS" -diff --git a/language/Dutch/strings.xml b/language/Dutch/strings.xml -index fd86371..545cc33 100644 -\ No newline at end of file -diff --git a/language/English/strings.xml b/language/English/strings.xml -index 9c7caaf..27487f4 100644 ---- a/language/English/strings.xml -+++ b/language/English/strings.xml -@@ -2393,17 +2393,20 @@ - Press "user" button command - Enable switch side commands - Could not open the adapter -- Power on the TV when starting XBMC -- Power off devices when stopping XBMC -+ Devices to power on the TV when starting XBMC -+ Devices to power off devices when stopping XBMC - Put devices in standby mode when activating screensaver - - Could not detect the CEC port. Set it up manually. -- Could not detect the CEC adapter. -- Unsupported libcec interface version. %d is greater than the version XBMC supports (%d) -+ Could not initialise the CEC adapter. Check your settings. -+ Unsupported libCEC interface version. %d is greater than the version XBMC supports (%d) - Put this PC in standby mode when the TV is switched off - HDMI port number - Connected -- Adapter found, but libcec is not available -+ Adapter found, but libCEC is not available - Use the TV's language setting - Connected to HDMI device -+ Make XBMC the active source when starting -+ Physical address (overrules HDMI port) -+ COM port (leave empty unless needed) - -diff --git a/lib/libcec/Makefile b/lib/libcec/Makefile -index 8776161..d9af688 100644 ---- a/lib/libcec/Makefile -+++ b/lib/libcec/Makefile -@@ -7,7 +7,7 @@ - - # lib name, version - LIBNAME=libcec --VERSION=1.2.0 -+VERSION=1.5.0 - SOURCE=$(LIBNAME)-$(VERSION) - - # download location and format -diff --git a/project/BuildDependencies/scripts/libcec_d.bat b/project/BuildDependencies/scripts/libcec_d.bat -index 27160b4..86a2797 100644 -diff --git a/project/BuildDependencies/scripts/libcec_d.txt b/project/BuildDependencies/scripts/libcec_d.txt -index ec9df80..0f70461 100644 -diff --git a/system/peripherals.xml b/system/peripherals.xml -index 4e2142d..1df6f1a 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -8,15 +8,21 @@ - - - -- -+ - -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - -diff --git a/tools/darwin/depends/libcec/Makefile b/tools/darwin/depends/libcec/Makefile -index c6b44c0..be4ee35 100644 ---- a/tools/darwin/depends/libcec/Makefile -+++ b/tools/darwin/depends/libcec/Makefile -@@ -2,7 +2,7 @@ include ../Makefile.include - - # lib name, version - LIBNAME=libcec --VERSION=1.2.0 -+VERSION=1.5.0 - SOURCE=$(LIBNAME)-$(VERSION) - ARCHIVE=$(SOURCE).tar.gz - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index a686def..645ca4f 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -18,8 +18,8 @@ - * http://www.gnu.org/copyleft/gpl.html - * - */ --#include "system.h" - -+#include "system.h" - #if defined(HAVE_LIBCEC) - #include "PeripheralCecAdapter.h" - #include "input/XBIRRemote.h" -@@ -34,13 +34,13 @@ - #include "settings/Settings.h" - #include "utils/log.h" - --#include -+#include - - using namespace PERIPHERALS; - using namespace ANNOUNCEMENT; - using namespace CEC; - --#define CEC_LIB_SUPPORTED_VERSION 1 -+#define CEC_LIB_SUPPORTED_VERSION 0x1500 - - /* time in seconds to ignore standby commands from devices after the screensaver has been activated */ - #define SCREENSAVER_TIMEOUT 10 -@@ -51,19 +51,19 @@ class DllLibCECInterface - { - public: - virtual ~DllLibCECInterface() {} -- virtual ICECAdapter* CECInit(const char *interfaceName, cec_device_type_list types)=0; -- virtual void* CECDestroy(ICECAdapter *adapter)=0; -+ virtual ICECAdapter* CECInitialise(libcec_configuration *configuration)=0; -+ virtual void* CECDestroy(ICECAdapter *adapter)=0; - }; - - class DllLibCEC : public DllDynamic, DllLibCECInterface - { - DECLARE_DLL_WRAPPER(DllLibCEC, DLL_PATH_LIBCEC) - -- DEFINE_METHOD2(ICECAdapter*, CECInit, (const char *p1, cec_device_type_list p2)) -- DEFINE_METHOD1(void* , CECDestroy, (ICECAdapter *p1)) -+ DEFINE_METHOD1(ICECAdapter*, CECInitialise, (libcec_configuration *p1)) -+ DEFINE_METHOD1(void* , CECDestroy, (ICECAdapter *p1)) - - BEGIN_METHOD_RESOLVE() -- RESOLVE_METHOD_RENAME(CECInit, CECInit) -+ RESOLVE_METHOD_RENAME(CECInitialise, CECInitialise) - RESOLVE_METHOD_RENAME(CECDestroy, CECDestroy) - END_METHOD_RESOLVE() - }; -@@ -82,35 +82,9 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface - m_button.iButton = 0; - m_button.iDuration = 0; - m_screensaverLastActivated.SetValid(false); -- m_dll = new DllLibCEC; -- if (m_dll->Load() && m_dll->IsLoaded()) -- { -- cec_device_type_list typeList; -- typeList.clear(); -- typeList.add(CEC_DEVICE_TYPE_RECORDING_DEVICE); -- m_cecAdapter = m_dll->CECInit("XBMC", typeList); -- } -- else -- m_cecAdapter = NULL; -- -- if (!m_cecAdapter || m_cecAdapter->GetMinLibVersion() > CEC_LIB_SUPPORTED_VERSION) -- { -- /* unsupported libcec version */ -- CLog::Log(LOGERROR, g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_cecAdapter->GetMinLibVersion() : -1); - -- CStdString strMessage; -- strMessage.Format(g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_cecAdapter->GetMinLibVersion() : -1); -- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), strMessage); -- m_bError = true; -- if (m_cecAdapter) -- m_dll->CECDestroy(m_cecAdapter); -- m_cecAdapter = NULL; -- } -- else -- { -- CLog::Log(LOGDEBUG, "%s - using libCEC v%d.%d", __FUNCTION__, m_cecAdapter->GetLibVersionMajor(), m_cecAdapter->GetLibVersionMinor()); -- m_features.push_back(FEATURE_CEC); -- } -+ m_configuration.Clear(); -+ m_features.push_back(FEATURE_CEC); - } - - CPeripheralCecAdapter::~CPeripheralCecAdapter(void) -@@ -133,53 +107,60 @@ void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, - { - if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit") && m_bIsReady) - { -- if (GetSettingBool("cec_power_off_shutdown")) -- m_cecAdapter->StandbyDevices(); -- else -- m_cecAdapter->SetInactiveView(); -+ // only send power off and inactive source command when we're currently active -+ if (m_cecAdapter->IsLibCECActiveSource()) -+ { -+ // if there are any devices to power off set, power them off -+ if (!m_configuration.powerOffDevices.IsEmpty()) -+ m_cecAdapter->StandbyDevices(CECDEVICE_BROADCAST); -+ // send an inactive source command otherwise -+ else -+ m_cecAdapter->SetInactiveView(); -+ } - } -- else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && GetSettingBool("cec_standby_screensaver") && m_bIsReady) -+ else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && m_bIsReady) - { -- m_cecAdapter->PowerOnDevices(); -+ if (m_configuration.bPowerOffScreensaver == 1) -+ { -+ // power off/on on screensaver is set, and devices to wake are set -+ if (!m_configuration.wakeDevices.IsEmpty()) -+ m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); -+ -+ // the option to make XBMC the active source is set -+ if (m_configuration.bActivateSource == 1) -+ m_cecAdapter->SetActiveSource(); -+ } - } -- else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && GetSettingBool("cec_standby_screensaver")) -+ else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && m_bIsReady) - { - // Don't put devices to standby if application is currently playing -- if (!g_application.IsPlaying() || g_application.IsPaused()) -+ if ((!g_application.IsPlaying() || g_application.IsPaused()) && m_configuration.bPowerOffScreensaver == 1) - { - m_screensaverLastActivated = CDateTime::GetCurrentDateTime(); -- m_cecAdapter->StandbyDevices(); -+ // only power off when we're the active source -+ if (m_cecAdapter->IsLibCECActiveSource()) -+ m_cecAdapter->StandbyDevices(CECDEVICE_BROADCAST); - } - } - else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) - { -- if (GetSettingBool("cec_power_off_shutdown") && m_bIsReady) -- m_cecAdapter->StandbyDevices(); -+ // this will also power off devices when we're the active source - CSingleLock lock(m_critSection); - m_bStop = true; - WaitForThreadExit(0); - } - else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) - { -+ // reconnect to the device - CSingleLock lock(m_critSection); - CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); -+ -+ // close the previous connection - m_cecAdapter->Close(); - -- CStdString strPort = GetComPort(); -- if (!strPort.empty()) -- { -- if (!m_cecAdapter->Open(strPort.c_str(), 10000)) -- { -- CLog::Log(LOGERROR, "%s - failed to reconnect to the CEC adapter", __FUNCTION__); -- m_bStop = true; -- } -- else -- { -- if (GetSettingBool("cec_power_on_startup")) -- PowerOnCecDevices(CECDEVICE_TV); -- m_cecAdapter->SetActiveView(); -- } -- } -+ // and open a new one -+ m_bStop = false; -+ Create(); - } - } - -@@ -187,6 +168,41 @@ bool CPeripheralCecAdapter::InitialiseFeature(const PeripheralFeature feature) - { - if (feature == FEATURE_CEC && !m_bStarted) - { -+ SetConfigurationFromSettings(); -+ m_callbacks.CBCecLogMessage = &CecLogMessage; -+ m_callbacks.CBCecKeyPress = &CecKeyPress; -+ m_callbacks.CBCecCommand = &CecCommand; -+ m_callbacks.CBCecConfigurationChanged = &CecConfiguration; -+ m_configuration.callbackParam = this; -+ m_configuration.callbacks = &m_callbacks; -+ -+ m_dll = new DllLibCEC; -+ if (m_dll->Load() && m_dll->IsLoaded()) -+ m_cecAdapter = m_dll->CECInitialise(&m_configuration); -+ else -+ return false; -+ -+ if (m_configuration.serverVersion < CEC_LIB_SUPPORTED_VERSION) -+ { -+ /* unsupported libcec version */ -+ CLog::Log(LOGERROR, g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_configuration.serverVersion : -1); -+ -+ CStdString strMessage; -+ strMessage.Format(g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_configuration.serverVersion : -1); -+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), strMessage); -+ m_bError = true; -+ if (m_cecAdapter) -+ m_dll->CECDestroy(m_cecAdapter); -+ m_cecAdapter = NULL; -+ -+ m_features.clear(); -+ return false; -+ } -+ else -+ { -+ CLog::Log(LOGDEBUG, "%s - using libCEC v%s", __FUNCTION__, m_cecAdapter->ToString((cec_server_version)m_configuration.serverVersion)); -+ } -+ - m_bStarted = true; - Create(); - } -@@ -225,25 +241,20 @@ CStdString CPeripheralCecAdapter::GetComPort(void) - return strPort; - } - --void CPeripheralCecAdapter::Process(void) -+bool CPeripheralCecAdapter::OpenConnection(void) - { -+ bool bIsOpen(false); -+ - if (!GetSettingBool("enabled")) - { - CLog::Log(LOGDEBUG, "%s - CEC adapter is disabled in peripheral settings", __FUNCTION__); - m_bStarted = false; -- return; -+ return bIsOpen; - } - - CStdString strPort = GetComPort(); - if (strPort.empty()) -- return; -- -- EnableCallbacks(); -- -- // set correct physical address from peripheral settings -- int iDevice = GetSettingInt("connected_device"); -- int iHdmiPort = GetSettingInt("cec_hdmi_port"); -- m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort); -+ return bIsOpen; - - // open the CEC adapter - CLog::Log(LOGDEBUG, "%s - opening a connection to the CEC adapter: %s", __FUNCTION__, strPort.c_str()); -@@ -253,24 +264,43 @@ void CPeripheralCecAdapter::Process(void) - strMessage.Format(g_localizeStrings.Get(21336), g_localizeStrings.Get(36000)); - CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strMessage); - -- if (!m_cecAdapter->Open(strPort.c_str(), 10000)) -+ bool bConnectionFailedDisplayed(false); -+ -+ while (!m_bStop && !bIsOpen) - { -- CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__); -- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); -- m_bStarted = false; -- return; -- } -+ if ((bIsOpen = m_cecAdapter->Open(strPort.c_str(), 10000)) == false) -+ { -+ CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__); -+ if (!bConnectionFailedDisplayed) -+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); -+ bConnectionFailedDisplayed = true; - -- CAnnouncementManager::AddAnnouncer(this); -- CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); -+ Sleep(10000); -+ } -+ } - -- if (GetSettingBool("cec_power_on_startup")) -+ if (bIsOpen) - { -- PowerOnCecDevices(CECDEVICE_TV); -- m_cecAdapter->SetActiveSource(); -+ CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); -+ -+ if (!m_configuration.wakeDevices.IsEmpty()) -+ m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); -+ -+ if (m_configuration.bActivateSource == 1) -+ m_cecAdapter->SetActiveSource(); - } - -- m_queryThread = new CPeripheralCecAdapterQueryThread(this); -+ return bIsOpen; -+} -+ -+void CPeripheralCecAdapter::Process(void) -+{ -+ if (!OpenConnection()) -+ return; -+ -+ CAnnouncementManager::AddAnnouncer(this); -+ -+ m_queryThread = new CPeripheralCecAdapterQueryThread(this, m_configuration.bUseTVMenuLanguage == 1); - m_queryThread->Create(false); - - while (!m_bStop) -@@ -283,62 +313,19 @@ void CPeripheralCecAdapter::Process(void) - } - - delete m_queryThread; -- m_cecAdapter->Close(); -- -- CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__); -- m_bStarted = false; --} -- --bool CPeripheralCecAdapter::PowerOnCecDevices(cec_logical_address iLogicalAddress) --{ -- bool bReturn(false); -- -- if (m_cecAdapter && m_bIsReady) -- { -- CLog::Log(LOGDEBUG, "%s - powering on CEC capable device with address %1x", __FUNCTION__, iLogicalAddress); -- bReturn = m_cecAdapter->PowerOnDevices(iLogicalAddress); -- } -- -- return bReturn; --} -- --bool CPeripheralCecAdapter::StandbyCecDevices(cec_logical_address iLogicalAddress) --{ -- bool bReturn(false); -- -- if (m_cecAdapter && m_bIsReady) -- { -- CLog::Log(LOGDEBUG, "%s - putting CEC capable devices with address %1x in standby mode", __FUNCTION__, iLogicalAddress); -- bReturn = m_cecAdapter->StandbyDevices(iLogicalAddress); -- } -- -- return bReturn; --} - --bool CPeripheralCecAdapter::SendPing(void) --{ -- bool bReturn(false); -- if (m_cecAdapter && m_bIsReady) -+ if (m_cecAdapter->IsLibCECActiveSource()) - { -- CLog::Log(LOGDEBUG, "%s - sending ping to the CEC adapter", __FUNCTION__); -- bReturn = m_cecAdapter->PingAdapter(); -+ if (m_configuration.bPowerOffOnStandby == 1) -+ m_cecAdapter->StandbyDevices(); -+ else -+ m_cecAdapter->SetInactiveView(); - } - -- return bReturn; --} -- --bool CPeripheralCecAdapter::SetHdmiPort(int iDevice, int iHdmiPort) --{ -- bool bReturn(false); -- if (m_cecAdapter && m_bIsReady) -- { -- if (iHdmiPort <= 0 || iHdmiPort > 16) -- iHdmiPort = 1; -- CLog::Log(LOGDEBUG, "%s - changing active HDMI port to %d on device %d", __FUNCTION__, iHdmiPort, iDevice); -- bReturn = m_cecAdapter->SetHDMIPort((cec_logical_address)iDevice, iHdmiPort); -- } -+ m_cecAdapter->Close(); - -- return bReturn; -+ CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__); -+ m_bStarted = false; - } - - bool CPeripheralCecAdapter::HasConnectedAudioSystem(void) -@@ -543,7 +530,7 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command) - case CEC_OPCODE_STANDBY: - /* a device was put in standby mode */ - CLog::Log(LOGDEBUG, "%s - device %1x was put in standby mode", __FUNCTION__, command.initiator); -- if (command.initiator == CECDEVICE_TV && adapter->GetSettingBool("standby_pc_on_tv_standby") && -+ if (command.initiator == CECDEVICE_TV && adapter->m_configuration.bPowerOffOnStandby == 1 && - (!adapter->m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT))) - { - adapter->m_bStarted = false; -@@ -551,7 +538,7 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command) - } - break; - case CEC_OPCODE_SET_MENU_LANGUAGE: -- if (adapter->GetSettingBool("use_tv_menu_language") && command.initiator == CECDEVICE_TV && command.parameters.size == 3) -+ if (adapter->m_configuration.bUseTVMenuLanguage == 1 && command.initiator == CECDEVICE_TV && command.parameters.size == 3) - { - char strNewLanguage[4]; - for (int iPtr = 0; iPtr < 3; iPtr++) -@@ -610,6 +597,17 @@ int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command) - return 1; - } - -+int CPeripheralCecAdapter::CecConfiguration(void *cbParam, const libcec_configuration &config) -+{ -+ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; -+ if (!adapter) -+ return 0; -+ -+ CSingleLock lock(adapter->m_critSection); -+ adapter->SetConfigurationFromLibCEC(config); -+ return 1; -+} -+ - int CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress &key) - { - CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; -@@ -870,9 +868,10 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting - else if (bEnabled && !m_cecAdapter && m_bStarted) - InitialiseFeature(FEATURE_CEC); - } -- else if (strChangedSetting.Equals("connected_device") || strChangedSetting.Equals("cec_hdmi_port")) -+ else - { -- SetHdmiPort(GetSettingInt("connected_device"), GetSettingInt("cec_hdmi_port")); -+ SetConfigurationFromSettings(); -+ m_cecAdapter->SetConfiguration(&m_configuration); - } - } - -@@ -920,9 +919,10 @@ bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation) - return false; - } - --CPeripheralCecAdapterQueryThread::CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter) : -+CPeripheralCecAdapterQueryThread::CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter, bool bGetMenuLanguage) : - CThread("CEC Adapter Query Thread"), -- m_adapter(adapter) -+ m_adapter(adapter), -+ m_bGetMenuLanguage(bGetMenuLanguage) - { - m_event.Reset(); - } -@@ -951,7 +951,7 @@ void CPeripheralCecAdapterQueryThread::Process(void) - bContinue = true; - }while(!bContinue); - -- if (m_adapter->GetSettingBool("use_tv_menu_language")) -+ if (m_bGetMenuLanguage) - { - cec_menu_language language; - if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) -@@ -981,12 +981,140 @@ void CPeripheralCecAdapterQueryThread::Process(void) - CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); - } - --void CPeripheralCecAdapter::EnableCallbacks(void) -+void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configuration &config) -+{ -+ // set the primary device type -+ m_configuration.deviceTypes.Clear(); -+ m_configuration.deviceTypes.Add(config.deviceTypes[0]); -+ SetSetting("device_type", (int)config.deviceTypes[0]); -+ -+ // set the connected device -+ m_configuration.baseDevice = config.baseDevice; -+ SetSetting("connected_device", (int)config.baseDevice); -+ -+ // set the HDMI port number -+ m_configuration.iHDMIPort = config.iHDMIPort; -+ SetSetting("cec_hdmi_port", config.iHDMIPort); -+ -+ // set the physical address, when baseDevice or iHDMIPort are not set -+ if (m_configuration.baseDevice == CECDEVICE_UNKNOWN || -+ m_configuration.iHDMIPort == 0 || m_configuration.iHDMIPort > 4) -+ { -+ m_configuration.iPhysicalAddress = config.iPhysicalAddress; -+ CStdString strPhysicalAddress; -+ strPhysicalAddress.Format("%x", config.iPhysicalAddress); -+ SetSetting("physical_address", strPhysicalAddress); -+ } -+ -+ // set the tv vendor override -+ m_configuration.tvVendor = config.tvVendor; -+ SetSetting("tv_vendor", (int)config.tvVendor); -+ -+ // set the devices to wake when starting -+ m_configuration.wakeDevices = config.wakeDevices; -+ CStdString strWakeDevices; -+ for (unsigned int iPtr = 0; iPtr <= 16; iPtr++) -+ if (config.wakeDevices[iPtr]) -+ strWakeDevices.AppendFormat(" %X", iPtr); -+ SetSetting("wake_devices", strWakeDevices.Trim()); -+ -+ // set the devices to power off when stopping -+ m_configuration.powerOffDevices = config.powerOffDevices; -+ CStdString strPowerOffDevices; -+ for (unsigned int iPtr = 0; iPtr <= 16; iPtr++) -+ if (config.powerOffDevices[iPtr]) -+ strPowerOffDevices.AppendFormat(" %X", iPtr); -+ SetSetting("wake_devices", strPowerOffDevices.Trim()); -+ -+ // set the boolean settings -+ m_configuration.bUseTVMenuLanguage = m_configuration.bUseTVMenuLanguage; -+ SetSetting("use_tv_menu_language", m_configuration.bUseTVMenuLanguage == 1); -+ -+ m_configuration.bActivateSource = m_configuration.bActivateSource; -+ SetSetting("activate_source", m_configuration.bActivateSource == 1); -+ -+ m_configuration.bPowerOffScreensaver = m_configuration.bPowerOffScreensaver; -+ SetSetting("cec_standby_screensaver", m_configuration.bPowerOffScreensaver == 1); -+ -+ m_configuration.bPowerOffOnStandby = m_configuration.bPowerOffOnStandby; -+ SetSetting("standby_pc_on_tv_standby", m_configuration.bPowerOffOnStandby == 1); -+} -+ -+void CPeripheralCecAdapter::SetConfigurationFromSettings(void) - { -- m_callbacks.CBCecLogMessage = &CecLogMessage; -- m_callbacks.CBCecKeyPress = &CecKeyPress; -- m_callbacks.CBCecCommand = &CecCommand; -- m_cecAdapter->EnableCallbacks(this, &m_callbacks); -+ // client version 1.5.0 -+ m_configuration.clientVersion = CEC_CLIENT_VERSION_1_5_0; -+ -+ // device name 'XBMC' -+ snprintf(m_configuration.strDeviceName, 13, "%s", GetSettingString("device_name").c_str()); -+ -+ // set the primary device type -+ m_configuration.deviceTypes.Clear(); -+ int iDeviceType = GetSettingInt("device_type"); -+ if (iDeviceType != (int)CEC_DEVICE_TYPE_RECORDING_DEVICE && -+ iDeviceType != (int)CEC_DEVICE_TYPE_PLAYBACK_DEVICE && -+ iDeviceType != (int)CEC_DEVICE_TYPE_TUNER) -+ iDeviceType = (int)CEC_DEVICE_TYPE_RECORDING_DEVICE; -+ m_configuration.deviceTypes.Add((cec_device_type)iDeviceType); -+ -+ // always try to autodetect the address. -+ // when the firmware supports this, it will override the physical address, connected device and hdmi port settings -+ m_configuration.bAutodetectAddress = 1; -+ -+ // set the physical address -+ // when set, it will override the connected device and hdmi port settings -+ CStdString strPhysicalAddress = GetSettingString("physical_address"); -+ int iPhysicalAddress; -+ if (sscanf(strPhysicalAddress.c_str(), "%x", &iPhysicalAddress) == 1 && iPhysicalAddress > 0 && iPhysicalAddress < 0xFFFF) -+ m_configuration.iPhysicalAddress = iPhysicalAddress; -+ -+ // set the connected device -+ int iConnectedDevice = GetSettingInt("connected_device"); -+ if (iConnectedDevice == 0 || iConnectedDevice == 5) -+ m_configuration.baseDevice = (cec_logical_address)iConnectedDevice; -+ -+ // set the HDMI port number -+ int iHDMIPort = GetSettingInt("cec_hdmi_port"); -+ if (iHDMIPort >= 0 && iHDMIPort <= 4) -+ m_configuration.iHDMIPort = iHDMIPort; -+ -+ // set the tv vendor override -+ int iVendor = GetSettingInt("tv_vendor"); -+ if (iVendor > 0 && iVendor < 0xFFFFFF) -+ m_configuration.tvVendor = iVendor; -+ -+ // read the devices to wake when starting -+ CStdString strWakeDevices = CStdString(GetSettingString("wake_devices")).Trim(); -+ m_configuration.wakeDevices.Clear(); -+ ReadLogicalAddresses(strWakeDevices, m_configuration.wakeDevices); -+ -+ // read the devices to power off when stopping -+ CStdString strStandbyDevices = CStdString(GetSettingString("standby_devices")).Trim(); -+ m_configuration.powerOffDevices.Clear(); -+ ReadLogicalAddresses(strStandbyDevices, m_configuration.powerOffDevices); -+ -+ // always get the settings from the rom, when supported by the firmware -+ m_configuration.bGetSettingsFromROM = 1; -+ -+ // read the boolean settings -+ m_configuration.bUseTVMenuLanguage = GetSettingBool("use_tv_menu_language") ? 1 : 0; -+ m_configuration.bActivateSource = GetSettingBool("activate_source") ? 1 : 0; -+ m_configuration.bPowerOffScreensaver = GetSettingBool("cec_standby_screensaver") ? 1 : 0; -+ m_configuration.bPowerOffOnStandby = GetSettingBool("standby_pc_on_tv_standby") ? 1 : 0; -+} -+ -+void CPeripheralCecAdapter::ReadLogicalAddresses(const CStdString &strString, cec_logical_addresses &addresses) -+{ -+ for (size_t iPtr = 0; iPtr < strString.size(); iPtr++) -+ { -+ CStdString strDevice = CStdString(strString.substr(iPtr, 1)).Trim(); -+ if (!strDevice.IsEmpty()) -+ { -+ int iDevice(0); -+ if (sscanf(strDevice.c_str(), "%x", &iDevice) == 1 && iDevice >= 0 && iDevice <= 0xF) -+ addresses.Set((cec_logical_address)iDevice); -+ } -+ } - } - - #endif -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index 54eef5f..9de351d 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -32,7 +32,7 @@ - #ifdef isset - #undef isset - #endif --#include -+#include - - class DllLibCEC; - -@@ -68,8 +68,6 @@ - virtual ~CPeripheralCecAdapter(void); - - virtual void Announce(ANNOUNCEMENT::EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); -- virtual bool PowerOnCecDevices(CEC::cec_logical_address iLogicalAddress); -- virtual bool StandbyCecDevices(CEC::cec_logical_address iLogicalAddress); - virtual bool HasConnectedAudioSystem(void); - virtual void SetAudioSystemConnected(bool bSetTo); - virtual void ScheduleVolumeUp(void); -@@ -79,9 +77,6 @@ - virtual void ScheduleMute(void); - virtual void Mute(void); - -- virtual bool SendPing(void); -- virtual bool SetHdmiPort(int iDevice, int iHdmiPort); -- - virtual void OnSettingChanged(const CStdString &strChangedSetting); - - virtual WORD GetButton(void); -@@ -90,10 +85,14 @@ - virtual CStdString GetComPort(void); - - protected: -- virtual void EnableCallbacks(void); -+ virtual bool OpenConnection(void); -+ virtual void SetConfigurationFromSettings(void); -+ virtual void SetConfigurationFromLibCEC(const CEC::libcec_configuration &config); -+ static void ReadLogicalAddresses(const CStdString &strString, CEC::cec_logical_addresses &addresses); - static int CecKeyPress(void *cbParam, const CEC::cec_keypress &key); - static int CecLogMessage(void *cbParam, const CEC::cec_log_message &message); - static int CecCommand(void *cbParam, const CEC::cec_command &command); -+ static int CecConfiguration(void *cbParam, const CEC::libcec_configuration &config); - - virtual bool GetNextKey(void); - virtual bool GetNextCecKey(CEC::cec_keypress &key); -@@ -120,12 +119,13 @@ - CPeripheralCecAdapterQueryThread *m_queryThread; - CEC::ICECCallbacks m_callbacks; - CCriticalSection m_critSection; -+ CEC::libcec_configuration m_configuration; - }; - - class CPeripheralCecAdapterQueryThread : public CThread - { - public: -- CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter); -+ CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter, bool bGetMenuLanguage); - virtual ~CPeripheralCecAdapterQueryThread(void); - - virtual void Signal(void); -@@ -135,6 +135,7 @@ - - CPeripheralCecAdapter *m_adapter; - CEvent m_event; -+ bool m_bGetMenuLanguage; - }; - } - --- -1.7.5.4 - - -From 7d03a9a7c37eab5891872eb93a5301f42cf0e7e8 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Fri, 17 Feb 2012 14:05:42 +0100 -Subject: [PATCH 13/18] cec: update settings async, so we don't block the gui - thread when the OK button is pressed - ---- - language/English/strings.xml | 2 + - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 219 +++++++++++++++------ - xbmc/peripherals/devices/PeripheralCecAdapter.h | 25 ++- - 3 files changed, 173 insertions(+), 73 deletions(-) - -diff --git a/language/English/strings.xml b/language/English/strings.xml -index 27487f4..1dc30d9 100644 ---- a/language/English/strings.xml -+++ b/language/English/strings.xml -@@ -2409,4 +2409,6 @@ - Make XBMC the active source when starting - Physical address (overrules HDMI port) - COM port (leave empty unless needed) -+ Configuration updated -+ Failed to set the new configuration. Please check your settings. - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 645ca4f..ef89bce 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -300,7 +300,7 @@ void CPeripheralCecAdapter::Process(void) - - CAnnouncementManager::AddAnnouncer(this); - -- m_queryThread = new CPeripheralCecAdapterQueryThread(this, m_configuration.bUseTVMenuLanguage == 1); -+ m_queryThread = new CPeripheralCecAdapterUpdateThread(this, &m_configuration); - m_queryThread->Create(false); - - while (!m_bStop) -@@ -871,7 +871,7 @@ void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting - else - { - SetConfigurationFromSettings(); -- m_cecAdapter->SetConfiguration(&m_configuration); -+ m_queryThread->UpdateConfiguration(&m_configuration); - } - } - -@@ -919,68 +919,6 @@ bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation) - return false; - } - --CPeripheralCecAdapterQueryThread::CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter, bool bGetMenuLanguage) : -- CThread("CEC Adapter Query Thread"), -- m_adapter(adapter), -- m_bGetMenuLanguage(bGetMenuLanguage) --{ -- m_event.Reset(); --} -- --CPeripheralCecAdapterQueryThread::~CPeripheralCecAdapterQueryThread(void) --{ -- m_event.Set(); -- StopThread(true); --} -- --void CPeripheralCecAdapterQueryThread::Signal(void) --{ -- m_event.Set(); --} -- --void CPeripheralCecAdapterQueryThread::Process(void) --{ -- bool bContinue(false); -- do -- { -- m_event.WaitMSec(5000); -- if (m_adapter->m_bStop) -- return; -- -- if (m_adapter->m_cecAdapter->GetDevicePowerStatus(CECDEVICE_TV) == CEC_POWER_STATUS_ON) -- bContinue = true; -- }while(!bContinue); -- -- if (m_bGetMenuLanguage) -- { -- cec_menu_language language; -- if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) -- m_adapter->SetMenuLanguage(language.language); -- } -- -- CStdString strNotification; -- cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); -- strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name); -- -- /* disable the mute setting when an amp is found, because the amp handles the mute setting and -- set PCM output to 100% */ -- if (m_adapter->m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM)) -- { -- cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); -- CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); -- strNotification.AppendFormat(" - %s", ampName.name); -- -- m_adapter->SetAudioSystemConnected(true); -- g_settings.m_bMute = false; -- g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; -- } -- -- m_adapter->m_bIsReady = true; -- -- m_adapter->m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); -- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); --} -- - void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configuration &config) - { - // set the primary device type -@@ -1117,4 +1055,157 @@ void CPeripheralCecAdapter::ReadLogicalAddresses(const CStdString &strString, ce - } - } - -+CPeripheralCecAdapterUpdateThread::CPeripheralCecAdapterUpdateThread(CPeripheralCecAdapter *adapter, libcec_configuration *configuration) : -+ CThread("CEC Adapter Update Thread"), -+ m_adapter(adapter), -+ m_configuration(*configuration), -+ m_bNextConfigurationScheduled(false), -+ m_bIsUpdating(true) -+{ -+ m_nextConfiguration.Clear(); -+ m_event.Reset(); -+} -+ -+CPeripheralCecAdapterUpdateThread::~CPeripheralCecAdapterUpdateThread(void) -+{ -+ StopThread(false); -+ m_event.Set(); -+ StopThread(true); -+} -+ -+void CPeripheralCecAdapterUpdateThread::Signal(void) -+{ -+ m_event.Set(); -+} -+ -+bool CPeripheralCecAdapterUpdateThread::UpdateConfiguration(libcec_configuration *configuration) -+{ -+ CSingleLock lock(m_critSection); -+ if (m_bIsUpdating) -+ { -+ m_bNextConfigurationScheduled = true; -+ m_nextConfiguration = *configuration; -+ } -+ else -+ { -+ m_configuration = *configuration; -+ m_event.Set(); -+ } -+ return true; -+} -+ -+bool CPeripheralCecAdapterUpdateThread::WaitReady(void) -+{ -+ // don't wait if we're not powering up anything -+ if (m_configuration.wakeDevices.IsEmpty() && m_configuration.bActivateSource == 0) -+ return true; -+ -+ // wait for the TV if we're configured to become the active source. -+ // wait for the first device in the wake list otherwise. -+ cec_logical_address waitFor = (m_configuration.bActivateSource == 1) ? -+ CECDEVICE_TV : -+ m_configuration.wakeDevices.primary; -+ -+ cec_power_status powerStatus(CEC_POWER_STATUS_UNKNOWN); -+ bool bContinue(true); -+ while (bContinue && !m_adapter->m_bStop && !m_bStop &&powerStatus != CEC_POWER_STATUS_ON) -+ { -+ powerStatus = m_adapter->m_cecAdapter->GetDevicePowerStatus(waitFor); -+ if (powerStatus != CEC_POWER_STATUS_ON) -+ bContinue = !m_event.WaitMSec(5000); -+ } -+ -+ return powerStatus == CEC_POWER_STATUS_ON; -+} -+ -+bool CPeripheralCecAdapterUpdateThread::SetInitialConfiguration(void) -+{ -+ // devices to wake are set -+ if (!m_configuration.wakeDevices.IsEmpty()) -+ m_adapter->m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); -+ -+ // the option to make XBMC the active source is set -+ if (m_configuration.bActivateSource == 1) -+ m_adapter->m_cecAdapter->SetActiveSource(); -+ -+ // wait until devices are powered up -+ if (!WaitReady()) -+ return false; -+ -+ // request the menu language of the TV -+ if (m_configuration.bUseTVMenuLanguage == 1) -+ { -+ cec_menu_language language; -+ if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) -+ m_adapter->SetMenuLanguage(language.language); -+ } -+ -+ // request the OSD name of the TV -+ CStdString strNotification; -+ cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); -+ strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name); -+ -+ /* disable the mute setting when an amp is found, because the amp handles the mute setting and -+ set PCM output to 100% */ -+ if (m_adapter->m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM)) -+ { -+ // request the OSD name of the amp -+ cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); -+ CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); -+ strNotification.AppendFormat(" - %s", ampName.name); -+ -+ // set amp present -+ m_adapter->SetAudioSystemConnected(true); -+ g_settings.m_bMute = false; -+ g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; -+ } -+ -+ m_adapter->m_bIsReady = true; -+ -+ // try to send an OSD string to the TV -+ m_adapter->m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); -+ // and let the gui know that we're done -+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); -+ -+ CSingleLock lock(m_critSection); -+ m_bIsUpdating = false; -+ return true; -+} -+ -+void CPeripheralCecAdapterUpdateThread::Process(void) -+{ -+ // set the initial configuration -+ if (!SetInitialConfiguration()) -+ return; -+ -+ // and wait for updates -+ bool bUpdate(false); -+ while (!m_bStop) -+ { -+ // update received -+ if (m_event.WaitMSec(500) || bUpdate) -+ { -+ // set the new configuration -+ bool bConfigSet(m_adapter->m_cecAdapter->SetConfiguration(&m_configuration)); -+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(bConfigSet ? 36023 : 36024)); -+ { -+ CSingleLock lock(m_critSection); -+ bUpdate = m_bNextConfigurationScheduled; -+ if (bUpdate) -+ { -+ // another update is scheduled -+ m_bNextConfigurationScheduled = false; -+ m_configuration = m_nextConfiguration; -+ } -+ else -+ { -+ // nothing left to do, wait for updates -+ m_bIsUpdating = false; -+ m_event.Reset(); -+ } -+ } -+ } -+ } -+} -+ - #endif -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index 9de351d..1eadca2 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -43,7 +43,7 @@ - - namespace PERIPHERALS - { -- class CPeripheralCecAdapterQueryThread; -+ class CPeripheralCecAdapterUpdateThread; - - typedef struct - { -@@ -61,7 +61,7 @@ - - class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread - { -- friend class CPeripheralCecAdapterQueryThread; -+ friend class CPeripheralCecAdapterUpdateThread; - - public: - CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); -@@ -116,26 +116,33 @@ - std::queue m_volumeChangeQueue; - unsigned int m_lastKeypress; - CecVolumeChange m_lastChange; -- CPeripheralCecAdapterQueryThread *m_queryThread; -+ CPeripheralCecAdapterUpdateThread*m_queryThread; - CEC::ICECCallbacks m_callbacks; - CCriticalSection m_critSection; - CEC::libcec_configuration m_configuration; - }; - -- class CPeripheralCecAdapterQueryThread : public CThread -+ class CPeripheralCecAdapterUpdateThread : public CThread - { - public: -- CPeripheralCecAdapterQueryThread(CPeripheralCecAdapter *adapter, bool bGetMenuLanguage); -- virtual ~CPeripheralCecAdapterQueryThread(void); -+ CPeripheralCecAdapterUpdateThread(CPeripheralCecAdapter *adapter, CEC::libcec_configuration *configuration); -+ virtual ~CPeripheralCecAdapterUpdateThread(void); - - virtual void Signal(void); -+ virtual bool UpdateConfiguration(CEC::libcec_configuration *configuration); - - protected: -+ virtual bool WaitReady(void); -+ virtual bool SetInitialConfiguration(void); - virtual void Process(void); - -- CPeripheralCecAdapter *m_adapter; -- CEvent m_event; -- bool m_bGetMenuLanguage; -+ CPeripheralCecAdapter * m_adapter; -+ CEvent m_event; -+ CCriticalSection m_critSection; -+ CEC::libcec_configuration m_configuration; -+ CEC::libcec_configuration m_nextConfiguration; -+ bool m_bNextConfigurationScheduled; -+ bool m_bIsUpdating; - }; - } - --- -1.7.5.4 - - -From e0206eb915349f7fc056cec7e80066a02af51edd Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Mon, 27 Feb 2012 20:49:08 +0100 -Subject: [PATCH 14/18] cec: don't send an inactive source message / standby - command directly when receiving the OnQuit - notification, but just stop the thread. fixes 'double - standby' commands being sent. bugzid: 439 - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 11 +---------- - 1 files changed, 1 insertions(+), 10 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index ef89bce..99346ae 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -107,16 +107,7 @@ void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, - { - if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit") && m_bIsReady) - { -- // only send power off and inactive source command when we're currently active -- if (m_cecAdapter->IsLibCECActiveSource()) -- { -- // if there are any devices to power off set, power them off -- if (!m_configuration.powerOffDevices.IsEmpty()) -- m_cecAdapter->StandbyDevices(CECDEVICE_BROADCAST); -- // send an inactive source command otherwise -- else -- m_cecAdapter->SetInactiveView(); -- } -+ StopThread(false); - } - else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && m_bIsReady) - { --- -1.7.5.4 - - -From fd9ba787f368b2eeee89b290b580a93443a804e9 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Mon, 27 Feb 2012 21:58:10 +0100 -Subject: [PATCH 15/18] cec: added an option to configure whether or not to - send an 'inactive source' message. bugzid: 439 - ---- - language/Dutch/strings.xml | 3 +++ - language/English/strings.xml | 1 + - lib/libcec/Makefile | 2 +- - project/BuildDependencies/scripts/libcec_d.txt | 2 +- - system/peripherals.xml | 21 +++++++++++---------- - tools/darwin/depends/libcec/Makefile | 2 +- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 17 +++++++++++------ - 7 files changed, 29 insertions(+), 19 deletions(-) - -diff --git a/language/Dutch/strings.xml b/language/Dutch/strings.xml -index 545cc33..8452a88 100644 -\ No newline at end of file -diff --git a/language/English/strings.xml b/language/English/strings.xml -index 1dc30d9..c60e728 100644 ---- a/language/English/strings.xml -+++ b/language/English/strings.xml -@@ -2411,4 +2411,5 @@ - COM port (leave empty unless needed) - Configuration updated - Failed to set the new configuration. Please check your settings. -+ Send 'inactive source' command when stopping XBMC - -diff --git a/lib/libcec/Makefile b/lib/libcec/Makefile -index d9af688..27eb5d2 100644 ---- a/lib/libcec/Makefile -+++ b/lib/libcec/Makefile -@@ -7,7 +7,7 @@ - - # lib name, version - LIBNAME=libcec --VERSION=1.5.0 -+VERSION=1.5.1 - SOURCE=$(LIBNAME)-$(VERSION) - - # download location and format -diff --git a/project/BuildDependencies/scripts/libcec_d.txt b/project/BuildDependencies/scripts/libcec_d.txt -index 0f70461..9aa0d55 100644 -diff --git a/system/peripherals.xml b/system/peripherals.xml -index 1df6f1a..c6852f7 100644 ---- a/system/peripherals.xml -+++ b/system/peripherals.xml -@@ -10,18 +10,19 @@ - - - -- -- -- -+ -+ -+ - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ - -- -+ - - - -diff --git a/tools/darwin/depends/libcec/Makefile b/tools/darwin/depends/libcec/Makefile -index be4ee35..abba42d 100644 ---- a/tools/darwin/depends/libcec/Makefile -+++ b/tools/darwin/depends/libcec/Makefile -@@ -2,7 +2,7 @@ include ../Makefile.include - - # lib name, version - LIBNAME=libcec --VERSION=1.5.0 -+VERSION=1.5.1 - SOURCE=$(LIBNAME)-$(VERSION) - ARCHIVE=$(SOURCE).tar.gz - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index 99346ae..a8fbf48 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -309,7 +309,7 @@ void CPeripheralCecAdapter::Process(void) - { - if (m_configuration.bPowerOffOnStandby == 1) - m_cecAdapter->StandbyDevices(); -- else -+ else if (m_configuration.bSendInactiveSource == 1) - m_cecAdapter->SetInactiveView(); - } - -@@ -956,23 +956,27 @@ void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configu - SetSetting("wake_devices", strPowerOffDevices.Trim()); - - // set the boolean settings -- m_configuration.bUseTVMenuLanguage = m_configuration.bUseTVMenuLanguage; -+ m_configuration.bUseTVMenuLanguage = config.bUseTVMenuLanguage; - SetSetting("use_tv_menu_language", m_configuration.bUseTVMenuLanguage == 1); - -- m_configuration.bActivateSource = m_configuration.bActivateSource; -+ m_configuration.bActivateSource = config.bActivateSource; - SetSetting("activate_source", m_configuration.bActivateSource == 1); - -- m_configuration.bPowerOffScreensaver = m_configuration.bPowerOffScreensaver; -+ m_configuration.bPowerOffScreensaver = config.bPowerOffScreensaver; - SetSetting("cec_standby_screensaver", m_configuration.bPowerOffScreensaver == 1); - -- m_configuration.bPowerOffOnStandby = m_configuration.bPowerOffOnStandby; -+ m_configuration.bPowerOffOnStandby = config.bPowerOffOnStandby; - SetSetting("standby_pc_on_tv_standby", m_configuration.bPowerOffOnStandby == 1); -+ -+ if (config.serverVersion >= CEC_SERVER_VERSION_1_5_1) -+ m_configuration.bSendInactiveSource = config.bSendInactiveSource; -+ SetSetting("send_inactive_source", m_configuration.bSendInactiveSource == 1); - } - - void CPeripheralCecAdapter::SetConfigurationFromSettings(void) - { - // client version 1.5.0 -- m_configuration.clientVersion = CEC_CLIENT_VERSION_1_5_0; -+ m_configuration.clientVersion = CEC_CLIENT_VERSION_1_5_1; - - // device name 'XBMC' - snprintf(m_configuration.strDeviceName, 13, "%s", GetSettingString("device_name").c_str()); -@@ -1030,6 +1034,7 @@ void CPeripheralCecAdapter::SetConfigurationFromSettings(void) - m_configuration.bActivateSource = GetSettingBool("activate_source") ? 1 : 0; - m_configuration.bPowerOffScreensaver = GetSettingBool("cec_standby_screensaver") ? 1 : 0; - m_configuration.bPowerOffOnStandby = GetSettingBool("standby_pc_on_tv_standby") ? 1 : 0; -+ m_configuration.bSendInactiveSource = GetSettingBool("send_inactive_source") ? 1 : 0; - } - - void CPeripheralCecAdapter::ReadLogicalAddresses(const CStdString &strString, cec_logical_addresses &addresses) --- -1.7.5.4 - - -From 0eccc2b66ec49b9fbee7bbe9d0894e8b3658cf7a Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Mon, 27 Feb 2012 22:13:45 +0100 -Subject: [PATCH 16/18] cec: don't send standby or inactive source messages - when rebooting - ---- - xbmc/Application.cpp | 3 +- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 28 ++++++++++++++++---- - xbmc/peripherals/devices/PeripheralCecAdapter.h | 1 + - 3 files changed, 25 insertions(+), 7 deletions(-) - -diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp -index c09c6d9..2b50388 100644 ---- a/xbmc/Application.cpp -+++ b/xbmc/Application.cpp -@@ -3308,7 +3308,8 @@ void CApplication::Stop(int exitCode) - { - try - { -- CAnnouncementManager::Announce(System, "xbmc", "OnQuit"); -+ CVariant vExitCode(exitCode); -+ CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode); - - // cancel any jobs from the jobmanager - CJobManager::GetInstance().CancelJobs(); -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index a8fbf48..ca5ada1 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -33,6 +33,7 @@ - #include "settings/GUISettings.h" - #include "settings/Settings.h" - #include "utils/log.h" -+#include "utils/Variant.h" - - #include - -@@ -77,7 +78,8 @@ class DllLibCEC : public DllDynamic, DllLibCECInterface - m_bHasConnectedAudioSystem(false), - m_strMenuLanguage("???"), - m_lastKeypress(0), -- m_lastChange(VOLUME_CHANGE_NONE) -+ m_lastChange(VOLUME_CHANGE_NONE), -+ m_iExitCode(0) - { - m_button.iButton = 0; - m_button.iDuration = 0; -@@ -107,6 +109,7 @@ void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, - { - if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit") && m_bIsReady) - { -+ m_iExitCode = data.asInteger(0); - StopThread(false); - } - else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && m_bIsReady) -@@ -305,12 +308,25 @@ void CPeripheralCecAdapter::Process(void) - - delete m_queryThread; - -- if (m_cecAdapter->IsLibCECActiveSource()) -+ if (m_iExitCode != EXITCODE_REBOOT) - { -- if (m_configuration.bPowerOffOnStandby == 1) -- m_cecAdapter->StandbyDevices(); -- else if (m_configuration.bSendInactiveSource == 1) -- m_cecAdapter->SetInactiveView(); -+ if (m_cecAdapter->IsLibCECActiveSource()) -+ { -+ if (!m_configuration.powerOffDevices.IsEmpty()) -+ { -+ CLog::Log(LOGDEBUG, "%s - sending standby commands", __FUNCTION__); -+ m_cecAdapter->StandbyDevices(); -+ } -+ else if (m_configuration.bSendInactiveSource == 1) -+ { -+ CLog::Log(LOGDEBUG, "%s - sending inactive source commands", __FUNCTION__); -+ m_cecAdapter->SetInactiveView(); -+ } -+ } -+ else -+ { -+ CLog::Log(LOGDEBUG, "%s - XBMC is not the active source, not sending any standby commands", __FUNCTION__); -+ } - } - - m_cecAdapter->Close(); -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h -index 1eadca2..7a9d8e8 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.h -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h -@@ -116,6 +116,7 @@ - std::queue m_volumeChangeQueue; - unsigned int m_lastKeypress; - CecVolumeChange m_lastChange; -+ int m_iExitCode; - CPeripheralCecAdapterUpdateThread*m_queryThread; - CEC::ICECCallbacks m_callbacks; - CCriticalSection m_critSection; --- -1.7.5.4 - - -From 04dee9642a307adc62d07c6cab6b721e414ab0fd Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Mon, 19 Mar 2012 16:50:03 +0100 -Subject: [PATCH 17/18] cec: get libCEC-latest from packages.pulse-eight.net, - so it can be updated separately, e.g. to add vendor - support - ---- - lib/libcec/Makefile | 30 ++++++++++++------------ - project/BuildDependencies/scripts/libcec_d.txt | 2 +- - tools/darwin/depends/libcec/Makefile | 26 ++++++++++---------- - 3 files changed, 29 insertions(+), 29 deletions(-) - -diff --git a/lib/libcec/Makefile b/lib/libcec/Makefile -index 27eb5d2..ec307c4 100644 ---- a/lib/libcec/Makefile -+++ b/lib/libcec/Makefile -@@ -7,17 +7,17 @@ - - # lib name, version - LIBNAME=libcec --VERSION=1.5.1 -+VERSION=latest - SOURCE=$(LIBNAME)-$(VERSION) - - # download location and format --BASE_URL=http://mirrors.xbmc.org/build-deps/darwin-libs --ARCHIVE=$(SOURCE).tar.gz -+BASE_URL=http://packages.pulse-eight.net/pulse/sources/libcec -+ARCHIVE=$(SOURCE).tar.bz2 - TARBALLS_LOCATION=. - RETRIEVE_TOOL=/usr/bin/curl - RETRIEVE_TOOL_FLAGS=-Ls --create-dirs --output $(TARBALLS_LOCATION)/$(ARCHIVE) - ARCHIVE_TOOL=tar --ARCHIVE_TOOL_FLAGS=xf -+ARCHIVE_TOOL_FLAGS=jxf - - PREFIX ?= /usr/local - LIBCEC_CONFIGOPTS ?= --prefix=$(PREFIX) -@@ -25,30 +25,30 @@ LIBCEC_CONFIGOPTS ?= --prefix=$(PREFIX) - # configuration settings - CONFIGURE=./configure CFLAGS=-D_FILE_OFFSET_BITS=64 $(LIBCEC_CONFIGOPTS) - --SO_NAME=$(SOURCE)/.libs/$(LIBNAME).so -+SO_NAME=$(LIBNAME)/.libs/$(LIBNAME).so - - all: $(SO_NAME) - - $(TARBALLS_LOCATION)/$(ARCHIVE): - $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) - --$(SOURCE): $(TARBALLS_LOCATION)/$(ARCHIVE) -- rm -rf $(SOURCE) -+$(LIBNAME): $(TARBALLS_LOCATION)/$(ARCHIVE) -+ rm -rf $(LIBNAME) - $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) -- echo $(SOURCE) > .gitignore -- cd $(SOURCE); autoreconf -vif -- cd $(SOURCE); $(CONFIGURE) -+ echo $(LIBNAME) > .gitignore -+ cd $(LIBNAME); autoreconf -vif -+ cd $(LIBNAME); $(CONFIGURE) - --$(SO_NAME): $(SOURCE) -- make -j 1 -C $(SOURCE) -+$(SO_NAME): $(LIBNAME) -+ make -j 1 -C $(LIBNAME) - - install: -- make -C $(SOURCE) install -+ make -C $(LIBNAME) install - ldconfig - - clean: -- rm -rf $(SOURCE) -+ rm -rf $(LIBNAME) - - distclean:: -- rm -rf $(SOURCE) -+ rm -rf $(LIBNAME) - -diff --git a/project/BuildDependencies/scripts/libcec_d.txt b/project/BuildDependencies/scripts/libcec_d.txt -index 9aa0d55..daa4e75 100644 -diff --git a/tools/darwin/depends/libcec/Makefile b/tools/darwin/depends/libcec/Makefile -index abba42d..2eaa7f6 100644 ---- a/tools/darwin/depends/libcec/Makefile -+++ b/tools/darwin/depends/libcec/Makefile -@@ -2,37 +2,37 @@ include ../Makefile.include - - # lib name, version - LIBNAME=libcec --VERSION=1.5.1 -+VERSION=latest - SOURCE=$(LIBNAME)-$(VERSION) --ARCHIVE=$(SOURCE).tar.gz -+ARCHIVE=$(SOURCE).tar.bz2 - - # configuration settings - CONFIGURE=./configure --prefix=$(PREFIX) - --LIBDYLIB=$(SOURCE)/.libs/$(LIBNAME).dylib -+LIBDYLIB=$(LIBNAME)/.libs/$(LIBNAME).dylib - - all: $(LIBDYLIB) .installed - - $(TARBALLS_LOCATION)/$(ARCHIVE): - $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) - --$(SOURCE): $(TARBALLS_LOCATION)/$(ARCHIVE) -- rm -rf $(SOURCE) -+$(LIBNAME): $(TARBALLS_LOCATION)/$(ARCHIVE) -+ rm -rf $(LIBNAME) - $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) -- echo $(SOURCE) > .gitignore -- cd $(SOURCE); autoreconf -vif -- cd $(SOURCE); $(CONFIGURE) -+ echo $(LIBNAME) > .gitignore -+ cd $(LIBNAME); autoreconf -vif -+ cd $(LIBNAME); $(CONFIGURE) - --$(LIBDYLIB): $(SOURCE) -- make -j 1 -C $(SOURCE) -+$(LIBDYLIB): $(LIBNAME) -+ make -j 1 -C $(LIBNAME) - - .installed: -- make -C $(SOURCE) install -+ make -C $(LIBNAME) install - touch $@ - - clean: -- rm -rf $(SOURCE) .installed -+ rm -rf $(LIBNAME) .installed - - distclean:: -- rm -rf $(SOURCE) .installed -+ rm -rf $(LIBNAME) .installed - --- -1.7.5.4 - - -From 2486a8c6a9a9ecdd801777729c3315cd543e7061 Mon Sep 17 00:00:00 2001 -From: Lars Op den Kamp -Date: Tue, 20 Mar 2012 15:30:01 +0100 -Subject: [PATCH 18/18] cec: don't send an updated configuration to libCEC - when stopping the update thread - ---- - xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - -diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -index ca5ada1..093675e 100644 ---- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp -@@ -1197,6 +1197,8 @@ void CPeripheralCecAdapterUpdateThread::Process(void) - // update received - if (m_event.WaitMSec(500) || bUpdate) - { -+ if (m_bStop) -+ return; - // set the new configuration - bool bConfigSet(m_adapter->m_cecAdapter->SetConfiguration(&m_configuration)); - CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(bConfigSet ? 36023 : 36024)); --- -1.7.5.4 - diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.01-cec-PR570.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.01-cec-PR570.patch new file mode 100644 index 0000000000..0a68955141 --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.01-cec-PR570.patch @@ -0,0 +1,1975 @@ +diff -Naur xbmc-pvr-11.0.1/configure.in xbmc-pvr-11.0.1.patch/configure.in +--- xbmc-pvr-11.0.1/configure.in 2012-03-27 17:55:54.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/configure.in 2012-04-17 14:03:25.176271190 +0200 +@@ -1173,7 +1173,7 @@ + + # libcec is dyloaded, so we need to check for its headers and link any depends. + if test "x$use_libcec" != "xno"; then +- PKG_CHECK_MODULES([CEC],[libcec >= 1.1.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) ++ PKG_CHECK_MODULES([CEC],[libcec >= 1.5.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) + + if test "x$use_libcec" != "xno"; then + INCLUDES="$INCLUDES $CEC_CFLAGS" +diff -Naur xbmc-pvr-11.0.1/language/English/strings.xml xbmc-pvr-11.0.1.patch/language/English/strings.xml +--- xbmc-pvr-11.0.1/language/English/strings.xml 2012-03-27 17:55:51.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/language/English/strings.xml 2012-04-17 14:03:25.195271549 +0200 +@@ -2831,6 +2831,7 @@ + Device removed + Keymap to use for this device + Keymap enabled ++ Do not use the custom keymap for this device + + Location + Class +@@ -2845,16 +2846,23 @@ + Press "user" button command + Enable switch side commands + Could not open the adapter +- Power on the TV when starting XBMC +- Power off devices when stopping XBMC ++ Devices to power on the TV when starting XBMC ++ Devices to power off devices when stopping XBMC + Put devices in standby mode when activating screensaver + + Could not detect the CEC port. Set it up manually. +- Could not detect the CEC adapter. +- Unsupported libcec interface version. %d is greater than the version XBMC supports (%d) ++ Could not initialise the CEC adapter. Check your settings. ++ Unsupported libCEC interface version. %d is greater than the version XBMC supports (%d) + Put this PC in standby mode when the TV is switched off + HDMI port number + Connected +- Adapter found, but libcec is not available ++ Adapter found, but libCEC is not available + Use the TV's language setting ++ Connected to HDMI device ++ Make XBMC the active source when starting ++ Physical address (overrules HDMI port) ++ COM port (leave empty unless needed) ++ Configuration updated ++ Failed to set the new configuration. Please check your settings. ++ Send 'inactive source' command when stopping XBMC + +diff -Naur xbmc-pvr-11.0.1/lib/libcec/Makefile xbmc-pvr-11.0.1.patch/lib/libcec/Makefile +--- xbmc-pvr-11.0.1/lib/libcec/Makefile 2012-03-27 17:55:40.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/lib/libcec/Makefile 2012-04-17 14:03:25.202271682 +0200 +@@ -7,17 +7,17 @@ + + # lib name, version + LIBNAME=libcec +-VERSION=1.2.0 ++VERSION=latest + SOURCE=$(LIBNAME)-$(VERSION) + + # download location and format +-BASE_URL=http://mirrors.xbmc.org/build-deps/darwin-libs +-ARCHIVE=$(SOURCE).tar.gz ++BASE_URL=http://packages.pulse-eight.net/pulse/sources/libcec ++ARCHIVE=$(SOURCE).tar.bz2 + TARBALLS_LOCATION=. + RETRIEVE_TOOL=/usr/bin/curl + RETRIEVE_TOOL_FLAGS=-Ls --create-dirs --output $(TARBALLS_LOCATION)/$(ARCHIVE) + ARCHIVE_TOOL=tar +-ARCHIVE_TOOL_FLAGS=xf ++ARCHIVE_TOOL_FLAGS=jxf + + PREFIX ?= /usr/local + LIBCEC_CONFIGOPTS ?= --prefix=$(PREFIX) +@@ -25,30 +25,30 @@ + # configuration settings + CONFIGURE=./configure CFLAGS=-D_FILE_OFFSET_BITS=64 $(LIBCEC_CONFIGOPTS) + +-SO_NAME=$(SOURCE)/.libs/$(LIBNAME).so ++SO_NAME=$(LIBNAME)/.libs/$(LIBNAME).so + + all: $(SO_NAME) + + $(TARBALLS_LOCATION)/$(ARCHIVE): + $(RETRIEVE_TOOL) $(RETRIEVE_TOOL_FLAGS) $(BASE_URL)/$(ARCHIVE) + +-$(SOURCE): $(TARBALLS_LOCATION)/$(ARCHIVE) +- rm -rf $(SOURCE) ++$(LIBNAME): $(TARBALLS_LOCATION)/$(ARCHIVE) ++ rm -rf $(LIBNAME) + $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) +- echo $(SOURCE) > .gitignore +- cd $(SOURCE); autoreconf -vif +- cd $(SOURCE); $(CONFIGURE) ++ echo $(LIBNAME) > .gitignore ++ cd $(LIBNAME); autoreconf -vif ++ cd $(LIBNAME); $(CONFIGURE) + +-$(SO_NAME): $(SOURCE) +- make -j 1 -C $(SOURCE) ++$(SO_NAME): $(LIBNAME) ++ make -j 1 -C $(LIBNAME) + + install: +- make -C $(SOURCE) install ++ make -C $(LIBNAME) install + ldconfig + + clean: +- rm -rf $(SOURCE) ++ rm -rf $(LIBNAME) + + distclean:: +- rm -rf $(SOURCE) ++ rm -rf $(LIBNAME) + +diff -Naur xbmc-pvr-11.0.1/system/peripherals.xml xbmc-pvr-11.0.1.patch/system/peripherals.xml +--- xbmc-pvr-11.0.1/system/peripherals.xml 2012-03-27 17:55:54.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/system/peripherals.xml 2012-04-17 14:03:25.196271568 +0200 +@@ -1,22 +1,29 @@ + + +- ++ + +- +- +- +- ++ ++ ++ ++ + + +- +- +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + +diff -Naur xbmc-pvr-11.0.1/xbmc/Application.cpp xbmc-pvr-11.0.1.patch/xbmc/Application.cpp +--- xbmc-pvr-11.0.1/xbmc/Application.cpp 2012-03-27 17:55:35.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/Application.cpp 2012-04-17 14:06:37.605914462 +0200 +@@ -160,9 +160,6 @@ + #endif + #include "interfaces/AnnouncementManager.h" + #include "peripherals/Peripherals.h" +-#ifdef HAVE_LIBCEC +-#include "peripherals/devices/PeripheralCecAdapter.h" +-#endif + #include "peripherals/dialogs/GUIDialogPeripheralManager.h" + #include "peripherals/dialogs/GUIDialogPeripheralSettings.h" + +@@ -2618,6 +2615,9 @@ + } + } + ++ if (g_peripherals.OnAction(action)) ++ return true; ++ + if (action.GetID() == ACTION_MUTE) + { + ToggleMute(); +@@ -2893,23 +2893,9 @@ + + bool CApplication::ProcessPeripherals(float frameTime) + { +-#ifdef HAVE_LIBCEC +- vector peripherals; +- if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) +- { +- for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) +- { +- CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); +- if (cecDevice && cecDevice->GetButton()) +- { +- CKey key(cecDevice->GetButton(), cecDevice->GetHoldTime()); +- cecDevice->ResetButton(); +- return OnKey(key); +- } +- } +- } +-#endif +- ++ CKey key; ++ if (g_peripherals.GetNextKeypress(frameTime, key)) ++ return OnKey(key); + return false; + } + +@@ -3365,7 +3351,8 @@ + { + try + { +- CAnnouncementManager::Announce(System, "xbmc", "OnQuit"); ++ CVariant vExitCode(exitCode); ++ CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode); + + // cancel any jobs from the jobmanager + CJobManager::GetInstance().CancelJobs(); +@@ -5123,6 +5110,8 @@ + + bool CApplication::IsMuted() const + { ++ if (g_peripherals.IsMuted()) ++ return true; + return g_settings.m_bMute; + } + +@@ -5136,6 +5125,9 @@ + + void CApplication::Mute() + { ++ if (g_peripherals.Mute()) ++ return; ++ + g_settings.m_iPreMuteVolumeLevel = GetVolume(); + SetVolume(0); + g_settings.m_bMute = true; +@@ -5143,6 +5135,9 @@ + + void CApplication::UnMute() + { ++ if (g_peripherals.UnMute()) ++ return; ++ + SetVolume(g_settings.m_iPreMuteVolumeLevel); + g_settings.m_iPreMuteVolumeLevel = 0; + g_settings.m_bMute = false; +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.cpp 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.cpp 2012-04-17 14:03:25.211271852 +0200 +@@ -18,8 +18,8 @@ + * http://www.gnu.org/copyleft/gpl.html + * + */ +-#include "system.h" + ++#include "system.h" + #if defined(HAVE_LIBCEC) + #include "PeripheralCecAdapter.h" + #include "input/XBIRRemote.h" +@@ -31,36 +31,40 @@ + #include "peripherals/Peripherals.h" + #include "peripherals/bus/PeripheralBus.h" + #include "settings/GUISettings.h" ++#include "settings/Settings.h" + #include "utils/log.h" ++#include "utils/Variant.h" + +-#include ++#include + + using namespace PERIPHERALS; + using namespace ANNOUNCEMENT; + using namespace CEC; + +-#define CEC_LIB_SUPPORTED_VERSION 1 ++#define CEC_LIB_SUPPORTED_VERSION 0x1500 + + /* time in seconds to ignore standby commands from devices after the screensaver has been activated */ + #define SCREENSAVER_TIMEOUT 10 ++#define VOLUME_CHANGE_TIMEOUT 250 ++#define VOLUME_REFRESH_TIMEOUT 100 + + class DllLibCECInterface + { + public: + virtual ~DllLibCECInterface() {} +- virtual ICECAdapter* CECInit(const char *interfaceName, cec_device_type_list types)=0; +- virtual void* CECDestroy(ICECAdapter *adapter)=0; ++ virtual ICECAdapter* CECInitialise(libcec_configuration *configuration)=0; ++ virtual void* CECDestroy(ICECAdapter *adapter)=0; + }; + + class DllLibCEC : public DllDynamic, DllLibCECInterface + { + DECLARE_DLL_WRAPPER(DllLibCEC, DLL_PATH_LIBCEC) + +- DEFINE_METHOD2(ICECAdapter*, CECInit, (const char *p1, cec_device_type_list p2)) +- DEFINE_METHOD1(void* , CECDestroy, (ICECAdapter *p1)) ++ DEFINE_METHOD1(ICECAdapter*, CECInitialise, (libcec_configuration *p1)) ++ DEFINE_METHOD1(void* , CECDestroy, (ICECAdapter *p1)) + + BEGIN_METHOD_RESOLVE() +- RESOLVE_METHOD_RENAME(CECInit, CECInit) ++ RESOLVE_METHOD_RENAME(CECInitialise, CECInitialise) + RESOLVE_METHOD_RENAME(CECDestroy, CECDestroy) + END_METHOD_RESOLVE() + }; +@@ -71,41 +75,19 @@ + m_bStarted(false), + m_bHasButton(false), + m_bIsReady(false), ++ m_bHasConnectedAudioSystem(false), + m_strMenuLanguage("???"), +- m_lastKeypress(0) ++ m_lastKeypress(0), ++ m_lastChange(VOLUME_CHANGE_NONE), ++ m_iExitCode(0), ++ m_bIsMuted(false) // TODO fetch the correct initial value when system audiostatus is implemented in libCEC + { + m_button.iButton = 0; + m_button.iDuration = 0; + m_screensaverLastActivated.SetValid(false); +- m_dll = new DllLibCEC; +- if (m_dll->Load() && m_dll->IsLoaded()) +- { +- cec_device_type_list typeList; +- typeList.clear(); +- typeList.add(CEC_DEVICE_TYPE_RECORDING_DEVICE); +- m_cecAdapter = m_dll->CECInit("XBMC", typeList); +- } +- else +- m_cecAdapter = NULL; +- +- if (!m_cecAdapter || m_cecAdapter->GetMinLibVersion() > CEC_LIB_SUPPORTED_VERSION) +- { +- /* unsupported libcec version */ +- CLog::Log(LOGERROR, g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_cecAdapter->GetMinLibVersion() : -1); + +- CStdString strMessage; +- strMessage.Format(g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_cecAdapter->GetMinLibVersion() : -1); +- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), strMessage); +- m_bError = true; +- if (m_cecAdapter) +- m_dll->CECDestroy(m_cecAdapter); +- m_cecAdapter = NULL; +- } +- else +- { +- CLog::Log(LOGDEBUG, "%s - using libCEC v%d.%d", __FUNCTION__, m_cecAdapter->GetLibVersionMajor(), m_cecAdapter->GetLibVersionMinor()); +- m_features.push_back(FEATURE_CEC); +- } ++ m_configuration.Clear(); ++ m_features.push_back(FEATURE_CEC); + } + + CPeripheralCecAdapter::~CPeripheralCecAdapter(void) +@@ -117,7 +99,6 @@ + + if (m_dll && m_cecAdapter) + { +- FlushLog(); + m_dll->CECDestroy(m_cecAdapter); + m_cecAdapter = NULL; + delete m_dll; +@@ -129,60 +110,94 @@ + { + if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit") && m_bIsReady) + { +- m_cecAdapter->SetInactiveView(); +- if (GetSettingBool("cec_power_off_shutdown")) +- m_cecAdapter->StandbyDevices(); ++ m_iExitCode = data.asInteger(0); ++ StopThread(false); + } +- else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && GetSettingBool("cec_standby_screensaver") && m_bIsReady) ++ else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && m_bIsReady) + { +- m_cecAdapter->PowerOnDevices(); ++ if (m_configuration.bPowerOffScreensaver == 1) ++ { ++ // power off/on on screensaver is set, and devices to wake are set ++ if (!m_configuration.wakeDevices.IsEmpty()) ++ m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); ++ ++ // the option to make XBMC the active source is set ++ if (m_configuration.bActivateSource == 1) ++ m_cecAdapter->SetActiveSource(); ++ } + } +- else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && GetSettingBool("cec_standby_screensaver")) ++ else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && m_bIsReady) + { + // Don't put devices to standby if application is currently playing +- if (!g_application.IsPlaying() || g_application.IsPaused()) ++ if ((!g_application.IsPlaying() || g_application.IsPaused()) && m_configuration.bPowerOffScreensaver == 1) + { + m_screensaverLastActivated = CDateTime::GetCurrentDateTime(); +- m_cecAdapter->StandbyDevices(); ++ // only power off when we're the active source ++ if (m_cecAdapter->IsLibCECActiveSource()) ++ m_cecAdapter->StandbyDevices(CECDEVICE_BROADCAST); + } + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) + { +- if (GetSettingBool("cec_power_off_shutdown") && m_bIsReady) +- m_cecAdapter->StandbyDevices(); ++ // this will also power off devices when we're the active source + CSingleLock lock(m_critSection); + m_bStop = true; + WaitForThreadExit(0); + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) + { ++ // reconnect to the device + CSingleLock lock(m_critSection); + CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); ++ ++ // close the previous connection + m_cecAdapter->Close(); + +- CStdString strPort = GetComPort(); +- if (!strPort.empty()) +- { +- if (!m_cecAdapter->Open(strPort.c_str(), 10000)) +- { +- CLog::Log(LOGERROR, "%s - failed to reconnect to the CEC adapter", __FUNCTION__); +- FlushLog(); +- m_bStop = true; +- } +- else +- { +- if (GetSettingBool("cec_power_on_startup")) +- PowerOnCecDevices(CECDEVICE_TV); +- m_cecAdapter->SetActiveView(); +- } +- } ++ // and open a new one ++ m_bStop = false; ++ Create(); + } + } + + bool CPeripheralCecAdapter::InitialiseFeature(const PeripheralFeature feature) + { +- if (feature == FEATURE_CEC && !m_bStarted) ++ if (feature == FEATURE_CEC && !m_bStarted && GetSettingBool("enabled")) + { ++ SetConfigurationFromSettings(); ++ m_callbacks.CBCecLogMessage = &CecLogMessage; ++ m_callbacks.CBCecKeyPress = &CecKeyPress; ++ m_callbacks.CBCecCommand = &CecCommand; ++ m_callbacks.CBCecConfigurationChanged = &CecConfiguration; ++ m_configuration.callbackParam = this; ++ m_configuration.callbacks = &m_callbacks; ++ ++ m_dll = new DllLibCEC; ++ if (m_dll->Load() && m_dll->IsLoaded()) ++ m_cecAdapter = m_dll->CECInitialise(&m_configuration); ++ else ++ return false; ++ ++ if (m_configuration.serverVersion < CEC_LIB_SUPPORTED_VERSION) ++ { ++ /* unsupported libcec version */ ++ CLog::Log(LOGERROR, g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_configuration.serverVersion : -1); ++ ++ CStdString strMessage; ++ strMessage.Format(g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecAdapter ? m_configuration.serverVersion : -1); ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), strMessage); ++ m_bError = true; ++ if (m_cecAdapter) ++ m_dll->CECDestroy(m_cecAdapter); ++ m_cecAdapter = NULL; ++ ++ m_features.clear(); ++ return false; ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, "%s - using libCEC v%s", __FUNCTION__, m_cecAdapter->ToString((cec_server_version)m_configuration.serverVersion)); ++ } ++ + m_bStarted = true; + Create(); + } +@@ -221,23 +236,20 @@ + return strPort; + } + +-void CPeripheralCecAdapter::Process(void) ++bool CPeripheralCecAdapter::OpenConnection(void) + { ++ bool bIsOpen(false); ++ + if (!GetSettingBool("enabled")) + { + CLog::Log(LOGDEBUG, "%s - CEC adapter is disabled in peripheral settings", __FUNCTION__); + m_bStarted = false; +- return; ++ return bIsOpen; + } + + CStdString strPort = GetComPort(); + if (strPort.empty()) +- return; +- +- // set correct physical address from peripheral settings +- int iHdmiPort = GetSettingInt("cec_hdmi_port"); +- SetHdmiPort(iHdmiPort); +- FlushLog(); ++ return bIsOpen; + + // open the CEC adapter + CLog::Log(LOGDEBUG, "%s - opening a connection to the CEC adapter: %s", __FUNCTION__, strPort.c_str()); +@@ -247,100 +259,221 @@ + strMessage.Format(g_localizeStrings.Get(21336), g_localizeStrings.Get(36000)); + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strMessage); + +- if (!m_cecAdapter->Open(strPort.c_str(), 10000)) +- { +- FlushLog(); +- CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__); +- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); +- m_bStarted = false; +- return; +- } ++ bool bConnectionFailedDisplayed(false); + +- CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); +- m_bIsReady = true; +- CAnnouncementManager::AddAnnouncer(this); +- +- if (GetSettingBool("cec_power_on_startup")) ++ while (!m_bStop && !bIsOpen) + { +- PowerOnCecDevices(CECDEVICE_TV); +- FlushLog(); ++ if ((bIsOpen = m_cecAdapter->Open(strPort.c_str(), 10000)) == false) ++ { ++ CLog::Log(LOGERROR, "%s - could not opening a connection to the CEC adapter", __FUNCTION__); ++ if (!bConnectionFailedDisplayed) ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); ++ bConnectionFailedDisplayed = true; ++ ++ Sleep(10000); ++ } + } + +- if (GetSettingBool("use_tv_menu_language")) ++ if (bIsOpen) + { +- cec_menu_language language; +- if (m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) +- SetMenuLanguage(language.language); ++ CLog::Log(LOGDEBUG, "%s - connection to the CEC adapter opened", __FUNCTION__); ++ ++ if (!m_configuration.wakeDevices.IsEmpty()) ++ m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); ++ ++ if (m_configuration.bActivateSource == 1) ++ m_cecAdapter->SetActiveSource(); + } + +- m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); +- CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(36016)); ++ return bIsOpen; ++} ++ ++void CPeripheralCecAdapter::Process(void) ++{ ++ if (!OpenConnection()) ++ return; ++ ++ CAnnouncementManager::AddAnnouncer(this); ++ ++ m_queryThread = new CPeripheralCecAdapterUpdateThread(this, &m_configuration); ++ m_queryThread->Create(false); + + while (!m_bStop) + { +- FlushLog(); + if (!m_bStop) +- ProcessNextCommand(); ++ ProcessVolumeChange(); ++ + if (!m_bStop) + Sleep(5); + } + ++ delete m_queryThread; ++ ++ if (m_iExitCode != EXITCODE_REBOOT) ++ { ++ if (m_cecAdapter->IsLibCECActiveSource()) ++ { ++ if (!m_configuration.powerOffDevices.IsEmpty()) ++ { ++ CLog::Log(LOGDEBUG, "%s - sending standby commands", __FUNCTION__); ++ m_cecAdapter->StandbyDevices(); ++ } ++ else if (m_configuration.bSendInactiveSource == 1) ++ { ++ CLog::Log(LOGDEBUG, "%s - sending inactive source commands", __FUNCTION__); ++ m_cecAdapter->SetInactiveView(); ++ } ++ } ++ else ++ { ++ CLog::Log(LOGDEBUG, "%s - XBMC is not the active source, not sending any standby commands", __FUNCTION__); ++ } ++ } ++ + m_cecAdapter->Close(); + + CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__); + m_bStarted = false; + } + +-bool CPeripheralCecAdapter::PowerOnCecDevices(cec_logical_address iLogicalAddress) ++bool CPeripheralCecAdapter::HasConnectedAudioSystem(void) + { +- bool bReturn(false); ++ CSingleLock lock(m_critSection); ++ return m_bHasConnectedAudioSystem; ++} + +- if (m_cecAdapter && m_bIsReady) ++void CPeripheralCecAdapter::SetAudioSystemConnected(bool bSetTo) ++{ ++ CSingleLock lock(m_critSection); ++ m_bHasConnectedAudioSystem = bSetTo; ++} ++ ++void CPeripheralCecAdapter::ScheduleVolumeUp(void) ++{ + { +- CLog::Log(LOGDEBUG, "%s - powering on CEC capable device with address %1x", __FUNCTION__, iLogicalAddress); +- bReturn = m_cecAdapter->PowerOnDevices(iLogicalAddress); ++ CSingleLock lock(m_critSection); ++ m_volumeChangeQueue.push(VOLUME_CHANGE_UP); + } ++ Sleep(5); ++} + +- return bReturn; ++void CPeripheralCecAdapter::ScheduleVolumeDown(void) ++{ ++ { ++ CSingleLock lock(m_critSection); ++ m_volumeChangeQueue.push(VOLUME_CHANGE_DOWN); ++ } ++ Sleep(5); + } + +-bool CPeripheralCecAdapter::StandbyCecDevices(cec_logical_address iLogicalAddress) ++void CPeripheralCecAdapter::ScheduleMute(void) + { +- bool bReturn(false); ++ { ++ CSingleLock lock(m_critSection); ++ m_volumeChangeQueue.push(VOLUME_CHANGE_MUTE); ++ } ++ Sleep(5); ++} + +- if (m_cecAdapter && m_bIsReady) ++void CPeripheralCecAdapter::ProcessVolumeChange(void) ++{ ++ bool bSendRelease(false); ++ CecVolumeChange pendingVolumeChange = VOLUME_CHANGE_NONE; + { +- CLog::Log(LOGDEBUG, "%s - putting CEC capable devices with address %1x in standby mode", __FUNCTION__, iLogicalAddress); +- bReturn = m_cecAdapter->StandbyDevices(iLogicalAddress); ++ CSingleLock lock(m_critSection); ++ if (m_volumeChangeQueue.size() > 0) ++ { ++ /* get the first change from the queue */ ++ pendingVolumeChange = m_volumeChangeQueue.front(); ++ m_volumeChangeQueue.pop(); ++ ++ /* remove all dupe entries */ ++ while (m_volumeChangeQueue.size() > 0 && m_volumeChangeQueue.front() == pendingVolumeChange) ++ m_volumeChangeQueue.pop(); ++ ++ /* send another keypress after VOLUME_REFRESH_TIMEOUT ms */ ++ bool bRefresh(m_lastKeypress + VOLUME_REFRESH_TIMEOUT < XbmcThreads::SystemClockMillis()); ++ ++ /* only send the keypress when it hasn't been sent yet */ ++ if (pendingVolumeChange != m_lastChange) ++ { ++ m_lastKeypress = XbmcThreads::SystemClockMillis(); ++ m_lastChange = pendingVolumeChange; ++ } ++ else if (bRefresh) ++ { ++ m_lastKeypress = XbmcThreads::SystemClockMillis(); ++ pendingVolumeChange = m_lastChange; ++ } ++ else ++ pendingVolumeChange = VOLUME_CHANGE_NONE; ++ } ++ else if (m_lastKeypress > 0 && m_lastKeypress + VOLUME_CHANGE_TIMEOUT < XbmcThreads::SystemClockMillis()) ++ { ++ /* send a key release */ ++ m_lastKeypress = 0; ++ bSendRelease = true; ++ m_lastChange = VOLUME_CHANGE_NONE; ++ } + } + +- return bReturn; ++ switch (pendingVolumeChange) ++ { ++ case VOLUME_CHANGE_UP: ++ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_VOLUME_UP, false); ++ break; ++ case VOLUME_CHANGE_DOWN: ++ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_VOLUME_DOWN, false); ++ break; ++ case VOLUME_CHANGE_MUTE: ++ m_cecAdapter->SendKeypress(CECDEVICE_AUDIOSYSTEM, CEC_USER_CONTROL_CODE_MUTE, false); ++ { ++ CSingleLock lock(m_critSection); ++ m_bIsMuted = !m_bIsMuted; ++ } ++ break; ++ case VOLUME_CHANGE_NONE: ++ if (bSendRelease) ++ m_cecAdapter->SendKeyRelease(CECDEVICE_AUDIOSYSTEM, false); ++ break; ++ } + } + +-bool CPeripheralCecAdapter::SendPing(void) ++void CPeripheralCecAdapter::VolumeUp(void) + { +- bool bReturn(false); +- if (m_cecAdapter && m_bIsReady) ++ if (HasConnectedAudioSystem()) + { +- CLog::Log(LOGDEBUG, "%s - sending ping to the CEC adapter", __FUNCTION__); +- bReturn = m_cecAdapter->PingAdapter(); ++ CSingleLock lock(m_critSection); ++ m_volumeChangeQueue.push(VOLUME_CHANGE_UP); + } ++} + +- return bReturn; ++void CPeripheralCecAdapter::VolumeDown(void) ++{ ++ if (HasConnectedAudioSystem()) ++ { ++ CSingleLock lock(m_critSection); ++ m_volumeChangeQueue.push(VOLUME_CHANGE_DOWN); ++ } + } + +-bool CPeripheralCecAdapter::SetHdmiPort(int iHdmiPort) ++void CPeripheralCecAdapter::Mute(void) + { +- bool bReturn(false); +- if (m_cecAdapter && m_bIsReady) ++ if (HasConnectedAudioSystem()) + { +- if (iHdmiPort <= 0 || iHdmiPort > 16) +- iHdmiPort = 1; +- CLog::Log(LOGDEBUG, "%s - changing active HDMI port to %d", __FUNCTION__, iHdmiPort); +- bReturn = m_cecAdapter->SetPhysicalAddress(iHdmiPort << 12); ++ CSingleLock lock(m_critSection); ++ m_volumeChangeQueue.push(VOLUME_CHANGE_MUTE); + } ++} + +- return bReturn; ++bool CPeripheralCecAdapter::IsMuted(void) ++{ ++ if (HasConnectedAudioSystem()) ++ { ++ CSingleLock lock(m_critSection); ++ return m_bIsMuted; ++ } ++ return false; + } + + void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage) +@@ -404,10 +537,13 @@ + CLog::Log(LOGWARNING, "%s - TV menu language set to unknown value '%s'", __FUNCTION__, strLanguage); + } + +-void CPeripheralCecAdapter::ProcessNextCommand(void) ++int CPeripheralCecAdapter::CecCommand(void *cbParam, const cec_command &command) + { +- cec_command command; +- if (m_cecAdapter && m_bIsReady && m_cecAdapter->GetNextCommand(&command)) ++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; ++ if (!adapter) ++ return 0; ++ ++ if (adapter->m_bIsReady) + { + CLog::Log(LOGDEBUG, "%s - processing command: initiator=%1x destination=%1x opcode=%02x", __FUNCTION__, command.initiator, command.destination, command.opcode); + +@@ -416,21 +552,21 @@ + case CEC_OPCODE_STANDBY: + /* a device was put in standby mode */ + CLog::Log(LOGDEBUG, "%s - device %1x was put in standby mode", __FUNCTION__, command.initiator); +- if (command.initiator == CECDEVICE_TV && GetSettingBool("standby_pc_on_tv_standby") && +- (!m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT))) ++ if (command.initiator == CECDEVICE_TV && adapter->m_configuration.bPowerOffOnStandby == 1 && ++ (!adapter->m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT))) + { +- m_bStarted = false; ++ adapter->m_bStarted = false; + g_application.getApplicationMessenger().Suspend(); + } + break; + case CEC_OPCODE_SET_MENU_LANGUAGE: +- if (GetSettingBool("use_tv_menu_language") && command.initiator == CECDEVICE_TV && command.parameters.size == 3) ++ if (adapter->m_configuration.bUseTVMenuLanguage == 1 && command.initiator == CECDEVICE_TV && command.parameters.size == 3) + { + char strNewLanguage[4]; + for (int iPtr = 0; iPtr < 3; iPtr++) + strNewLanguage[iPtr] = command.parameters[iPtr]; + strNewLanguage[3] = 0; +- SetMenuLanguage(strNewLanguage); ++ adapter->SetMenuLanguage(strNewLanguage); + } + break; + case CEC_OPCODE_DECK_CONTROL: +@@ -438,11 +574,11 @@ + command.parameters.size == 1 && + command.parameters[0] == CEC_DECK_CONTROL_MODE_STOP) + { +- CSingleLock lock(m_critSection); ++ CSingleLock lock(adapter->m_critSection); + cec_keypress key; + key.duration = 500; + key.keycode = CEC_USER_CONTROL_CODE_STOP; +- m_buttonQueue.push(key); ++ adapter->m_buttonQueue.push(key); + } + break; + case CEC_OPCODE_PLAY: +@@ -451,26 +587,58 @@ + { + if (command.parameters[0] == CEC_PLAY_MODE_PLAY_FORWARD) + { +- CSingleLock lock(m_critSection); ++ CSingleLock lock(adapter->m_critSection); + cec_keypress key; + key.duration = 500; + key.keycode = CEC_USER_CONTROL_CODE_PLAY; +- m_buttonQueue.push(key); ++ adapter->m_buttonQueue.push(key); + } + else if (command.parameters[0] == CEC_PLAY_MODE_PLAY_STILL) + { +- CSingleLock lock(m_critSection); ++ CSingleLock lock(adapter->m_critSection); + cec_keypress key; + key.duration = 500; + key.keycode = CEC_USER_CONTROL_CODE_PAUSE; +- m_buttonQueue.push(key); ++ adapter->m_buttonQueue.push(key); + } + } + break; ++ case CEC_OPCODE_REPORT_POWER_STATUS: ++ if (command.initiator == CECDEVICE_TV && ++ command.parameters.size == 1 && ++ command.parameters[0] == CEC_POWER_STATUS_ON && ++ adapter->m_queryThread) ++ { ++ adapter->m_queryThread->Signal(); ++ } ++ break; + default: + break; + } + } ++ return 1; ++} ++ ++int CPeripheralCecAdapter::CecConfiguration(void *cbParam, const libcec_configuration &config) ++{ ++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; ++ if (!adapter) ++ return 0; ++ ++ CSingleLock lock(adapter->m_critSection); ++ adapter->SetConfigurationFromLibCEC(config); ++ return 1; ++} ++ ++int CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress &key) ++{ ++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; ++ if (!adapter) ++ return 0; ++ ++ CSingleLock lock(adapter->m_critSection); ++ adapter->m_buttonQueue.push(key); ++ return 1; + } + + bool CPeripheralCecAdapter::GetNextCecKey(cec_keypress &key) +@@ -483,10 +651,6 @@ + m_buttonQueue.pop(); + bReturn = true; + } +- else if (m_cecAdapter->GetNextKeypress(&key)) +- { +- bReturn = true; +- } + + return bReturn; + } +@@ -726,41 +890,43 @@ + else if (bEnabled && !m_cecAdapter && m_bStarted) + InitialiseFeature(FEATURE_CEC); + } +- else if (strChangedSetting.Equals("cec_hdmi_port")) ++ else + { +- SetHdmiPort(GetSettingInt("cec_hdmi_port")); ++ SetConfigurationFromSettings(); ++ m_queryThread->UpdateConfiguration(&m_configuration); + } + } + +-void CPeripheralCecAdapter::FlushLog(void) ++int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message &message) + { +- cec_log_message message; +- while (m_cecAdapter && m_cecAdapter->GetNextLogMessage(&message)) +- { +- int iLevel = -1; +- switch (message.level) +- { +- case CEC_LOG_ERROR: +- iLevel = LOGERROR; +- break; +- case CEC_LOG_WARNING: +- iLevel = LOGWARNING; +- break; +- case CEC_LOG_NOTICE: +- iLevel = LOGDEBUG; +- break; +- case CEC_LOG_TRAFFIC: +- case CEC_LOG_DEBUG: +- if (GetSettingBool("cec_debug_logging")) +- iLevel = LOGDEBUG; +- break; +- default: +- break; +- } ++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; ++ if (!adapter) ++ return 0; + +- if (iLevel >= 0) +- CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message); ++ int iLevel = -1; ++ switch (message.level) ++ { ++ case CEC_LOG_ERROR: ++ iLevel = LOGERROR; ++ break; ++ case CEC_LOG_WARNING: ++ iLevel = LOGWARNING; ++ break; ++ case CEC_LOG_NOTICE: ++ iLevel = LOGDEBUG; ++ break; ++ case CEC_LOG_TRAFFIC: ++ case CEC_LOG_DEBUG: ++ iLevel = LOGDEBUG; ++ break; ++ default: ++ break; + } ++ ++ if (iLevel >= 0) ++ CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message); ++ ++ return 1; + } + + bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation) +@@ -774,4 +940,301 @@ + + return false; + } ++ ++void CPeripheralCecAdapter::SetConfigurationFromLibCEC(const CEC::libcec_configuration &config) ++{ ++ // set the primary device type ++ m_configuration.deviceTypes.Clear(); ++ m_configuration.deviceTypes.Add(config.deviceTypes[0]); ++ SetSetting("device_type", (int)config.deviceTypes[0]); ++ ++ // set the connected device ++ m_configuration.baseDevice = config.baseDevice; ++ SetSetting("connected_device", (int)config.baseDevice); ++ ++ // set the HDMI port number ++ m_configuration.iHDMIPort = config.iHDMIPort; ++ SetSetting("cec_hdmi_port", config.iHDMIPort); ++ ++ // set the physical address, when baseDevice or iHDMIPort are not set ++ if (m_configuration.baseDevice == CECDEVICE_UNKNOWN || ++ m_configuration.iHDMIPort == 0 || m_configuration.iHDMIPort > 4) ++ { ++ m_configuration.iPhysicalAddress = config.iPhysicalAddress; ++ CStdString strPhysicalAddress; ++ strPhysicalAddress.Format("%x", config.iPhysicalAddress); ++ SetSetting("physical_address", strPhysicalAddress); ++ } ++ ++ // set the tv vendor override ++ m_configuration.tvVendor = config.tvVendor; ++ SetSetting("tv_vendor", (int)config.tvVendor); ++ ++ // set the devices to wake when starting ++ m_configuration.wakeDevices = config.wakeDevices; ++ CStdString strWakeDevices; ++ for (unsigned int iPtr = 0; iPtr <= 16; iPtr++) ++ if (config.wakeDevices[iPtr]) ++ strWakeDevices.AppendFormat(" %X", iPtr); ++ SetSetting("wake_devices", strWakeDevices.Trim()); ++ ++ // set the devices to power off when stopping ++ m_configuration.powerOffDevices = config.powerOffDevices; ++ CStdString strPowerOffDevices; ++ for (unsigned int iPtr = 0; iPtr <= 16; iPtr++) ++ if (config.powerOffDevices[iPtr]) ++ strPowerOffDevices.AppendFormat(" %X", iPtr); ++ SetSetting("wake_devices", strPowerOffDevices.Trim()); ++ ++ // set the boolean settings ++ m_configuration.bUseTVMenuLanguage = config.bUseTVMenuLanguage; ++ SetSetting("use_tv_menu_language", m_configuration.bUseTVMenuLanguage == 1); ++ ++ m_configuration.bActivateSource = config.bActivateSource; ++ SetSetting("activate_source", m_configuration.bActivateSource == 1); ++ ++ m_configuration.bPowerOffScreensaver = config.bPowerOffScreensaver; ++ SetSetting("cec_standby_screensaver", m_configuration.bPowerOffScreensaver == 1); ++ ++ m_configuration.bPowerOffOnStandby = config.bPowerOffOnStandby; ++ SetSetting("standby_pc_on_tv_standby", m_configuration.bPowerOffOnStandby == 1); ++ ++ if (config.serverVersion >= CEC_SERVER_VERSION_1_5_1) ++ m_configuration.bSendInactiveSource = config.bSendInactiveSource; ++ SetSetting("send_inactive_source", m_configuration.bSendInactiveSource == 1); ++} ++ ++void CPeripheralCecAdapter::SetConfigurationFromSettings(void) ++{ ++ // client version 1.5.0 ++ m_configuration.clientVersion = CEC_CLIENT_VERSION_1_5_1; ++ ++ // device name 'XBMC' ++ snprintf(m_configuration.strDeviceName, 13, "%s", GetSettingString("device_name").c_str()); ++ ++ // set the primary device type ++ m_configuration.deviceTypes.Clear(); ++ int iDeviceType = GetSettingInt("device_type"); ++ if (iDeviceType != (int)CEC_DEVICE_TYPE_RECORDING_DEVICE && ++ iDeviceType != (int)CEC_DEVICE_TYPE_PLAYBACK_DEVICE && ++ iDeviceType != (int)CEC_DEVICE_TYPE_TUNER) ++ iDeviceType = (int)CEC_DEVICE_TYPE_RECORDING_DEVICE; ++ m_configuration.deviceTypes.Add((cec_device_type)iDeviceType); ++ ++ // always try to autodetect the address. ++ // when the firmware supports this, it will override the physical address, connected device and hdmi port settings ++ m_configuration.bAutodetectAddress = 1; ++ ++ // set the physical address ++ // when set, it will override the connected device and hdmi port settings ++ CStdString strPhysicalAddress = GetSettingString("physical_address"); ++ int iPhysicalAddress; ++ if (sscanf(strPhysicalAddress.c_str(), "%x", &iPhysicalAddress) == 1 && iPhysicalAddress > 0 && iPhysicalAddress < 0xFFFF) ++ m_configuration.iPhysicalAddress = iPhysicalAddress; ++ ++ // set the connected device ++ int iConnectedDevice = GetSettingInt("connected_device"); ++ if (iConnectedDevice == 0 || iConnectedDevice == 5) ++ m_configuration.baseDevice = (cec_logical_address)iConnectedDevice; ++ ++ // set the HDMI port number ++ int iHDMIPort = GetSettingInt("cec_hdmi_port"); ++ if (iHDMIPort >= 0 && iHDMIPort <= 4) ++ m_configuration.iHDMIPort = iHDMIPort; ++ ++ // set the tv vendor override ++ int iVendor = GetSettingInt("tv_vendor"); ++ if (iVendor > 0 && iVendor < 0xFFFFFF) ++ m_configuration.tvVendor = iVendor; ++ ++ // read the devices to wake when starting ++ CStdString strWakeDevices = CStdString(GetSettingString("wake_devices")).Trim(); ++ m_configuration.wakeDevices.Clear(); ++ ReadLogicalAddresses(strWakeDevices, m_configuration.wakeDevices); ++ ++ // read the devices to power off when stopping ++ CStdString strStandbyDevices = CStdString(GetSettingString("standby_devices")).Trim(); ++ m_configuration.powerOffDevices.Clear(); ++ ReadLogicalAddresses(strStandbyDevices, m_configuration.powerOffDevices); ++ ++ // always get the settings from the rom, when supported by the firmware ++ m_configuration.bGetSettingsFromROM = 1; ++ ++ // read the boolean settings ++ m_configuration.bUseTVMenuLanguage = GetSettingBool("use_tv_menu_language") ? 1 : 0; ++ m_configuration.bActivateSource = GetSettingBool("activate_source") ? 1 : 0; ++ m_configuration.bPowerOffScreensaver = GetSettingBool("cec_standby_screensaver") ? 1 : 0; ++ m_configuration.bPowerOffOnStandby = GetSettingBool("standby_pc_on_tv_standby") ? 1 : 0; ++ m_configuration.bSendInactiveSource = GetSettingBool("send_inactive_source") ? 1 : 0; ++} ++ ++void CPeripheralCecAdapter::ReadLogicalAddresses(const CStdString &strString, cec_logical_addresses &addresses) ++{ ++ for (size_t iPtr = 0; iPtr < strString.size(); iPtr++) ++ { ++ CStdString strDevice = CStdString(strString.substr(iPtr, 1)).Trim(); ++ if (!strDevice.IsEmpty()) ++ { ++ int iDevice(0); ++ if (sscanf(strDevice.c_str(), "%x", &iDevice) == 1 && iDevice >= 0 && iDevice <= 0xF) ++ addresses.Set((cec_logical_address)iDevice); ++ } ++ } ++} ++ ++CPeripheralCecAdapterUpdateThread::CPeripheralCecAdapterUpdateThread(CPeripheralCecAdapter *adapter, libcec_configuration *configuration) : ++ CThread("CEC Adapter Update Thread"), ++ m_adapter(adapter), ++ m_configuration(*configuration), ++ m_bNextConfigurationScheduled(false), ++ m_bIsUpdating(true) ++{ ++ m_nextConfiguration.Clear(); ++ m_event.Reset(); ++} ++ ++CPeripheralCecAdapterUpdateThread::~CPeripheralCecAdapterUpdateThread(void) ++{ ++ StopThread(false); ++ m_event.Set(); ++ StopThread(true); ++} ++ ++void CPeripheralCecAdapterUpdateThread::Signal(void) ++{ ++ m_event.Set(); ++} ++ ++bool CPeripheralCecAdapterUpdateThread::UpdateConfiguration(libcec_configuration *configuration) ++{ ++ CSingleLock lock(m_critSection); ++ if (m_bIsUpdating) ++ { ++ m_bNextConfigurationScheduled = true; ++ m_nextConfiguration = *configuration; ++ } ++ else ++ { ++ m_configuration = *configuration; ++ m_event.Set(); ++ } ++ return true; ++} ++ ++bool CPeripheralCecAdapterUpdateThread::WaitReady(void) ++{ ++ // don't wait if we're not powering up anything ++ if (m_configuration.wakeDevices.IsEmpty() && m_configuration.bActivateSource == 0) ++ return true; ++ ++ // wait for the TV if we're configured to become the active source. ++ // wait for the first device in the wake list otherwise. ++ cec_logical_address waitFor = (m_configuration.bActivateSource == 1) ? ++ CECDEVICE_TV : ++ m_configuration.wakeDevices.primary; ++ ++ cec_power_status powerStatus(CEC_POWER_STATUS_UNKNOWN); ++ bool bContinue(true); ++ while (bContinue && !m_adapter->m_bStop && !m_bStop && powerStatus != CEC_POWER_STATUS_ON) ++ { ++ powerStatus = m_adapter->m_cecAdapter->GetDevicePowerStatus(waitFor); ++ if (powerStatus != CEC_POWER_STATUS_ON) ++ bContinue = !m_event.WaitMSec(1000); ++ } ++ ++ return powerStatus == CEC_POWER_STATUS_ON; ++} ++ ++bool CPeripheralCecAdapterUpdateThread::SetInitialConfiguration(void) ++{ ++ // devices to wake are set ++ if (!m_configuration.wakeDevices.IsEmpty()) ++ m_adapter->m_cecAdapter->PowerOnDevices(CECDEVICE_BROADCAST); ++ ++ // the option to make XBMC the active source is set ++ if (m_configuration.bActivateSource == 1) ++ m_adapter->m_cecAdapter->SetActiveSource(); ++ ++ // wait until devices are powered up ++ if (!WaitReady()) ++ return false; ++ ++ // request the menu language of the TV ++ if (m_configuration.bUseTVMenuLanguage == 1) ++ { ++ cec_menu_language language; ++ if (m_adapter->m_cecAdapter->GetDeviceMenuLanguage(CECDEVICE_TV, &language)) ++ m_adapter->SetMenuLanguage(language.language); ++ } ++ ++ // request the OSD name of the TV ++ CStdString strNotification; ++ cec_osd_name tvName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_TV); ++ strNotification.Format("%s: %s", g_localizeStrings.Get(36016), tvName.name); ++ ++ /* disable the mute setting when an amp is found, because the amp handles the mute setting and ++ set PCM output to 100% */ ++ if (m_adapter->m_cecAdapter->IsActiveDeviceType(CEC_DEVICE_TYPE_AUDIO_SYSTEM)) ++ { ++ // request the OSD name of the amp ++ cec_osd_name ampName = m_adapter->m_cecAdapter->GetDeviceOSDName(CECDEVICE_AUDIOSYSTEM); ++ CLog::Log(LOGDEBUG, "%s - CEC capable amplifier found (%s). volume will be controlled on the amp", __FUNCTION__, ampName.name); ++ strNotification.AppendFormat(" - %s", ampName.name); ++ ++ // set amp present ++ m_adapter->SetAudioSystemConnected(true); ++ g_settings.m_bMute = false; ++ g_settings.m_nVolumeLevel = VOLUME_MAXIMUM; ++ } ++ ++ m_adapter->m_bIsReady = true; ++ ++ // try to send an OSD string to the TV ++ m_adapter->m_cecAdapter->SetOSDString(CECDEVICE_TV, CEC_DISPLAY_CONTROL_DISPLAY_FOR_DEFAULT_TIME, g_localizeStrings.Get(36016).c_str()); ++ // and let the gui know that we're done ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), strNotification); ++ ++ CSingleLock lock(m_critSection); ++ m_bIsUpdating = false; ++ return true; ++} ++ ++void CPeripheralCecAdapterUpdateThread::Process(void) ++{ ++ // set the initial configuration ++ if (!SetInitialConfiguration()) ++ return; ++ ++ // and wait for updates ++ bool bUpdate(false); ++ while (!m_bStop) ++ { ++ // update received ++ if (m_event.WaitMSec(500) || bUpdate) ++ { ++ if (m_bStop) ++ return; ++ // set the new configuration ++ bool bConfigSet(m_adapter->m_cecAdapter->SetConfiguration(&m_configuration)); ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(bConfigSet ? 36023 : 36024)); ++ { ++ CSingleLock lock(m_critSection); ++ bUpdate = m_bNextConfigurationScheduled; ++ if (bUpdate) ++ { ++ // another update is scheduled ++ m_bNextConfigurationScheduled = false; ++ m_configuration = m_nextConfiguration; ++ } ++ else ++ { ++ // nothing left to do, wait for updates ++ m_bIsUpdating = false; ++ m_event.Reset(); ++ } ++ } ++ } ++ } ++} ++ + #endif +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.h xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.h +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.h 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.h 2012-04-17 14:05:05.882177854 +0200 +@@ -20,7 +20,28 @@ + * + */ + +-#if defined(HAVE_LIBCEC) ++#if !defined(HAVE_LIBCEC) ++#include "Peripheral.h" ++ ++// an empty implementation, so CPeripherals can be compiled without a bunch of #ifdef's when libCEC is not available ++namespace PERIPHERALS ++{ ++ class CPeripheralCecAdapter : public CPeripheral ++ { ++ public: ++ bool HasConnectedAudioSystem(void) { return false; } ++ void ScheduleVolumeUp(void) {} ++ void ScheduleVolumeDown(void) {} ++ bool IsMuted(void) { return false; } ++ void ScheduleMute(void) {} ++ ++ WORD GetButton(void) { return 0; } ++ unsigned int GetHoldTime(void) { return 0; } ++ void ResetButton(void) {} ++ }; ++} ++ ++#else + + #include "PeripheralHID.h" + #include "interfaces/AnnouncementManager.h" +@@ -32,7 +53,7 @@ + #ifdef isset + #undef isset + #endif +-#include ++#include + + class DllLibCEC; + +@@ -43,25 +64,40 @@ + + namespace PERIPHERALS + { ++ class CPeripheralCecAdapterUpdateThread; ++ + typedef struct + { + WORD iButton; + unsigned int iDuration; + } CecButtonPress; + ++ typedef enum ++ { ++ VOLUME_CHANGE_NONE, ++ VOLUME_CHANGE_UP, ++ VOLUME_CHANGE_DOWN, ++ VOLUME_CHANGE_MUTE ++ } CecVolumeChange; + + class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread + { ++ friend class CPeripheralCecAdapterUpdateThread; ++ + public: + CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralCecAdapter(void); + + virtual void Announce(ANNOUNCEMENT::EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); +- virtual bool PowerOnCecDevices(CEC::cec_logical_address iLogicalAddress); +- virtual bool StandbyCecDevices(CEC::cec_logical_address iLogicalAddress); +- +- virtual bool SendPing(void); +- virtual bool SetHdmiPort(int iHdmiPort); ++ virtual bool HasConnectedAudioSystem(void); ++ virtual void SetAudioSystemConnected(bool bSetTo); ++ virtual void ScheduleVolumeUp(void); ++ virtual void VolumeUp(void); ++ virtual void ScheduleVolumeDown(void); ++ virtual void VolumeDown(void); ++ virtual void ScheduleMute(void); ++ virtual void Mute(void); ++ virtual bool IsMuted(void); + + virtual void OnSettingChanged(const CStdString &strChangedSetting); + +@@ -71,27 +107,66 @@ + virtual CStdString GetComPort(void); + + protected: +- virtual void FlushLog(void); +- virtual bool GetNextCecKey(CEC::cec_keypress &key); ++ virtual bool OpenConnection(void); ++ virtual void SetConfigurationFromSettings(void); ++ virtual void SetConfigurationFromLibCEC(const CEC::libcec_configuration &config); ++ static void ReadLogicalAddresses(const CStdString &strString, CEC::cec_logical_addresses &addresses); ++ static int CecKeyPress(void *cbParam, const CEC::cec_keypress &key); ++ static int CecLogMessage(void *cbParam, const CEC::cec_log_message &message); ++ static int CecCommand(void *cbParam, const CEC::cec_command &command); ++ static int CecConfiguration(void *cbParam, const CEC::libcec_configuration &config); ++ + virtual bool GetNextKey(void); ++ virtual bool GetNextCecKey(CEC::cec_keypress &key); + virtual bool InitialiseFeature(const PeripheralFeature feature); + virtual void Process(void); +- virtual void ProcessNextCommand(void); ++ virtual void ProcessVolumeChange(void); + virtual void SetMenuLanguage(const char *strLanguage); + static bool FindConfigLocation(CStdString &strString); + static bool TranslateComPort(CStdString &strPort); + +- DllLibCEC* m_dll; +- CEC::ICECAdapter* m_cecAdapter; +- bool m_bStarted; +- bool m_bHasButton; +- bool m_bIsReady; +- CStdString m_strMenuLanguage; +- CDateTime m_screensaverLastActivated; +- CecButtonPress m_button; +- std::queue m_buttonQueue; +- unsigned int m_lastKeypress; +- CCriticalSection m_critSection; ++ DllLibCEC* m_dll; ++ CEC::ICECAdapter* m_cecAdapter; ++ bool m_bStarted; ++ bool m_bHasButton; ++ bool m_bIsReady; ++ bool m_bHasConnectedAudioSystem; ++ CStdString m_strMenuLanguage; ++ CDateTime m_screensaverLastActivated; ++ CecButtonPress m_button; ++ std::queue m_buttonQueue; ++ std::queue m_volumeChangeQueue; ++ unsigned int m_lastKeypress; ++ CecVolumeChange m_lastChange; ++ int m_iExitCode; ++ bool m_bIsMuted; ++ CPeripheralCecAdapterUpdateThread*m_queryThread; ++ CEC::ICECCallbacks m_callbacks; ++ CCriticalSection m_critSection; ++ CEC::libcec_configuration m_configuration; ++ }; ++ ++ class CPeripheralCecAdapterUpdateThread : public CThread ++ { ++ public: ++ CPeripheralCecAdapterUpdateThread(CPeripheralCecAdapter *adapter, CEC::libcec_configuration *configuration); ++ virtual ~CPeripheralCecAdapterUpdateThread(void); ++ ++ virtual void Signal(void); ++ virtual bool UpdateConfiguration(CEC::libcec_configuration *configuration); ++ ++ protected: ++ virtual bool WaitReady(void); ++ virtual bool SetInitialConfiguration(void); ++ virtual void Process(void); ++ ++ CPeripheralCecAdapter * m_adapter; ++ CEvent m_event; ++ CCriticalSection m_critSection; ++ CEC::libcec_configuration m_configuration; ++ CEC::libcec_configuration m_nextConfiguration; ++ bool m_bNextConfigurationScheduled; ++ bool m_bIsUpdating; + }; + } + +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.cpp 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.cpp 2012-04-17 14:03:25.174271152 +0200 +@@ -30,6 +30,14 @@ + using namespace PERIPHERALS; + using namespace std; + ++struct SortBySettingsOrder ++{ ++ bool operator()(const CSetting *left, const CSetting *right) ++ { ++ return left->GetOrder() < right->GetOrder(); ++ } ++}; ++ + CPeripheral::CPeripheral(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + m_type(type), + m_busType(busType), +@@ -168,6 +176,15 @@ + return m_subDevices.size() > 0; + } + ++vector CPeripheral::GetSettings(void) const ++{ ++ vector settings; ++ for (map::const_iterator it = m_settings.begin(); it != m_settings.end(); it++) ++ settings.push_back(it->second); ++ sort(settings.begin(), settings.end(), SortBySettingsOrder()); ++ return settings; ++} ++ + void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) + { + if (!setting) +@@ -183,7 +200,7 @@ + case SETTINGS_TYPE_BOOL: + { + const CSettingBool *mappedSetting = (const CSettingBool *) setting; +- CSettingBool *boolSetting = new CSettingBool(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->GetControlType()); ++ CSettingBool *boolSetting = new CSettingBool(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->GetControlType()); + if (boolSetting) + { + boolSetting->SetVisible(mappedSetting->IsVisible()); +@@ -194,7 +211,7 @@ + case SETTINGS_TYPE_INT: + { + const CSettingInt *mappedSetting = (const CSettingInt *) setting; +- CSettingInt *intSetting = new CSettingInt(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); ++ CSettingInt *intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); + if (intSetting) + { + intSetting->SetVisible(mappedSetting->IsVisible()); +@@ -205,7 +222,7 @@ + case SETTINGS_TYPE_FLOAT: + { + const CSettingFloat *mappedSetting = (const CSettingFloat *) setting; +- CSettingFloat *floatSetting = new CSettingFloat(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_fMin, mappedSetting->m_fStep, mappedSetting->m_fMax, mappedSetting->GetControlType()); ++ CSettingFloat *floatSetting = new CSettingFloat(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_fMin, mappedSetting->m_fStep, mappedSetting->m_fMax, mappedSetting->GetControlType()); + if (floatSetting) + { + floatSetting->SetVisible(mappedSetting->IsVisible()); +@@ -216,7 +233,7 @@ + case SETTINGS_TYPE_STRING: + { + const CSettingString *mappedSetting = (const CSettingString *) setting; +- CSettingString *stringSetting = new CSettingString(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData().c_str(), mappedSetting->GetControlType(), mappedSetting->m_bAllowEmpty, mappedSetting->m_iHeadingString); ++ CSettingString *stringSetting = new CSettingString(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData().c_str(), mappedSetting->GetControlType(), mappedSetting->m_bAllowEmpty, mappedSetting->m_iHeadingString); + if (stringSetting) + { + stringSetting->SetVisible(mappedSetting->IsVisible()); +@@ -323,7 +340,7 @@ + bool bChanged(boolSetting->GetData() != bValue); + boolSetting->SetData(bValue); + if (bChanged && m_bInitialised) +- m_changedSettings.push_back(strKey); ++ m_changedSettings.insert(strKey); + } + } + } +@@ -339,7 +356,7 @@ + bool bChanged(intSetting->GetData() != iValue); + intSetting->SetData(iValue); + if (bChanged && m_bInitialised) +- m_changedSettings.push_back(strKey); ++ m_changedSettings.insert(strKey); + } + } + } +@@ -355,11 +372,26 @@ + bool bChanged(floatSetting->GetData() != fValue); + floatSetting->SetData(fValue); + if (bChanged && m_bInitialised) +- m_changedSettings.push_back(strKey); ++ m_changedSettings.insert(strKey); + } + } + } + ++void CPeripheral::SetSettingVisible(const CStdString &strKey, bool bSetTo) ++{ ++ map::iterator it = m_settings.find(strKey); ++ if (it != m_settings.end()) ++ (*it).second->SetVisible(bSetTo); ++} ++ ++bool CPeripheral::IsSettingVisible(const CStdString &strKey) const ++{ ++ map::const_iterator it = m_settings.find(strKey); ++ if (it != m_settings.end()) ++ return (*it).second->IsVisible(); ++ return false; ++} ++ + void CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValue) + { + map::iterator it = m_settings.find(strKey); +@@ -373,7 +405,7 @@ + bool bChanged(!stringSetting->GetData().Equals(strValue)); + stringSetting->SetData(strValue); + if (bChanged && m_bInitialised) +- m_changedSettings.push_back(strKey); ++ m_changedSettings.insert(strKey); + } + } + else if ((*it).second->GetType() == SETTINGS_TYPE_INT) +@@ -436,7 +468,7 @@ + + if (!bExiting) + { +- for (vector::iterator it = m_changedSettings.begin(); it != m_changedSettings.end(); it++) ++ for (set::const_iterator it = m_changedSettings.begin(); it != m_changedSettings.end(); it++) + OnSettingChanged(*it); + } + m_changedSettings.clear(); +@@ -467,7 +499,7 @@ + map::iterator it = m_settings.begin(); + while (it != m_settings.end()) + { +- m_changedSettings.push_back((*it).first); ++ m_changedSettings.insert((*it).first); + ++it; + } + +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.h xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.h +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.h 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.h 2012-04-17 14:03:25.174271152 +0200 +@@ -20,7 +20,7 @@ + * + */ + +-#include ++#include + #include "utils/StdString.h" + #include "peripherals/PeripheralTypes.h" + +@@ -128,6 +128,8 @@ + */ + virtual const CStdString GetSettingString(const CStdString &strKey) const; + virtual void SetSetting(const CStdString &strKey, const CStdString &strValue); ++ virtual void SetSettingVisible(const CStdString &strKey, bool bSetTo); ++ virtual bool IsSettingVisible(const CStdString &strKey) const; + + virtual int GetSettingInt(const CStdString &strKey) const; + virtual void SetSetting(const CStdString &strKey, int iValue); +@@ -142,6 +144,8 @@ + virtual void LoadPersistedSettings(void); + virtual void ResetDefaultSettings(void); + ++ virtual std::vector GetSettings(void) const; ++ + virtual bool ErrorOccured(void) const { return m_bError; } + + protected: +@@ -163,6 +167,6 @@ + std::vector m_features; + std::vector m_subDevices; + std::map m_settings; +- std::vector m_changedSettings; ++ std::set m_changedSettings; + }; + } +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralHID.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralHID.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralHID.cpp 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralHID.cpp 2012-04-17 14:03:25.173271133 +0200 +@@ -37,7 +37,7 @@ + + CPeripheralHID::~CPeripheralHID(void) + { +- if (!m_strKeymap.IsEmpty() && GetSettingBool("keymap_enabled")) ++ if (!m_strKeymap.IsEmpty() && !GetSettingBool("do_not_use_custom_keymap")) + { + CLog::Log(LOGDEBUG, "%s - switching active keymapping to: default", __FUNCTION__); + CButtonTranslator::GetInstance().RemoveDevice(m_strKeymap); +@@ -59,9 +59,12 @@ + SetSetting("keymap", m_strKeymap); + } + ++ if (!IsSettingVisible("keymap")) ++ SetSettingVisible("do_not_use_custom_keymap", false); ++ + if (!m_strKeymap.IsEmpty()) + { +- bool bKeymapEnabled(GetSettingBool("keymap_enabled")); ++ bool bKeymapEnabled(!GetSettingBool("do_not_use_custom_keymap")); + if (bKeymapEnabled) + { + CLog::Log(LOGDEBUG, "%s - adding keymapping for: %s", __FUNCTION__, m_strKeymap.c_str()); +@@ -82,7 +85,7 @@ + + void CPeripheralHID::OnSettingChanged(const CStdString &strChangedSetting) + { +- if (m_bInitialised && ((strChangedSetting.Equals("keymap") && GetSettingBool("keymap_enabled")) || strChangedSetting.Equals("keymap_enabled"))) ++ if (m_bInitialised && ((strChangedSetting.Equals("keymap") && !GetSettingBool("do_not_use_custom_keymap")) || strChangedSetting.Equals("keymap_enabled"))) + { + m_bInitialised = false; + InitialiseFeature(FEATURE_HID); +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp 2012-04-17 14:03:25.169271055 +0200 +@@ -66,17 +66,15 @@ + + if (m_item) + { +- int iIndex = 1; + CPeripheral *peripheral = g_peripherals.GetByPath(m_item->GetPath()); + if (peripheral) + { +- map::iterator it = peripheral->m_settings.begin(); +- while (it != peripheral->m_settings.end()) ++ vector settings = peripheral->GetSettings(); ++ for (size_t iPtr = 0; iPtr < settings.size(); iPtr++) + { +- CSetting *setting = (*it).second; ++ CSetting *setting = settings[iPtr]; + if (!setting->IsVisible()) + { +- ++it; + CLog::Log(LOGDEBUG, "%s - invisible", __FUNCTION__); + continue; + } +@@ -89,7 +87,7 @@ + if (boolSetting) + { + m_boolSettings.insert(make_pair(CStdString(boolSetting->GetSetting()), boolSetting->GetData())); +- AddBool(iIndex++, boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetSetting()], true); ++ AddBool(boolSetting->GetOrder(), boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetSetting()], true); + } + } + break; +@@ -99,7 +97,7 @@ + if (intSetting) + { + m_intSettings.insert(make_pair(CStdString(intSetting->GetSetting()), (float) intSetting->GetData())); +- AddSlider(iIndex++, intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); ++ AddSlider(intSetting->GetOrder(), intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); + } + } + break; +@@ -109,7 +107,7 @@ + if (floatSetting) + { + m_floatSettings.insert(make_pair(CStdString(floatSetting->GetSetting()), floatSetting->GetData())); +- AddSlider(iIndex++, floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetSetting()], floatSetting->m_fMin, floatSetting->m_fStep, floatSetting->m_fMax, CGUIDialogVideoSettings::FormatFloat, false); ++ AddSlider(floatSetting->GetOrder(), floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetSetting()], floatSetting->m_fMin, floatSetting->m_fStep, floatSetting->m_fMax, CGUIDialogVideoSettings::FormatFloat, false); + } + } + break; +@@ -119,7 +117,7 @@ + if (stringSetting) + { + m_stringSettings.insert(make_pair(CStdString(stringSetting->GetSetting()), stringSetting->GetData())); +- AddString(iIndex, stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetSetting()]); ++ AddString(stringSetting->GetOrder(), stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetSetting()]); + } + } + break; +@@ -128,7 +126,6 @@ + CLog::Log(LOGDEBUG, "%s - unknown type", __FUNCTION__); + break; + } +- ++it; + } + } + else +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/Peripherals.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/Peripherals.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/Peripherals.cpp 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/Peripherals.cpp 2012-04-17 14:03:25.213271888 +0200 +@@ -27,9 +27,7 @@ + #include "devices/PeripheralNIC.h" + #include "devices/PeripheralNyxboard.h" + #include "devices/PeripheralTuner.h" +-#if defined(HAVE_LIBCEC) + #include "devices/PeripheralCecAdapter.h" +-#endif + #include "bus/PeripheralBusUSB.h" + #include "dialogs/GUIDialogPeripheralManager.h" + +@@ -43,6 +41,7 @@ + #include "guilib/LocalizeStrings.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "utils/StringUtils.h" ++#include "guilib/Key.h" + + using namespace PERIPHERALS; + using namespace XFILE; +@@ -447,6 +446,8 @@ + void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map &m_settings) + { + TiXmlElement *currentNode = xmlNode->FirstChildElement("setting"); ++ int iMaxOrder(0); ++ + while (currentNode) + { + CSetting *setting = NULL; +@@ -492,10 +493,32 @@ + } + + //TODO add more types if needed ++ ++ /* set the visibility */ + setting->SetVisible(bConfigurable); ++ ++ /* set the order */ ++ int iOrder(0); ++ currentNode->Attribute("order", &iOrder); ++ /* if the order attribute is invalid or 0, then the setting will be added at the end */ ++ if (iOrder < 0) ++ iOrder = 0; ++ setting->SetOrder(iOrder); ++ if (iOrder > iMaxOrder) ++ iMaxOrder = iOrder; ++ ++ /* and add this new setting */ + m_settings[strKey] = setting; ++ + currentNode = currentNode->NextSiblingElement("setting"); + } ++ ++ /* add the settings without an order attribute or an invalid order attribute set at the end */ ++ for (map::iterator it = m_settings.begin(); it != m_settings.end(); it++) ++ { ++ if (it->second->GetOrder() == 0) ++ it->second->SetOrder(++iMaxOrder); ++ } + } + + void CPeripherals::GetDirectory(const CStdString &strPath, CFileItemList &items) const +@@ -531,3 +554,89 @@ + + return NULL; + } ++ ++bool CPeripherals::OnAction(const CAction &action) ++{ ++ if (action.GetID() == ACTION_MUTE) ++ { ++ return ToggleMute(); ++ } ++ ++ if (SupportsCEC() && action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN)) ++ { ++ vector peripherals; ++ if (GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) ++ { ++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) ++ { ++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); ++ if (cecDevice && cecDevice->HasConnectedAudioSystem()) ++ { ++ if (action.GetID() == ACTION_VOLUME_UP) ++ cecDevice->ScheduleVolumeUp(); ++ else ++ cecDevice->ScheduleVolumeDown(); ++ return true; ++ } ++ } ++ } ++ } ++ ++ return false; ++} ++ ++bool CPeripherals::IsMuted(void) ++{ ++ vector peripherals; ++ if (SupportsCEC() && GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) ++ { ++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) ++ { ++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); ++ if (cecDevice && cecDevice->IsMuted()) ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++bool CPeripherals::ToggleMute(void) ++{ ++ vector peripherals; ++ if (SupportsCEC() && GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) ++ { ++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) ++ { ++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); ++ if (cecDevice && cecDevice->HasConnectedAudioSystem()) ++ { ++ cecDevice->ScheduleMute(); ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++bool CPeripherals::GetNextKeypress(float frameTime, CKey &key) ++{ ++ vector peripherals; ++ if (SupportsCEC() && GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) ++ { ++ for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) ++ { ++ CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); ++ if (cecDevice && cecDevice->GetButton()) ++ { ++ CKey newKey(cecDevice->GetButton(), cecDevice->GetHoldTime()); ++ cecDevice->ResetButton(); ++ key = newKey; ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/Peripherals.h xbmc-pvr-11.0.1.patch/xbmc/peripherals/Peripherals.h +--- xbmc-pvr-11.0.1/xbmc/peripherals/Peripherals.h 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/Peripherals.h 2012-04-17 14:03:25.213271888 +0200 +@@ -29,6 +29,8 @@ + class CSetting; + class CSettingsCategory; + class TiXmlElement; ++class CAction; ++class CKey; + + namespace PERIPHERALS + { +@@ -147,6 +149,54 @@ + */ + virtual CPeripheral *GetByPath(const CStdString &strPath) const; + ++ /*! ++ * @brief Try to let one of the peripherals handle an action. ++ * @param action The change to handle. ++ * @return True when this change was handled by a peripheral (and should not be handled by anything else), false otherwise. ++ */ ++ virtual bool OnAction(const CAction &action); ++ ++ /*! ++ * @brief Check whether there's a peripheral that reports to be muted. ++ * @return True when at least one peripheral reports to be muted, false otherwise. ++ */ ++ virtual bool IsMuted(void); ++ ++ /*! ++ * @brief Try to toggle the mute status via a peripheral. ++ * @return True when this change was handled by a peripheral (and should not be handled by anything else), false otherwise. ++ */ ++ virtual bool ToggleMute(void); ++ ++ /*! ++ * @brief Try to mute the audio via a peripheral. ++ * @return True when this change was handled by a peripheral (and should not be handled by anything else), false otherwise. ++ */ ++ virtual bool Mute(void) { return ToggleMute(); } // TODO CEC only supports toggling the mute status at this time ++ ++ /*! ++ * @brief Try to unmute the audio via a peripheral. ++ * @return True when this change was handled by a peripheral (and should not be handled by anything else), false otherwise. ++ */ ++ virtual bool UnMute(void) { return ToggleMute(); } // TODO CEC only supports toggling the mute status at this time ++ ++ /*! ++ * @brief Try to get a keypress from a peripheral. ++ * @param frameTime The current frametime. ++ * @param key The fetched key. ++ * @return True when a keypress was fetched, false otherwise. ++ */ ++ virtual bool GetNextKeypress(float frameTime, CKey &key); ++ ++ bool SupportsCEC(void) const ++ { ++#if defined(HAVE_LIBCEC) ++ return true; ++#else ++ return false; ++#endif ++ } ++ + private: + CPeripherals(void); + bool LoadMappings(void); diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.02-cec-fixed_possible_deadlock.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.02-cec-fixed_possible_deadlock.patch new file mode 100644 index 0000000000..d08d45ece7 --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.02-cec-fixed_possible_deadlock.patch @@ -0,0 +1,29 @@ +From 35e4a2eb5515fe72d87b6d78b0567609df79df2b Mon Sep 17 00:00:00 2001 +From: bobo1on1 +Date: Wed, 28 Mar 2012 21:30:25 +0200 +Subject: [PATCH] fixed: possible deadlock + +--- + xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +index 0cb6602..1c91341 100644 +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +@@ -140,8 +140,10 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender, + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) + { + // this will also power off devices when we're the active source +- CSingleLock lock(m_critSection); +- m_bStop = true; ++ { ++ CSingleLock lock(m_critSection); ++ m_bStop = true; ++ } + WaitForThreadExit(0); + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) +-- +1.7.5.4 + diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.03-cec-fixed_make_sure_the_old_thread_is_stopped_before_starting_a_new_one.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.03-cec-fixed_make_sure_the_old_thread_is_stopped_before_starting_a_new_one.patch new file mode 100644 index 0000000000..c186e4d62a --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.03-cec-fixed_make_sure_the_old_thread_is_stopped_before_starting_a_new_one.patch @@ -0,0 +1,41 @@ +From de4cd8d63257af1cb9060c4b2b304a82655adb99 Mon Sep 17 00:00:00 2001 +From: bobo1on1 +Date: Wed, 28 Mar 2012 21:31:46 +0200 +Subject: [PATCH] fixed: make sure the old thread is stopped before starting a + new one, fixes throwing an exception in the main thread + +--- + xbmc/peripherals/devices/PeripheralCecAdapter.cpp | 14 ++++++++------ + 1 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +index 1c91341..a898a16 100644 +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +@@ -148,15 +148,17 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender, + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) + { +- // reconnect to the device +- CSingleLock lock(m_critSection); +- CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); ++ { ++ // reconnect to the device ++ CSingleLock lock(m_critSection); ++ CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); + +- // close the previous connection +- m_cecAdapter->Close(); ++ // close the previous connection ++ m_cecAdapter->Close(); ++ } + + // and open a new one +- m_bStop = false; ++ StopThread(); + Create(); + } + } +-- +1.7.5.4 + diff --git a/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.04-cec-PR887.patch b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.04-cec-PR887.patch new file mode 100644 index 0000000000..f870fbb3b6 --- /dev/null +++ b/packages/mediacenter/xbmc-pvr/patches/xbmc-pvr-11.0.1-801.04-cec-PR887.patch @@ -0,0 +1,630 @@ +diff -Naur xbmc-pvr-11.0.1/configure.in xbmc-pvr-11.0.1.patch/configure.in +--- xbmc-pvr-11.0.1/configure.in 2012-04-17 14:08:05.972587511 +0200 ++++ xbmc-pvr-11.0.1.patch/configure.in 2012-04-17 14:18:39.755586920 +0200 +@@ -1173,7 +1173,7 @@ + + # libcec is dyloaded, so we need to check for its headers and link any depends. + if test "x$use_libcec" != "xno"; then +- PKG_CHECK_MODULES([CEC],[libcec >= 1.5.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) ++ PKG_CHECK_MODULES([CEC],[libcec >= 1.6.0],,[use_libcec="no";AC_MSG_RESULT($libcec_disabled)]) + + if test "x$use_libcec" != "xno"; then + INCLUDES="$INCLUDES $CEC_CFLAGS" +diff -Naur xbmc-pvr-11.0.1/language/English/strings.xml xbmc-pvr-11.0.1.patch/language/English/strings.xml +--- xbmc-pvr-11.0.1/language/English/strings.xml 2012-04-17 14:08:05.974587546 +0200 ++++ xbmc-pvr-11.0.1.patch/language/English/strings.xml 2012-04-17 14:18:39.757586958 +0200 +@@ -2853,7 +2853,7 @@ + Could not detect the CEC port. Set it up manually. + Could not initialise the CEC adapter. Check your settings. + Unsupported libCEC interface version. %d is greater than the version XBMC supports (%d) +- Put this PC in standby mode when the TV is switched off ++ When the TV is switched off + HDMI port number + Connected + Adapter found, but libCEC is not available +@@ -2865,4 +2865,7 @@ + Configuration updated + Failed to set the new configuration. Please check your settings. + Send 'inactive source' command when stopping XBMC ++ Put devices in standby mode when putting the PC in standby ++ This device needs servicing ++ Ignore + +diff -Naur xbmc-pvr-11.0.1/system/peripherals.xml xbmc-pvr-11.0.1.patch/system/peripherals.xml +--- xbmc-pvr-11.0.1/system/peripherals.xml 2012-04-17 14:08:05.975587564 +0200 ++++ xbmc-pvr-11.0.1.patch/system/peripherals.xml 2012-04-17 14:18:39.757586958 +0200 +@@ -14,13 +14,14 @@ + + + +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/bus/PeripheralBus.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/bus/PeripheralBus.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/bus/PeripheralBus.cpp 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/bus/PeripheralBus.cpp 2012-04-17 14:18:39.758586977 +0200 +@@ -323,6 +323,7 @@ + peripheralFile->SetProperty("bus", PeripheralTypeTranslator::BusTypeToString(peripheral->GetBusType())); + peripheralFile->SetProperty("location", peripheral->Location()); + peripheralFile->SetProperty("class", PeripheralTypeTranslator::TypeToString(peripheral->Type())); ++ peripheralFile->SetProperty("version", peripheral->GetVersionInfo()); + items.Add(peripheralFile); + } + } +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.cpp 2012-04-17 14:17:35.207364830 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.cpp 2012-04-17 14:18:39.760587015 +0200 +@@ -41,7 +41,7 @@ + using namespace ANNOUNCEMENT; + using namespace CEC; + +-#define CEC_LIB_SUPPORTED_VERSION 0x1500 ++#define CEC_LIB_SUPPORTED_VERSION 0x1600 + + /* time in seconds to ignore standby commands from devices after the screensaver has been activated */ + #define SCREENSAVER_TIMEOUT 10 +@@ -80,7 +80,9 @@ + m_lastKeypress(0), + m_lastChange(VOLUME_CHANGE_NONE), + m_iExitCode(0), +- m_bIsMuted(false) // TODO fetch the correct initial value when system audiostatus is implemented in libCEC ++ m_bIsMuted(false), // TODO fetch the correct initial value when system audiostatus is implemented in libCEC ++ m_bGoingToStandby(false), ++ m_bIsRunning(false) + { + m_button.iButton = 0; + m_button.iDuration = 0; +@@ -96,6 +98,7 @@ + + m_bStop = true; + StopThread(true); ++ CAnnouncementManager::RemoveAnnouncer(this); + + if (m_dll && m_cecAdapter) + { +@@ -110,7 +113,11 @@ + { + if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnQuit") && m_bIsReady) + { +- m_iExitCode = data.asInteger(0); ++ { ++ CSingleLock lock(m_critSection); ++ m_iExitCode = data.asInteger(0); ++ } ++ CAnnouncementManager::RemoveAnnouncer(this); + StopThread(false); + } + else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && m_bIsReady) +@@ -142,23 +149,22 @@ + // this will also power off devices when we're the active source + { + CSingleLock lock(m_critSection); +- m_bStop = true; ++ m_bGoingToStandby = false; + } +- WaitForThreadExit(0); ++ StopThread(); + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) + { + { +- // reconnect to the device + CSingleLock lock(m_critSection); +- CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); +- +- // close the previous connection +- m_cecAdapter->Close(); ++ m_iExitCode = EXITCODE_RESTARTAPP; + } + +- // and open a new one ++ CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); ++ CAnnouncementManager::RemoveAnnouncer(this); + StopThread(); ++ ++ // and open a new one + Create(); + } + } +@@ -172,6 +178,7 @@ + m_callbacks.CBCecKeyPress = &CecKeyPress; + m_callbacks.CBCecCommand = &CecCommand; + m_callbacks.CBCecConfigurationChanged = &CecConfiguration; ++ m_callbacks.CBCecAlert = &CecAlert; + m_configuration.callbackParam = this; + m_configuration.callbacks = &m_callbacks; + +@@ -200,6 +207,8 @@ + else + { + CLog::Log(LOGDEBUG, "%s - using libCEC v%s", __FUNCTION__, m_cecAdapter->ToString((cec_server_version)m_configuration.serverVersion)); ++ if (m_configuration.serverVersion >= CEC_SERVER_VERSION_1_6_0) ++ m_strVersionInfo.Format("%d", m_configuration.iFirmwareVersion); + } + + m_bStarted = true; +@@ -297,6 +306,13 @@ + if (!OpenConnection()) + return; + ++ { ++ CSingleLock lock(m_critSection); ++ m_iExitCode = EXITCODE_QUIT; ++ m_bGoingToStandby = false; ++ m_bIsRunning = true; ++ } ++ + CAnnouncementManager::AddAnnouncer(this); + + m_queryThread = new CPeripheralCecAdapterUpdateThread(this, &m_configuration); +@@ -312,8 +328,17 @@ + } + + delete m_queryThread; ++ m_queryThread = NULL; ++ ++ bool bSendStandbyCommands(false); ++ { ++ CSingleLock lock(m_critSection); ++ bSendStandbyCommands = m_iExitCode != EXITCODE_REBOOT && ++ m_iExitCode != EXITCODE_RESTARTAPP && ++ (!m_bGoingToStandby || GetSettingBool("standby_tv_on_pc_standby")); ++ } + +- if (m_iExitCode != EXITCODE_REBOOT) ++ if (bSendStandbyCommands) + { + if (m_cecAdapter->IsLibCECActiveSource()) + { +@@ -337,7 +362,12 @@ + m_cecAdapter->Close(); + + CLog::Log(LOGDEBUG, "%s - CEC adapter processor thread ended", __FUNCTION__); +- m_bStarted = false; ++ ++ { ++ CSingleLock lock(m_critSection); ++ m_bStarted = false; ++ m_bIsRunning = false; ++ } + } + + bool CPeripheralCecAdapter::HasConnectedAudioSystem(void) +@@ -556,11 +586,15 @@ + case CEC_OPCODE_STANDBY: + /* a device was put in standby mode */ + CLog::Log(LOGDEBUG, "%s - device %1x was put in standby mode", __FUNCTION__, command.initiator); +- if (command.initiator == CECDEVICE_TV && adapter->m_configuration.bPowerOffOnStandby == 1 && ++ if (command.initiator == CECDEVICE_TV && ++ (adapter->m_configuration.bPowerOffOnStandby == 1 || adapter->m_configuration.bShutdownOnStandby == 1) && + (!adapter->m_screensaverLastActivated.IsValid() || CDateTime::GetCurrentDateTime() - adapter->m_screensaverLastActivated > CDateTimeSpan(0, 0, 0, SCREENSAVER_TIMEOUT))) + { + adapter->m_bStarted = false; +- g_application.getApplicationMessenger().Suspend(); ++ if (adapter->m_configuration.bPowerOffOnStandby == 1) ++ g_application.getApplicationMessenger().Suspend(); ++ else if (adapter->m_configuration.bShutdownOnStandby == 1) ++ g_application.getApplicationMessenger().Shutdown(); + } + break; + case CEC_OPCODE_SET_MENU_LANGUAGE: +@@ -634,6 +668,30 @@ + return 1; + } + ++int CPeripheralCecAdapter::CecAlert(void *cbParam, const libcec_alert alert, const libcec_parameter &data) ++{ ++ (void)data; ++ ++ CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; ++ if (!adapter) ++ return 0; ++ ++ int iAlertString(0); ++ switch (alert) ++ { ++ case CEC_ALERT_SERVICE_DEVICE: ++ iAlertString = 36027; ++ break; ++ default: ++ break; ++ } ++ ++ if (iAlertString) ++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(36000), g_localizeStrings.Get(iAlertString)); ++ ++ return 1; ++} ++ + int CPeripheralCecAdapter::CecKeyPress(void *cbParam, const cec_keypress &key) + { + CPeripheralCecAdapter *adapter = (CPeripheralCecAdapter *)cbParam; +@@ -695,6 +753,10 @@ + case CEC_USER_CONTROL_CODE_RIGHT_DOWN: + iButton = XINPUT_IR_REMOTE_RIGHT; + break; ++ case CEC_USER_CONTROL_CODE_NEXT_FAVORITE: ++ case CEC_USER_CONTROL_CODE_SETUP_MENU: ++ case CEC_USER_CONTROL_CODE_CONTENTS_MENU: ++ case CEC_USER_CONTROL_CODE_FAVORITE_MENU: + case CEC_USER_CONTROL_CODE_ROOT_MENU: + iButton = XINPUT_IR_REMOTE_MENU; + break; +@@ -711,7 +773,11 @@ + iButton = XINPUT_IR_REMOTE_CHANNEL_PLUS; + break; + case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: ++#if defined(XINPUT_IR_REMOTE_TELETEXT) ++ iButton = XINPUT_IR_REMOTE_TELETEXT; // only supported by the pvr branch ++#else + iButton = XINPUT_IR_REMOTE_BACK; ++#endif + break; + case CEC_USER_CONTROL_CODE_SOUND_SELECT: + iButton = XINPUT_IR_REMOTE_LANGUAGE; +@@ -806,13 +872,23 @@ + case CEC_USER_CONTROL_CODE_F4_YELLOW: + iButton = XINPUT_IR_REMOTE_YELLOW; + break; ++ case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: ++#if defined(XINPUT_IR_REMOTE_GUIDE) ++ iButton = XINPUT_IR_REMOTE_GUIDE; ++#else ++ bHasButton = false; ++#endif ++ break; ++ case CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST: ++#if defined(XINPUT_IR_REMOTE_LIVE_TV) ++ iButton = XINPUT_IR_REMOTE_LIVE_TV; ++#else ++ bHasButton = false; ++#endif ++ break; + case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: + case CEC_USER_CONTROL_CODE_EJECT: +- case CEC_USER_CONTROL_CODE_SETUP_MENU: +- case CEC_USER_CONTROL_CODE_CONTENTS_MENU: +- case CEC_USER_CONTROL_CODE_FAVORITE_MENU: + case CEC_USER_CONTROL_CODE_DOT: +- case CEC_USER_CONTROL_CODE_NEXT_FAVORITE: + case CEC_USER_CONTROL_CODE_INPUT_SELECT: + case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION: + case CEC_USER_CONTROL_CODE_HELP: +@@ -821,7 +897,6 @@ + case CEC_USER_CONTROL_CODE_ANGLE: + case CEC_USER_CONTROL_CODE_SUB_PICTURE: + case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND: +- case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: + case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: + case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: + case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: +@@ -894,11 +969,15 @@ + else if (bEnabled && !m_cecAdapter && m_bStarted) + InitialiseFeature(FEATURE_CEC); + } +- else ++ else if (IsRunning()) + { + SetConfigurationFromSettings(); + m_queryThread->UpdateConfiguration(&m_configuration); + } ++ else ++ { ++ InitialiseFeature(FEATURE_CEC); ++ } + } + + int CPeripheralCecAdapter::CecLogMessage(void *cbParam, const cec_log_message &message) +@@ -962,7 +1041,7 @@ + + // set the physical address, when baseDevice or iHDMIPort are not set + if (m_configuration.baseDevice == CECDEVICE_UNKNOWN || +- m_configuration.iHDMIPort == 0 || m_configuration.iHDMIPort > 4) ++ m_configuration.iHDMIPort == 0 || m_configuration.iHDMIPort > 15) + { + m_configuration.iPhysicalAddress = config.iPhysicalAddress; + CStdString strPhysicalAddress; +@@ -977,7 +1056,7 @@ + // set the devices to wake when starting + m_configuration.wakeDevices = config.wakeDevices; + CStdString strWakeDevices; +- for (unsigned int iPtr = 0; iPtr <= 16; iPtr++) ++ for (unsigned int iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++) + if (config.wakeDevices[iPtr]) + strWakeDevices.AppendFormat(" %X", iPtr); + SetSetting("wake_devices", strWakeDevices.Trim()); +@@ -985,10 +1064,10 @@ + // set the devices to power off when stopping + m_configuration.powerOffDevices = config.powerOffDevices; + CStdString strPowerOffDevices; +- for (unsigned int iPtr = 0; iPtr <= 16; iPtr++) ++ for (unsigned int iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++) + if (config.powerOffDevices[iPtr]) + strPowerOffDevices.AppendFormat(" %X", iPtr); +- SetSetting("wake_devices", strPowerOffDevices.Trim()); ++ SetSetting("standby_devices", strPowerOffDevices.Trim()); + + // set the boolean settings + m_configuration.bUseTVMenuLanguage = config.bUseTVMenuLanguage; +@@ -1001,17 +1080,27 @@ + SetSetting("cec_standby_screensaver", m_configuration.bPowerOffScreensaver == 1); + + m_configuration.bPowerOffOnStandby = config.bPowerOffOnStandby; +- SetSetting("standby_pc_on_tv_standby", m_configuration.bPowerOffOnStandby == 1); + + if (config.serverVersion >= CEC_SERVER_VERSION_1_5_1) + m_configuration.bSendInactiveSource = config.bSendInactiveSource; + SetSetting("send_inactive_source", m_configuration.bSendInactiveSource == 1); ++ ++ if (config.serverVersion >= CEC_SERVER_VERSION_1_6_0) ++ { ++ m_configuration.iFirmwareVersion = config.iFirmwareVersion; ++ m_strVersionInfo.Format("%d", m_configuration.iFirmwareVersion); ++ m_configuration.bShutdownOnStandby = config.bShutdownOnStandby; ++ } ++ ++ SetSetting("standby_pc_on_tv_standby", ++ m_configuration.bPowerOffOnStandby == 1 ? 13011 : ++ m_configuration.bShutdownOnStandby == 1 ? 13005 : 36028); + } + + void CPeripheralCecAdapter::SetConfigurationFromSettings(void) + { +- // client version 1.5.0 +- m_configuration.clientVersion = CEC_CLIENT_VERSION_1_5_1; ++ // client version 1.6.0 ++ m_configuration.clientVersion = CEC_CLIENT_VERSION_1_6_0; + + // device name 'XBMC' + snprintf(m_configuration.strDeviceName, 13, "%s", GetSettingString("device_name").c_str()); +@@ -1061,15 +1150,16 @@ + m_configuration.powerOffDevices.Clear(); + ReadLogicalAddresses(strStandbyDevices, m_configuration.powerOffDevices); + +- // always get the settings from the rom, when supported by the firmware +- m_configuration.bGetSettingsFromROM = 1; +- + // read the boolean settings + m_configuration.bUseTVMenuLanguage = GetSettingBool("use_tv_menu_language") ? 1 : 0; + m_configuration.bActivateSource = GetSettingBool("activate_source") ? 1 : 0; + m_configuration.bPowerOffScreensaver = GetSettingBool("cec_standby_screensaver") ? 1 : 0; +- m_configuration.bPowerOffOnStandby = GetSettingBool("standby_pc_on_tv_standby") ? 1 : 0; + m_configuration.bSendInactiveSource = GetSettingBool("send_inactive_source") ? 1 : 0; ++ ++ // read the mutually exclusive boolean settings ++ int iStandbyAction(GetSettingInt("standby_pc_on_tv_standby")); ++ m_configuration.bPowerOffOnStandby = iStandbyAction == 13011 ? 1 : 0; ++ m_configuration.bShutdownOnStandby = iStandbyAction == 13005 ? 1 : 0; + } + + void CPeripheralCecAdapter::ReadLogicalAddresses(const CStdString &strString, cec_logical_addresses &addresses) +@@ -1203,6 +1293,12 @@ + return true; + } + ++bool CPeripheralCecAdapter::IsRunning(void) const ++{ ++ CSingleLock lock(m_critSection); ++ return m_bIsRunning; ++} ++ + void CPeripheralCecAdapterUpdateThread::Process(void) + { + // set the initial configuration +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.h xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.h +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/PeripheralCecAdapter.h 2012-04-17 14:08:06.071589381 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/PeripheralCecAdapter.h 2012-04-17 14:18:39.761587034 +0200 +@@ -115,6 +115,8 @@ + static int CecLogMessage(void *cbParam, const CEC::cec_log_message &message); + static int CecCommand(void *cbParam, const CEC::cec_command &command); + static int CecConfiguration(void *cbParam, const CEC::libcec_configuration &config); ++ static int CecAlert(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter &data); ++ bool IsRunning(void) const; + + virtual bool GetNextKey(void); + virtual bool GetNextCecKey(CEC::cec_keypress &key); +@@ -140,6 +142,8 @@ + CecVolumeChange m_lastChange; + int m_iExitCode; + bool m_bIsMuted; ++ bool m_bGoingToStandby; ++ bool m_bIsRunning; + CPeripheralCecAdapterUpdateThread*m_queryThread; + CEC::ICECCallbacks m_callbacks; + CCriticalSection m_critSection; +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.cpp 2012-04-17 14:08:06.104590004 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.cpp 2012-04-17 14:18:39.752586865 +0200 +@@ -211,7 +211,15 @@ + case SETTINGS_TYPE_INT: + { + const CSettingInt *mappedSetting = (const CSettingInt *) setting; +- CSettingInt *intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); ++ CSettingInt *intSetting(NULL); ++ if (mappedSetting->GetControlType() == SPIN_CONTROL_INT) ++ { ++ intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); ++ } ++ else if (mappedSetting->GetControlType() == SPIN_CONTROL_TEXT) ++ { ++ intSetting = new CSettingInt(mappedSetting->GetOrder(), strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_entries, mappedSetting->GetControlType()); ++ } + if (intSetting) + { + intSetting->SetVisible(mappedSetting->IsVisible()); +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.h xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.h +--- xbmc-pvr-11.0.1/xbmc/peripherals/devices/Peripheral.h 2012-04-17 14:08:06.104590004 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/devices/Peripheral.h 2012-04-17 14:18:39.758586977 +0200 +@@ -53,6 +53,7 @@ + const CStdString &DeviceName(void) const { return m_strDeviceName; } + bool IsHidden(void) const { return m_bHidden; } + void SetHidden(bool bSetTo = true) { m_bHidden = bSetTo; } ++ const CStdString &GetVersionInfo(void) const { return m_strVersionInfo; } + + /*! + * @brief Check whether this device has the given feature. +@@ -161,6 +162,7 @@ + CStdString m_strVendorId; + int m_iProductId; + CStdString m_strProductId; ++ CStdString m_strVersionInfo; + bool m_bInitialised; + bool m_bHidden; + bool m_bError; +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp 2012-04-17 14:08:06.105590023 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp 2012-04-17 14:18:39.753586884 +0200 +@@ -51,6 +51,7 @@ + delete m_item; + m_boolSettings.clear(); + m_intSettings.clear(); ++ m_intTextSettings.clear(); + m_floatSettings.clear(); + m_stringSettings.clear(); + m_settings.clear(); +@@ -96,8 +97,23 @@ + CSettingInt *intSetting = (CSettingInt *) setting; + if (intSetting) + { +- m_intSettings.insert(make_pair(CStdString(intSetting->GetSetting()), (float) intSetting->GetData())); +- AddSlider(intSetting->GetOrder(), intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); ++ if (intSetting->GetControlType() == SPIN_CONTROL_INT) ++ { ++ m_intSettings.insert(make_pair(CStdString(intSetting->GetSetting()), (float) intSetting->GetData())); ++ AddSlider(intSetting->GetOrder(), intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], (float)intSetting->m_iMin, (float)intSetting->m_iStep, (float)intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); ++ } ++ else if (intSetting->GetControlType() == SPIN_CONTROL_TEXT) ++ { ++ m_intTextSettings.insert(make_pair(CStdString(intSetting->GetSetting()), intSetting->GetData())); ++ vector > entries; ++ map::iterator entriesItr = intSetting->m_entries.begin(); ++ while (entriesItr != intSetting->m_entries.end()) ++ { ++ entries.push_back(make_pair(entriesItr->first, entriesItr->second)); ++ ++entriesItr; ++ } ++ AddSpin(intSetting->GetOrder(), intSetting->GetLabel(), &m_intTextSettings[intSetting->GetSetting()], entries); ++ } + } + } + break; +@@ -160,6 +176,13 @@ + ++intItr; + } + ++ map::iterator intTextItr = m_intTextSettings.begin(); ++ while (intTextItr != m_intTextSettings.end()) ++ { ++ peripheral->SetSetting((*intTextItr).first, (*intTextItr).second); ++ ++intTextItr; ++ } ++ + map::iterator floatItr = m_floatSettings.begin(); + while (floatItr != m_floatSettings.end()) + { +@@ -210,6 +233,7 @@ + /* clear the settings */ + m_boolSettings.clear(); + m_intSettings.clear(); ++ m_intTextSettings.clear(); + m_floatSettings.clear(); + m_stringSettings.clear(); + m_settings.clear(); +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h xbmc-pvr-11.0.1.patch/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h +--- xbmc-pvr-11.0.1/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h 2012-03-27 17:55:34.000000000 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h 2012-04-17 14:18:39.753586884 +0200 +@@ -44,6 +44,7 @@ + bool m_bIsInitialising; + std::map m_boolSettings; + std::map m_intSettings; ++ std::map m_intTextSettings; + std::map m_floatSettings; + std::map m_stringSettings; + }; +diff -Naur xbmc-pvr-11.0.1/xbmc/peripherals/Peripherals.cpp xbmc-pvr-11.0.1.patch/xbmc/peripherals/Peripherals.cpp +--- xbmc-pvr-11.0.1/xbmc/peripherals/Peripherals.cpp 2012-04-17 14:08:06.106590043 +0200 ++++ xbmc-pvr-11.0.1.patch/xbmc/peripherals/Peripherals.cpp 2012-04-17 14:18:39.752586865 +0200 +@@ -41,6 +41,7 @@ + #include "guilib/LocalizeStrings.h" + #include "dialogs/GUIDialogKaiToast.h" + #include "utils/StringUtils.h" ++#include "Util.h" + #include "guilib/Key.h" + + using namespace PERIPHERALS; +@@ -486,29 +487,46 @@ + float fMax = currentNode->Attribute("max") ? (float) atof(currentNode->Attribute("max")) : 0; + setting = new CSettingFloat(0, strKey, iLabelId, fValue, fMin, fStep, fMax, SPIN_CONTROL_FLOAT); + } ++ else if (strSettingsType.Equals("enum")) ++ { ++ CStdString strEnums(currentNode->Attribute("lvalues")); ++ if (!strEnums.IsEmpty()) ++ { ++ map enums; ++ vector valuesVec; ++ CUtil::Tokenize(strEnums, valuesVec, "|"); ++ for (unsigned int i = 0; i < valuesVec.size(); i++) ++ enums.insert(make_pair(atoi(valuesVec[i]), atoi(valuesVec[i]))); ++ int iValue = currentNode->Attribute("value") ? atoi(currentNode->Attribute("value")) : 0; ++ setting = new CSettingInt(0, strKey, iLabelId, iValue, enums, SPIN_CONTROL_TEXT); ++ } ++ } + else + { + CStdString strValue(currentNode->Attribute("value")); + setting = new CSettingString(0, strKey, iLabelId, strValue, EDIT_CONTROL_INPUT, !bConfigurable, -1); + } + +- //TODO add more types if needed ++ if (setting) ++ { ++ //TODO add more types if needed + +- /* set the visibility */ +- setting->SetVisible(bConfigurable); ++ /* set the visibility */ ++ setting->SetVisible(bConfigurable); + +- /* set the order */ +- int iOrder(0); +- currentNode->Attribute("order", &iOrder); +- /* if the order attribute is invalid or 0, then the setting will be added at the end */ +- if (iOrder < 0) +- iOrder = 0; +- setting->SetOrder(iOrder); +- if (iOrder > iMaxOrder) +- iMaxOrder = iOrder; ++ /* set the order */ ++ int iOrder(0); ++ currentNode->Attribute("order", &iOrder); ++ /* if the order attribute is invalid or 0, then the setting will be added at the end */ ++ if (iOrder < 0) ++ iOrder = 0; ++ setting->SetOrder(iOrder); ++ if (iOrder > iMaxOrder) ++ iMaxOrder = iOrder; + +- /* and add this new setting */ +- m_settings[strKey] = setting; ++ /* and add this new setting */ ++ m_settings[strKey] = setting; ++ } + + currentNode = currentNode->NextSiblingElement("setting"); + }