+libcec (2.1.4-1) unstable; urgency=low
+
+ * changed / added:
+ * set the vendor id of devices handled by libCEC to our vendor id
+ * added protection against standby without a notification from XBMC and
+ clock changes. issue #186
+ * update system audio mode when audio system devices are activated
+ * added vendor id and name 'Harman/Kardon'
+ * added vendor id and name 'Marantz'
+ * cec-tray: support for away mode
+ * cec-tray: support for screensaver events
+ * fixed:
+ * fixed potential crash when SendCommand returns NULL
+ * fixed crash when CCECProcessor::Transmit was called after
+ CCECProcessor::Close
+ * always call the SourceActivated() callback in
+ CCECBusDevice::MarkAsActiveSource(), even when we were already active,
+ and let clients handle dupes. this prevented the screensaver from
+ being cancelled in XBMC
+ * send our vendor id when the tv sends it's vendor id
+ * transmit our physical address when the TV sends it's physical address
+ * potential deadlock
+ * leak on exit in CWaitForResponse::Clear()
+ * also transmit an active source message as response to a set stream path
+ command when we were already marked as active. bugzid: 3116
+ * only send an active source message when receiving a routing change to an
+ address handled by libCEC. issue #56
+ * HandleVendorRemoteButtonUp -> HandleUserControlRelease for all vendors
+ * silence warning for xx:a0:00:09:b0:00:80:20. bugzid: 2559
+ * fixed comboKeyTimeout=0. closes #168
+ * Panasonic: doesn't request the active source status when powered up, but
+ it does send a vendor command. send an active source message when we're
+ marked as active source after receiving this command. issue #192
+ * possible crash when the tv does not respond to polls and the client isn't
+ registered yet. don't poll the tv in monitoring mode. closes #163
+ * Panasonic: standby command
+ * Panasonic: silence 'unmapped code' warning. bugzid: 2375
+ * LG: clean up and attempt to fix issue #176
+ * LG: newer firmwares don't send a second power status request after it's
+ been requested once and replied with 'standby -> on' like previous
+ versions. send an active source message in an attempt to fix this. issue:
+ #176
+ * Sharp: check whether the 'auto power on' option is disabled and tell the
+ user how to enable it
+ * Samsung: respond to vendor command 0x23 sent by samsung. attempt to fix
+ bugzid: 2164
+ * cec-client: try to reconnect when the connection was lost
+ * cec-tray: crash on load (MissingManifestResourceException)
+ * cec-tray: crash or deadlock on exit
+ * cec-tray: crash when the connection to the adapter was lost
+ * cec-tray: display TV not responding warning on top
+ * windows: build libCEC and cec-client against toolset v100 (VS2010)
+ * FreeBSD: proper the adapter detection. credits @fneufneu
+ * suppress mangling warning. credits @warped-rudi. closes #190
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Sat, 13 Dec 2013 16:02:00 +0100
+
libcec (2.1.3-1) unstable; urgency=low
* changed / added:
LIBS_LIBCEC="$LIBS"
LIBS="$libs_client"
-CXXFLAGS="$CXXFLAGS -fPIC -Wall -Wextra -Wno-missing-field-initializers"
+CXXFLAGS="$CXXFLAGS -fPIC -Wall -Wextra -Wno-missing-field-initializers -Wno-psabi"
if test "x$use_debug" = "xyes"; then
CXXFLAGS="$CXXFLAGS -g"
+libcec (2.1.4-1) unstable; urgency=low
+
+ * changed / added:
+ * set the vendor id of devices handled by libCEC to our vendor id
+ * added protection against standby without a notification from XBMC and
+ clock changes. issue #186
+ * update system audio mode when audio system devices are activated
+ * added vendor id and name 'Harman/Kardon'
+ * added vendor id and name 'Marantz'
+ * cec-tray: support for away mode
+ * cec-tray: support for screensaver events
+ * fixed:
+ * fixed potential crash when SendCommand returns NULL
+ * fixed crash when CCECProcessor::Transmit was called after
+ CCECProcessor::Close
+ * always call the SourceActivated() callback in
+ CCECBusDevice::MarkAsActiveSource(), even when we were already active,
+ and let clients handle dupes. this prevented the screensaver from
+ being cancelled in XBMC
+ * send our vendor id when the tv sends it's vendor id
+ * transmit our physical address when the TV sends it's physical address
+ * potential deadlock
+ * leak on exit in CWaitForResponse::Clear()
+ * also transmit an active source message as response to a set stream path
+ command when we were already marked as active. bugzid: 3116
+ * only send an active source message when receiving a routing change to an
+ address handled by libCEC. issue #56
+ * HandleVendorRemoteButtonUp -> HandleUserControlRelease for all vendors
+ * silence warning for xx:a0:00:09:b0:00:80:20. bugzid: 2559
+ * fixed comboKeyTimeout=0. closes #168
+ * Panasonic: doesn't request the active source status when powered up, but
+ it does send a vendor command. send an active source message when we're
+ marked as active source after receiving this command. issue #192
+ * possible crash when the tv does not respond to polls and the client isn't
+ registered yet. don't poll the tv in monitoring mode. closes #163
+ * Panasonic: standby command
+ * Panasonic: silence 'unmapped code' warning. bugzid: 2375
+ * LG: clean up and attempt to fix issue #176
+ * LG: newer firmwares don't send a second power status request after it's
+ been requested once and replied with 'standby -> on' like previous
+ versions. send an active source message in an attempt to fix this. issue:
+ #176
+ * Sharp: check whether the 'auto power on' option is disabled and tell the
+ user how to enable it
+ * Samsung: respond to vendor command 0x23 sent by samsung. attempt to fix
+ bugzid: 2164
+ * cec-client: try to reconnect when the connection was lost
+ * cec-tray: crash on load (MissingManifestResourceException)
+ * cec-tray: crash or deadlock on exit
+ * cec-tray: crash when the connection to the adapter was lost
+ * cec-tray: display TV not responding warning on top
+ * windows: build libCEC and cec-client against toolset v100 (VS2010)
+ * FreeBSD: proper the adapter detection. credits @fneufneu
+ * suppress mangling warning. credits @warped-rudi. closes #190
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com> Sat, 13 Dec 2013 16:02:00 +0100
+
libcec (2.1.3-1) unstable; urgency=low
* changed / added:
typedef enum cec_vendor_id
{
- CEC_VENDOR_TOSHIBA = 0x000039,
- CEC_VENDOR_SAMSUNG = 0x0000F0,
- CEC_VENDOR_DENON = 0x0005CD,
- CEC_VENDOR_LOEWE = 0x000982,
- CEC_VENDOR_ONKYO = 0x0009B0,
- CEC_VENDOR_MEDION = 0x000CB8,
- CEC_VENDOR_TOSHIBA2 = 0x000CE7,
- CEC_VENDOR_AKAI = 0x0020C7,
- CEC_VENDOR_AOC = 0x002467,
- CEC_VENDOR_PANASONIC = 0x008045,
- CEC_VENDOR_PHILIPS = 0x00903E,
- CEC_VENDOR_DAEWOO = 0x009053,
- CEC_VENDOR_YAMAHA = 0x00A0DE,
- CEC_VENDOR_GRUNDIG = 0x00D0D5,
- CEC_VENDOR_PIONEER = 0x00E036,
- CEC_VENDOR_LG = 0x00E091,
- CEC_VENDOR_SHARP = 0x08001F,
- CEC_VENDOR_SONY = 0x080046,
- CEC_VENDOR_BROADCOM = 0x18C086,
- CEC_VENDOR_VIZIO = 0x6B746D,
- CEC_VENDOR_BENQ = 0x8065E9,
- CEC_VENDOR_UNKNOWN = 0
+ CEC_VENDOR_TOSHIBA = 0x000039,
+ CEC_VENDOR_SAMSUNG = 0x0000F0,
+ CEC_VENDOR_DENON = 0x0005CD,
+ CEC_VENDOR_MARANTZ = 0x000678,
+ CEC_VENDOR_LOEWE = 0x000982,
+ CEC_VENDOR_ONKYO = 0x0009B0,
+ CEC_VENDOR_MEDION = 0x000CB8,
+ CEC_VENDOR_TOSHIBA2 = 0x000CE7,
+ CEC_VENDOR_PULSE_EIGHT = 0x001582,
+ CEC_VENDOR_AKAI = 0x0020C7,
+ CEC_VENDOR_AOC = 0x002467,
+ CEC_VENDOR_PANASONIC = 0x008045,
+ CEC_VENDOR_PHILIPS = 0x00903E,
+ CEC_VENDOR_DAEWOO = 0x009053,
+ CEC_VENDOR_YAMAHA = 0x00A0DE,
+ CEC_VENDOR_GRUNDIG = 0x00D0D5,
+ CEC_VENDOR_PIONEER = 0x00E036,
+ CEC_VENDOR_LG = 0x00E091,
+ CEC_VENDOR_SHARP = 0x08001F,
+ CEC_VENDOR_SONY = 0x080046,
+ CEC_VENDOR_BROADCOM = 0x18C086,
+ CEC_VENDOR_VIZIO = 0x6B746D,
+ CEC_VENDOR_BENQ = 0x8065E9,
+ CEC_VENDOR_HARMAN_KARDON = 0x9C645E,
+ CEC_VENDOR_UNKNOWN = 0
} cec_vendor_id;
typedef enum cec_adapter_type
CEC_CLIENT_VERSION_2_1_1 = 0x2101,
CEC_CLIENT_VERSION_2_1_2 = 0x2102,
CEC_CLIENT_VERSION_2_1_3 = 0x2103,
- CEC_CLIENT_VERSION_CURRENT = 0x2103
+ CEC_CLIENT_VERSION_2_1_4 = 0x2104,
+ CEC_CLIENT_VERSION_CURRENT = 0x2104
} cec_client_version;
typedef enum cec_server_version
CEC_SERVER_VERSION_2_1_1 = 0x2101,
CEC_SERVER_VERSION_2_1_2 = 0x2102,
CEC_SERVER_VERSION_2_1_3 = 0x2103,
- CEC_SERVER_VERSION_CURRENT = 0x2103
+ CEC_SERVER_VERSION_2_1_4 = 0x2104,
+ CEC_SERVER_VERSION_CURRENT = 0x2104
} cec_server_version;
struct libcec_configuration
<ClInclude Include="..\..\src\lib\implementations\RLCommandHandler.h" />
<ClInclude Include="..\..\src\lib\implementations\SLCommandHandler.h" />
<ClInclude Include="..\..\src\lib\implementations\VLCommandHandler.h" />
+ <ClInclude Include="..\..\src\lib\implementations\RHCommandHandler.h" />
+ <ClInclude Include="..\..\src\lib\implementations\AQCommandHandler.h" />
<ClInclude Include="..\..\src\lib\LibCEC.h" />
<ClInclude Include="..\..\src\lib\platform\adl\adl-edid.h" />
<ClInclude Include="..\..\src\lib\platform\adl\adl_defines.h" />
<ClCompile Include="..\..\src\lib\implementations\RLCommandHandler.cpp" />
<ClCompile Include="..\..\src\lib\implementations\SLCommandHandler.cpp" />
<ClCompile Include="..\..\src\lib\implementations\VLCommandHandler.cpp" />
+ <ClCompile Include="..\..\src\lib\implementations\RHCommandHandler.cpp" />
+ <ClCompile Include="..\..\src\lib\implementations\AQCommandHandler.cpp" />
<ClCompile Include="..\..\src\lib\LibCEC.cpp" />
<ClCompile Include="..\..\src\lib\LibCECC.cpp" />
<ClCompile Include="..\..\src\lib\LibCECDll.cpp" />
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<ClInclude Include="..\..\src\lib\implementations\VLCommandHandler.h">
<Filter>implementations</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\lib\implementations\RHCommandHandler.h">
+ <Filter>implementations</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\implementations\ANCommandHandler.h">
+ <Filter>implementations</Filter>
+ </ClInclude>
<ClInclude Include="..\..\src\lib\devices\CECAudioSystem.h">
<Filter>devices</Filter>
</ClInclude>
<ClCompile Include="..\..\src\lib\implementations\VLCommandHandler.cpp">
<Filter>implementations</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\lib\implementations\RHCommandHandler.cpp">
+ <Filter>implementations</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\implementations\AQCommandHandler.cpp">
+ <Filter>implementations</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\lib\devices\CECAudioSystem.cpp">
<Filter>devices</Filter>
</ClCompile>
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v110</PlatformToolset>
+ <PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.1.3.0")]
-[assembly: AssemblyFileVersion("2.1.3.0")]
+[assembly: AssemblyVersion("2.1.4.0")]
+[assembly: AssemblyFileVersion("2.1.4.0")]
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
-[assembly:AssemblyVersionAttribute("2.1.3.0")];
+[assembly:AssemblyVersionAttribute("2.1.4.0")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
/// </summary>
public enum class CecVendorId
{
- Toshiba = 0x000039,
- Samsung = 0x0000F0,
- Denon = 0x0005CD,
- Loewe = 0x000982,
- Onkyo = 0x0009B0,
- Medion = 0x000CB8,
- Akai = 0x0020C7,
- AOC = 0x002467,
- Panasonic = 0x008045,
- Philips = 0x00903E,
- Daewoo = 0x009053,
- Yamaha = 0x00A0DE,
- Grundig = 0x00D0D5,
- Pioneer = 0x00E036,
- LG = 0x00E091,
- Sharp = 0x08001F,
- Sony = 0x080046,
- Broadcom = 0x18C086,
- Vizio = 0x6B746D,
- Benq = 0x8065E9,
- Unknown = 0
+ Toshiba = 0x000039,
+ Samsung = 0x0000F0,
+ Denon = 0x0005CD,
+ Marantz = 0x000678,
+ Loewe = 0x000982,
+ Onkyo = 0x0009B0,
+ Medion = 0x000CB8,
+ Toshiba2 = 0x000CE7,
+ PulseEight = 0x001582,
+ Akai = 0x0020C7,
+ AOC = 0x002467,
+ Panasonic = 0x008045,
+ Philips = 0x00903E,
+ Daewoo = 0x009053,
+ Yamaha = 0x00A0DE,
+ Grundig = 0x00D0D5,
+ Pioneer = 0x00E036,
+ LG = 0x00E091,
+ Sharp = 0x08001F,
+ Sony = 0x080046,
+ Broadcom = 0x18C086,
+ Vizio = 0x6B746D,
+ Benq = 0x8065E9,
+ HarmanKardon = 0x9C645E,
+ Unknown = 0
};
/// <summary>
/// </summary>
Version2_1_3 = 0x2103,
/// <summary>
+ /// v2.1.4
+ /// </summary>
+ Version2_1_4 = 0x2104,
+ /// <summary>
/// The current version
/// </summary>
- CurrentVersion = 0x2103
+ CurrentVersion = 0x2104
};
/// <summary>
/// v2.1.3
/// </summary>
Version2_1_3 = 0x2103,
+ /// <summary>
+ /// v2.1.4
+ /// </summary>
+ Version2_1_4 = 0x2104,
/// <summary>
/// The current version
/// </summary>
- CurrentVersion = 0x2103
+ CurrentVersion = 0x2104
};
/// <summary>
CecParameterType newType = (CecParameterType)data.paramType;
if (newType == CecParameterType::ParameterTypeString)
{
- System::String ^ newData = gcnew System::String((const char *)data.paramData, 0, 128);
+ System::String ^ newData = gcnew System::String(data.paramData ? (const char *)data.paramData : "", 0, 128);
CecParameter ^ newParam = gcnew CecParameter(newType, newData);
iReturn = m_callbacks->ReceiveAlert((CecAlert)alert, newParam);
}
</ItemGroup>
<ItemGroup>
<Compile Include="controller\Actions.cs" />
+ <Compile Include="controller\actions\ActivateSource.cs" />
<Compile Include="controller\actions\GetCurrentPhysicalAddress.cs" />
<Compile Include="controller\actions\UpdateConfiguration.cs" />
<Compile Include="controller\actions\ConnectToDevice.cs" />
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.1.3.0")]
-[assembly: AssemblyFileVersion("2.1.3.0")]
+[assembly: AssemblyVersion("2.1.4.0")]
+[assembly: AssemblyFileVersion("2.1.4.0")]
_controller.CheckActiveDevices();
break;
case UpdateEventType.ProcessCompleted:
- if (!(_activeProcess is GetCurrentPhysicalAddress))
+ if (!(_activeProcess is GetCurrentPhysicalAddress) && !SuppressUpdates)
{
_activeProcess = new GetCurrentPhysicalAddress(_controller.Lib);
_activeProcess.EventHandler += ProcessEventHandler;
break;
case UpdateEventType.ExitApplication:
+ SuppressUpdates = true;
_activeProcess = null;
Application.Exit();
break;
/// Activate the source at the given logical address.
/// </summary>
/// <param name="address">The logical address of the device to activate</param>
- public void ActivateSource(CecLogicalAddress address)
+ public void SetStreamPath(CecLogicalAddress address)
{
if (SuppressUpdates || _activeProcess != null) return;
(new Thread(_activeProcess.Run)).Start();
}
+ public void ActivateSource()
+ {
+ if (SuppressUpdates || _activeProcess != null) return;
+
+ _controller.SetControlsEnabled(false);
+ _activeProcess = new ActivateSource(_controller.Lib);
+ _activeProcess.EventHandler += ProcessEventHandler;
+ (new Thread(_activeProcess.Run)).Start();
+ }
+
/// <summary>
/// Send a standby command to the device at the given logical address
/// </summary>
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+using CecSharp;
+using LibCECTray.Properties;
+
+namespace LibCECTray.controller.actions
+{
+ class ActivateSource : UpdateProcess
+ {
+ public ActivateSource(LibCecSharp lib)
+ {
+ _lib = lib;
+ }
+
+ public override void Process()
+ {
+ SendEvent(UpdateEventType.StatusText, Resources.action_activating_source);
+ SendEvent(UpdateEventType.ProgressBar, 50);
+
+ var bResult = _lib.SetActiveSource(CecDeviceType.Reserved);
+ SendEvent(UpdateEventType.ProgressBar, 100);
+ }
+
+ private readonly LibCecSharp _lib;
+ }
+}
SendEvent(UpdateEventType.StatusText, Resources.action_sending_power_on);
_lib.PowerOnDevices(CecLogicalAddress.Broadcast);
- SendEvent(UpdateEventType.StatusText, Resources.action_detecting_tv_vendor);
- SendEvent(UpdateEventType.ProgressBar, 30);
- SendEvent(UpdateEventType.TVVendorId, (int)_lib.GetDeviceVendorId(CecLogicalAddress.Tv));
+ if (_lib.IsActiveDevice(CecLogicalAddress.Tv))
+ {
+ SendEvent(UpdateEventType.StatusText, Resources.action_detecting_tv_vendor);
+ SendEvent(UpdateEventType.ProgressBar, 30);
+ SendEvent(UpdateEventType.TVVendorId, (int)_lib.GetDeviceVendorId(CecLogicalAddress.Tv));
+ }
SendEvent(UpdateEventType.ProgressBar, 50);
SendEvent(UpdateEventType.StatusText, Resources.action_detecting_avr);
SendEvent(UpdateEventType.AVRVendorId, (int)_lib.GetDeviceVendorId(CecLogicalAddress.AudioSystem));
}
- if (!_lib.GetDevicePowerStatus(CecLogicalAddress.Tv).Equals(CecPowerStatus.On))
+ if (_lib.IsActiveDevice(CecLogicalAddress.Tv)&& !_lib.GetDevicePowerStatus(CecLogicalAddress.Tv).Equals(CecPowerStatus.On))
{
SendEvent(UpdateEventType.ProgressBar, 70);
SendEvent(UpdateEventType.StatusText, Resources.action_activating_source);
if (!_lib.IsActiveDevice(CecLogicalAddress.Tv))
{
- MessageBox.Show(Resources.alert_tv_poll_failed, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ MessageBox.Show(Resources.alert_tv_poll_failed, Resources.cec_alert, MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
}
SendEvent(UpdateEventType.ProgressBar, 100);
using LibCECTray.settings;
using Microsoft.Win32;
using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Threading;
namespace LibCECTray.ui
{
- /// <summary>
- /// The tab pages in this application
- /// </summary>
- internal enum ConfigTab
- {
- Configuration,
- KeyConfiguration,
- Tester,
- Log,
- WMC,
- XBMC
- }
-
/// <summary>
/// Main LibCecTray GUI
/// </summary>
{
Text = Resources.app_name;
InitializeComponent();
+
+ _sstimer.Interval = 5000;
+ _sstimer.Tick += ScreensaverActiveCheck;
+ _sstimer.Enabled = false;
+
+ _lastScreensaverActivated = DateTime.Now;
+
VisibleChanged += delegate
{
if (!Visible)
else
OnShow();
};
- SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(OnPowerModeChanged);
+
SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
}
public void OnSessionEnding(object sender, SessionEndingEventArgs e)
{
+ Controller.CECActions.SuppressUpdates = true;
Controller.Close();
}
- public void OnPowerModeChanged(Object sender, PowerModeChangedEventArgs e)
+ #region Power state change window messages
+ private const int WM_POWERBROADCAST = 0x0218;
+ private const int WM_SYSCOMMAND = 0x0112;
+
+ private const int PBT_APMSUSPEND = 0x0004;
+ private const int PBT_APMRESUMESUSPEND = 0x0007;
+ private const int PBT_APMRESUMECRITICAL = 0x0006;
+ private const int PBT_APMRESUMEAUTOMATIC = 0x0012;
+ private const int PBT_POWERSETTINGCHANGE = 0x8013;
+
+ private static Guid GUID_SYSTEM_AWAYMODE = new Guid("98a7f580-01f7-48aa-9c0f-44352c29e5c0");
+
+ private const int SC_SCREENSAVE = 0xF140;
+ private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
+
+ [DllImport("user32.dll", SetLastError = true)]
+ static extern bool SystemParametersInfo(int action, int param, ref int retval, int updini);
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ internal struct POWERBROADCAST_SETTING
+ {
+ public Guid PowerSetting;
+ public uint DataLength;
+ public byte Data;
+ }
+ #endregion
+
+ /// <summary>
+ /// Check for power state changes, and pass up when it's something we don't care about
+ /// </summary>
+ /// <param name="msg">The incoming window message</param>
+ protected override void WndProc(ref Message msg)
{
- switch (e.Mode)
+ if (msg.Msg == WM_SYSCOMMAND && (msg.WParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
{
- case PowerModes.Resume:
- Controller.Initialise();
- break;
- case PowerModes.Suspend:
- Controller.Close();
- break;
- case PowerModes.StatusChange:
- break;
+ // there's no event for screensaver exit
+ if (!_sstimer.Enabled)
+ {
+ // guard against screensaver failing, and resulting in power up and down spam to the tv
+ TimeSpan diff = DateTime.Now - _lastScreensaverActivated;
+ if (diff.TotalSeconds > 60)
+ {
+ _sstimer.Enabled = true;
+ _lastScreensaverActivated = DateTime.Now;
+ Controller.CECActions.SendStandby(CecLogicalAddress.Broadcast);
+ }
+ }
}
+ else if (msg.Msg == WM_POWERBROADCAST)
+ {
+ switch (msg.WParam.ToInt32())
+ {
+ case PBT_APMSUSPEND:
+ OnSleep();
+ return;
+
+ case PBT_APMRESUMESUSPEND:
+ case PBT_APMRESUMECRITICAL:
+ case PBT_APMRESUMEAUTOMATIC:
+ OnWake();
+ return;
+
+ case PBT_POWERSETTINGCHANGE:
+ {
+ POWERBROADCAST_SETTING pwr = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(msg.LParam, typeof(POWERBROADCAST_SETTING));
+ if (pwr.PowerSetting == GUID_SYSTEM_AWAYMODE && pwr.DataLength == Marshal.SizeOf(typeof(Int32)))
+ {
+ switch (pwr.Data)
+ {
+ case 0:
+ // do _not_ wake the pc when away mode is deactivated
+ //OnWake();
+ //return;
+ case 1:
+ Controller.CECActions.SendStandby(CecLogicalAddress.Broadcast);
+ return;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // pass up when not handled
+ base.WndProc(ref msg);
+ }
+
+ private void ScreensaverActiveCheck(object sender, EventArgs e)
+ {
+ if (!IsScreensaverActive())
+ {
+ _sstimer.Enabled = false;
+ Controller.CECActions.ActivateSource();
+ }
+ }
+
+ private bool IsScreensaverActive()
+ {
+ int active = 1;
+ SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref active, 0);
+ return active == 1;
+ }
+
+ private void OnWake()
+ {
+ Controller.Initialise();
+ }
+
+ private void OnSleep()
+ {
+ Controller.CECActions.SuppressUpdates = true;
+ AsyncDisconnect dc = new AsyncDisconnect(Controller);
+ (new Thread(dc.Process)).Start();
}
public override sealed string Text
Hide();
if (disposing)
{
- Controller.Close();
+ OnSleep();
}
if (disposing && (components != null))
{
private void BActivateSourceClick(object sender, EventArgs e)
{
- Controller.CECActions.ActivateSource(GetTargetDevice());
+ Controller.CECActions.SetStreamPath(GetTargetDevice());
}
private void CbCommandDestinationSelectedIndexChanged(object sender, EventArgs e)
{
get { return GetSelectedTabName(tabPanel, tabPanel.TabPages); }
}
+
+ private System.Windows.Forms.Timer _sstimer = new System.Windows.Forms.Timer();
+ private DateTime _lastScreensaverActivated;
#endregion
private void AddNewApplicationToolStripMenuItemClick(object sender, EventArgs e)
Controller.DisplayDialog(appConfig, false);
}
}
+
+ /// <summary>
+ /// The tab pages in this application
+ /// </summary>
+ internal enum ConfigTab
+ {
+ Configuration,
+ KeyConfiguration,
+ Tester,
+ Log,
+ WMC,
+ XBMC
+ }
+
+ class AsyncDisconnect
+ {
+ public AsyncDisconnect(CECController controller)
+ {
+ _controller = controller;
+ }
+
+ public void Process()
+ {
+ _controller.Close();
+ }
+
+ private CECController _controller;
+ }
}
{
SetControlVisible(lInactiveSource, false);
SetControlVisible(lActiveSource, true);
- _controller.CECActions.ActivateSource(Address);
+ _controller.CECActions.SetStreamPath(Address);
}
private void LStandbyLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
- cec_user_control_code comboKey(m_configuration.comboKey);
- uint32_t iTimeoutMs(m_configuration.iComboKeyTimeoutMs);
-
- if (key.duration > iTimeoutMs || m_iCurrentButton != comboKey || bSendComboKey)
+ if (key.duration > m_configuration.iComboKeyTimeoutMs ||
+ m_configuration.iComboKeyTimeoutMs == 0 ||
+ m_iCurrentButton != m_configuration.comboKey ||
+ bSendComboKey)
{
key.keycode = m_iCurrentButton;
{
CLockObject lock(m_mutex);
- if (m_iCurrentButton == comboKey && key.duration == 0)
+ if (m_configuration.iComboKeyTimeoutMs > 0 && m_iCurrentButton == comboKey && key.duration == 0)
{
// stop + ok -> exit
if (key.keycode == CEC_USER_CONTROL_CODE_SELECT)
m_configuration.iComboKeyTimeoutMs : CEC_DEFAULT_COMBO_TIMEOUT_MS);
if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN &&
- ((m_iCurrentButton == comboKey && iNow - m_buttontime > iTimeoutMs) ||
+ ((m_iCurrentButton == comboKey && iTimeoutMs > 0 && iNow - m_buttontime > iTimeoutMs) ||
(m_iCurrentButton != comboKey && iNow - m_buttontime > CEC_BUTTON_TIMEOUT)))
{
key.duration = (unsigned int) (iNow - m_buttontime);
#define ToString(x) CCECTypeUtils::ToString(x)
+CCECStandbyProtection::CCECStandbyProtection(CCECProcessor* processor) :
+ m_processor(processor) {}
+CCECStandbyProtection::~CCECStandbyProtection(void) {}
+
+void* CCECStandbyProtection::Process(void)
+{
+ int64_t last = GetTimeMs();
+ int64_t next;
+ while (!IsStopped())
+ {
+ PLATFORM::CEvent::Sleep(1000);
+
+ next = GetTimeMs();
+
+ // reset the connection if the clock changed
+ if (next < last || next - last > 10000)
+ {
+ libcec_parameter param;
+ param.paramData = NULL; param.paramType = CEC_PARAMETER_TYPE_UNKOWN;
+ m_processor->GetLib()->Alert(CEC_ALERT_CONNECTION_LOST, param);
+ break;
+ }
+
+ last = next;
+ }
+ return NULL;
+}
+
CCECProcessor::CCECProcessor(CLibCEC *libcec) :
m_bInitialised(false),
m_communication(NULL),
m_iLastTransmission(0),
m_bMonitor(true),
m_addrAllocator(NULL),
- m_bStallCommunication(false)
+ m_bStallCommunication(false),
+ m_connCheck(NULL)
{
m_busDevices = new CCECDeviceMap(this);
}
SetCECInitialised(false);
// stop the processor
+ DELETE_AND_NULL(m_connCheck);
StopThread(-1);
m_inBuffer.Broadcast();
StopThread();
// close the connection
+ CLockObject lock(m_mutex);
DELETE_AND_NULL(m_communication);
}
{
m_libcec->AddLog(CEC_LOG_DEBUG, "processor thread started");
+ if (!m_connCheck)
+ m_connCheck = new CCECStandbyProtection(this);
+ m_connCheck->CreateThread();
+
cec_command command; command.Clear();
CTimeout activeSourceCheck(ACTIVE_SOURCE_CHECK_INTERVAL);
CTimeout tvPresentCheck(TV_PRESENT_CHECK_INTERVAL);
// check whether the TV is present and responding
if (tvPresentCheck.TimeLeft() == 0)
{
- if (!m_busDevices->At(CECDEVICE_TV)->IsPresent())
+ CCECClient *primary = GetPrimaryClient();
+ // only check whether the tv responds to polls when a client is connected and not in monitoring mode
+ if (primary && primary->GetConfiguration()->bMonitorOnly != 1)
{
- libcec_parameter param;
- param.paramType = CEC_PARAMETER_TYPE_STRING;
- param.paramData = (void*)"TV does not respond to CEC polls";
- GetPrimaryClient()->Alert(CEC_ALERT_TV_POLL_FAILED, param);
+ if (!m_busDevices->At(CECDEVICE_TV)->IsPresent())
+ {
+ libcec_parameter param;
+ param.paramType = CEC_PARAMETER_TYPE_STRING;
+ param.paramData = (void*)"TV does not respond to CEC polls";
+ primary->Alert(CEC_ALERT_TV_POLL_FAILED, param);
+ }
}
tvPresentCheck.Init(TV_PRESENT_CHECK_INTERVAL);
}
// reset the state of this message to 'unknown'
cec_adapter_message_state adapterState = ADAPTER_MESSAGE_STATE_UNKNOWN;
+ CLockObject lock(m_mutex);
+ if (!m_communication)
+ return false;
+
if (!m_communication->SupportsSourceLogicalAddress(transmitData.initiator))
{
if (transmitData.initiator == CECDEVICE_UNREGISTERED && m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE))
}
// wait until we finished allocating a new LA if it got lost
+ lock.Unlock();
while (m_bStallCommunication) Sleep(5);
+ lock.Lock();
- {
- CLockObject lock(m_mutex);
- m_iLastTransmission = GetTimeMs();
- // set the number of tries
- iMaxTries = initiator->GetHandler()->GetTransmitRetries() + 1;
- initiator->MarkHandlerReady();
- }
+ m_iLastTransmission = GetTimeMs();
+ // set the number of tries
+ iMaxTries = initiator->GetHandler()->GetTransmitRetries() + 1;
+ initiator->MarkHandlerReady();
// and try to send the command
while (bRetry && ++iTries < iMaxTries)
client->GetPrimaryDevice()->TransmitOSDName(CECDEVICE_TV, false);
// request the power status of the TV
- tv->RequestPowerStatus(sourceAddress, true);
+ tv->RequestPowerStatus(sourceAddress, true, true);
return bReturn;
}
class CCECTV;
class CCECClient;
class CCECProcessor;
+ class CCECStandbyProtection;
class CCECAllocateLogicalAddress : public PLATFORM::CThread
{
bool m_bMonitor;
CCECAllocateLogicalAddress* m_addrAllocator;
bool m_bStallCommunication;
+ CCECStandbyProtection* m_connCheck;
+ };
+
+ class CCECStandbyProtection : public PLATFORM::CThread
+ {
+ public:
+ CCECStandbyProtection(CCECProcessor* processor);
+ virtual ~CCECStandbyProtection(void);
+ void* Process(void);
+
+ private:
+ CCECProcessor* m_processor;
};
};
return "Loewe";
case CEC_VENDOR_DENON:
return "Denon";
+ case CEC_VENDOR_MARANTZ:
+ return "Marantz";
+ case CEC_VENDOR_HARMAN_KARDON:
+ return "Harman/Kardon";
+ case CEC_VENDOR_PULSE_EIGHT:
+ return "Pulse Eight";
default:
return "Unknown";
}
return "2.1.2";
case CEC_CLIENT_VERSION_2_1_3:
return "2.1.3";
+ case CEC_CLIENT_VERSION_2_1_4:
+ return "2.1.4";
default:
return "Unknown";
}
return "2.1.2";
case CEC_SERVER_VERSION_2_1_3:
return "2.1.3";
+ case CEC_SERVER_VERSION_2_1_4:
+ return "2.1.4";
default:
return "Unknown";
}
implementations/SLCommandHandler.cpp \
implementations/VLCommandHandler.cpp \
implementations/RLCommandHandler.cpp \
- implementations/PHCommandHandler.cpp
+ implementations/PHCommandHandler.cpp \
+ implementations/RHCommandHandler.cpp \
+ implementations/AQCommandHandler.cpp
## server sockets, currently unused
##libcec_la_SOURCES += platform/posix/serversocket.cpp
#include "lib/LibCEC.h"
#include "lib/CECProcessor.h"
#include "lib/CECTypeUtils.h"
+#include "lib/platform/util/util.h"
#include <stdio.h>
using namespace CEC;
CCECAdapterMessage params;
CCECAdapterMessage *message = m_comm->SendCommand(msgCode, params);
- if (message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED)
+ if (message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED)
{
retVal = message->response;
retVal.Shift(2); // shift out start and msgcode
retVal.size -= 1; // remove end
}
- delete message;
+ DELETE_AND_NULL(message);
return retVal;
}
CCECAdapterMessage params;
params.PushEscaped(enabled ? 1 : 0);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_AUTO_ENABLED, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
CCECAdapterMessage params;
params.PushEscaped((uint8_t)type);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_DEVICE_TYPE, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
CCECAdapterMessage params;
params.PushEscaped((uint8_t)address);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
params.PushEscaped(iMask >> 8);
params.PushEscaped((uint8_t)iMask);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_LOGICAL_ADDRESS_MASK, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
params.PushEscaped(iPhysicalAddress >> 8);
params.PushEscaped((uint8_t)iPhysicalAddress);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_PHYSICAL_ADDRESS, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
CCECAdapterMessage params;
params.PushEscaped((uint8_t)version);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_HDMI_VERSION, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
for (size_t iPtr = 0; iPtr < strlen(strOSDName); iPtr++)
params.PushEscaped(strOSDName[iPtr]);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_OSD_NAME, params);
- bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
snprintf(m_persistedConfiguration.strDeviceName, 13, "%s", strOSDName);
CCECAdapterMessage params;
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_WRITE_EEPROM, params);
- bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
CCECAdapterMessage params;
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_PING, params);
- bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
return bReturn;
}
params.PushEscaped(iMask >> 8);
params.PushEscaped((uint8_t)iMask);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_ACK_MASK, params);
- bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
return bReturn;
}
CCECAdapterMessage params;
params.PushEscaped(bSetTo ? 1 : 0);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_ACTIVE_SOURCE, params);
- delete message;
+ DELETE_AND_NULL(message);
}
}
CCECAdapterMessage params;
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_START_BOOTLOADER, params);
- bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
return bReturn;
}
CCECAdapterMessage params;
params.PushEscaped(iTimeout);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_TRANSMIT_IDLETIME, params);
- bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
return bReturn;
}
CCECAdapterMessage params;
params.PushEscaped(controlled ? 1 : 0);
CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_CONTROLLED, params);
- bool bReturn = message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
- delete message;
+ bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ DELETE_AND_NULL(message);
if (bReturn)
{
m_lastPollDestination = msg.Destination();
if (msg.Destination() < CECDEVICE_BROADCAST)
{
+ CLockObject waitingLock(m_waitingMutex);
if (!m_bWaitingForAck[msg.Destination()] && !msg.IsEOM())
{
if (m_callback)
/* mark as waiting for an ack from the destination */
if (dest < CECDEVICE_BROADCAST)
{
- CLockObject lock(m_mutex);
+ CLockObject waitingLock(m_waitingMutex);
m_bWaitingForAck[dest] = true;
}
}
{
LIB_CEC->AddLog(CEC_LOG_DEBUG, "error writing command '%s' to serial port '%s': %s", CCECAdapterMessage::ToString(message->Message()), m_port->GetName().c_str(), m_port->GetError().c_str());
message->state = ADAPTER_MESSAGE_STATE_ERROR;
- // this will trigger an alert in the reader thread
- m_port->Close();
+ // let the higher level close the port
return false;
}
if (m_port->GetErrorNumber())
{
LIB_CEC->AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str());
- m_port->Close();
+ // let the higher level close the port
return false;
}
}
/* failed to ping the adapter 3 times in a row. something must be wrong with the connection */
m_com->LIB_CEC->AddLog(CEC_LOG_ERROR, "failed to ping the adapter 3 times in a row. closing the connection.");
m_com->StopThread(false);
+
+ libcec_parameter param;
+ param.paramData = NULL; param.paramType = CEC_PARAMETER_TYPE_UNKOWN;
+ m_com->LIB_CEC->Alert(CEC_ALERT_CONNECTION_LOST, param);
+
break;
}
}
CUSBCECAdapterCommands * m_commands; /**< commands that can be sent to the adapter */
CCECAdapterMessageQueue * m_adapterMessageQueue; /**< the incoming and outgoing message queue */
cec_logical_addresses m_logicalAddresses; /**< the logical address list that this instance is using */
+ PLATFORM::CMutex m_waitingMutex;
};
class CAdapterEepromWriteThread : public PLATFORM::CThread
#include <libudev.h>
}
#elif defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/sysctl.h>
#include <stdio.h>
#include <unistd.h>
#endif
}
#elif defined(__FreeBSD__)
char devicePath[PATH_MAX + 1];
+ char infos[512];
+ char sysctlname[32];
+ char ttyname[8];
+ char *pos;
+ size_t infos_size = sizeof(infos);
int i;
- for (i = 0; i < 8; ++i)
+ for (i = 0; ; ++i)
{
- (void)snprintf(devicePath, sizeof(devicePath), "/dev/ttyU%d", i);
- if (strDevicePath && strcmp(devicePath, strDevicePath) != 0)
+ unsigned int iVendor, iProduct;
+ memset(infos, 0, sizeof(infos));
+ (void)snprintf(sysctlname, sizeof(sysctlname),
+ "dev.umodem.%d.%%pnpinfo", i);
+ if (sysctlbyname(sysctlname, infos, &infos_size,
+ NULL, 0) != 0)
+ break;
+ pos = strstr(infos, "vendor=");
+ if (pos == NULL)
continue;
- if (!access(devicePath, 0))
- {
- snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", devicePath);
- snprintf(deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName), "%s", devicePath);
- deviceList[iFound].iVendorId = CEC_VID;
- deviceList[iFound].iProductId = CEC_VID;
- deviceList[iFound].adapterType = ADAPTERTYPE_P8_EXTERNAL; // will be overridden when not doing a "quick scan" by the actual type
- iFound++;
+ sscanf(pos, "vendor=%x ", &iVendor);
+
+ pos = strstr(infos, "product=");
+ if (pos == NULL)
+ continue;
+ sscanf(pos, "product=%x ", &iProduct);
+
+ if (iVendor != CEC_VID || (iProduct != CEC_PID && iProduct != CEC_PID2))
+ continue;
+
+ pos = strstr(infos, "ttyname=");
+ if (pos == NULL)
+ continue;
+ sscanf(pos, "ttyname=%s ", ttyname);
+
+ (void)snprintf(devicePath, sizeof(devicePath),
+ "/dev/tty%s", ttyname);
+
+ if (strDevicePath) {
+ char currStrDevicePath[512];
+ int port = 0;
+ int devaddr = 0;
+ memset(currStrDevicePath, 0, sizeof(currStrDevicePath));
+ memset(infos, 0, sizeof(infos));
+ (void)snprintf(sysctlname, sizeof(sysctlname),
+ "dev.umodem.%d.%%location", i);
+ if (sysctlbyname(sysctlname, infos, &infos_size,
+ NULL, 0) != 0)
+ break;
+
+ pos = strstr(infos, "port=");
+ if (pos == NULL)
+ continue;
+ sscanf(pos, "port=%d ", &port);
+
+ pos = strstr(infos, "devaddr=");
+ if (pos == NULL)
+ continue;
+ sscanf(pos, "devaddr=%d ", &devaddr);
+
+ (void)snprintf(currStrDevicePath, sizeof(currStrDevicePath),
+ "/dev/ugen%d.%d", port, devaddr);
+
+ if (strcmp(currStrDevicePath, strDevicePath) != 0)
+ continue;
}
+ snprintf(deviceList[iFound].strComPath, sizeof(deviceList[iFound].strComPath), "%s", devicePath);
+ snprintf(deviceList[iFound].strComName, sizeof(deviceList[iFound].strComName), "%s", devicePath);
+ deviceList[iFound].iVendorId = iVendor;
+ deviceList[iFound].iProductId = iProduct;
+ deviceList[iFound].adapterType = ADAPTERTYPE_P8_EXTERNAL; // will be overridden when not doing a "quick scan" by the actual type
+ iFound++;
}
#else
//silence "unused" warnings
#include "lib/implementations/VLCommandHandler.h"
#include "lib/implementations/PHCommandHandler.h"
#include "lib/implementations/RLCommandHandler.h"
+#include "lib/implementations/RHCommandHandler.h"
+#include "lib/implementations/AQCommandHandler.h"
#include "lib/LibCEC.h"
#include "lib/CECTypeUtils.h"
#include "lib/platform/util/timeutils.h"
#define LIB_CEC m_processor->GetLib()
#define ToString(p) CCECTypeUtils::ToString(p)
+CResponse::CResponse(cec_opcode opcode) :
+ m_opcode(opcode)
+{
+}
+
+CResponse::~CResponse(void)
+{
+ Broadcast();
+}
+
+bool CResponse::Wait(uint32_t iTimeout)
+{
+ return m_event.Wait(iTimeout);
+}
+
+void CResponse::Broadcast(void)
+{
+ m_event.Broadcast();
+}
+
+CWaitForResponse::CWaitForResponse(void)
+{
+}
+
+CWaitForResponse::~CWaitForResponse(void)
+{
+ Clear();
+}
+
+void CWaitForResponse::Clear()
+{
+ PLATFORM::CLockObject lock(m_mutex);
+ for (std::map<cec_opcode, CResponse*>::iterator it = m_waitingFor.begin(); it != m_waitingFor.end(); it++)
+ {
+ it->second->Broadcast();
+ delete it->second;
+ }
+ m_waitingFor.clear();
+}
+
+bool CWaitForResponse::Wait(cec_opcode opcode, uint32_t iTimeout)
+{
+ CResponse *response = GetEvent(opcode);
+ return response ? response->Wait(iTimeout) : false;
+}
+
+void CWaitForResponse::Received(cec_opcode opcode)
+{
+ CResponse *response = GetEvent(opcode);
+ if (response)
+ response->Broadcast();
+}
+
+CResponse* CWaitForResponse::GetEvent(cec_opcode opcode)
+{
+ CResponse *retVal(NULL);
+ {
+ PLATFORM::CLockObject lock(m_mutex);
+ std::map<cec_opcode, CResponse*>::iterator it = m_waitingFor.find(opcode);
+ if (it != m_waitingFor.end())
+ {
+ retVal = it->second;
+ }
+ else
+ {
+ retVal = new CResponse(opcode);
+ m_waitingFor[opcode] = retVal;
+ }
+ return retVal;
+ }
+}
+
CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress /* = CEC_INVALID_PHYSICAL_ADDRESS */) :
m_type (CEC_DEVICE_TYPE_RESERVED),
m_iPhysicalAddress (iPhysicalAddress),
case CEC_VENDOR_TOSHIBA2:
m_handler = new CRLCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
break;
+ case CEC_VENDOR_ONKYO:
+ m_handler = new CRHCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
+ break;
+ case CEC_VENDOR_SHARP:
+ m_handler = new CAQCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
+ break;
default:
m_handler = new CCECCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending);
break;
if (bRequestUpdate)
{
CheckVendorIdRequested(initiator);
- RequestPowerStatus(initiator);
+ RequestPowerStatus(initiator, bUpdate);
}
CLockObject lock(m_mutex);
return m_bImageViewOnSent;
}
-bool CCECBusDevice::RequestPowerStatus(const cec_logical_address initiator, bool bWaitForResponse /* = true */)
+bool CCECBusDevice::RequestPowerStatus(const cec_logical_address initiator, bool bUpdate, bool bWaitForResponse /* = true */)
{
bool bReturn(false);
!IsUnsupportedFeature(CEC_OPCODE_GIVE_DEVICE_POWER_STATUS))
{
MarkBusy();
- bReturn = m_handler->TransmitRequestPowerStatus(initiator, m_iLogicalAddress, bWaitForResponse);
+ bReturn = m_handler->TransmitRequestPowerStatus(initiator, m_iLogicalAddress, bUpdate, bWaitForResponse);
if (!bReturn)
SetPowerStatus(CEC_POWER_STATUS_UNKNOWN);
MarkReady();
if (m_deviceStatus != newStatus)
LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s (%X): device status changed into 'handled by libCEC'", GetLogicalAddressName(), m_iLogicalAddress);
SetPowerStatus (CEC_POWER_STATUS_ON);
- SetVendorId (CEC_VENDOR_UNKNOWN);
+ SetVendorId (CEC_VENDOR_PULSE_EIGHT);
SetMenuState (CEC_MENU_STATE_ACTIVATED);
SetCecVersion (libCECSpecVersion);
SetStreamPath (CEC_INVALID_PHYSICAL_ADDRESS);
if ((*it)->GetLogicalAddress() != m_iLogicalAddress)
(*it)->MarkAsInactiveSource();
- if (bWasActivated)
- {
- if (IsHandledByLibCEC())
- m_processor->SetActiveSource(true, false);
- CCECClient *client = GetClient();
- if (client)
- client->SourceActivated(m_iLogicalAddress);
- }
+ if (bWasActivated && IsHandledByLibCEC())
+ m_processor->SetActiveSource(true, false);
+
+ CCECClient *client = GetClient();
+ if (client)
+ client->SourceActivated(m_iLogicalAddress);
}
void CCECBusDevice::MarkAsInactiveSource(bool bClientUnregistered /* = false */)
return;
CCECBusDevice* newRoute = m_processor->GetDeviceByPhysicalAddress(iRoute, true);
- if (newRoute)
+ if (newRoute && newRoute->IsHandledByLibCEC())
{
// we were made the active source, send notification
- if (newRoute->IsHandledByLibCEC())
- newRoute->ActivateSource();
- // another device was made active
- else
- newRoute->MarkAsActiveSource();
+ newRoute->ActivateSource();
}
}
class CResponse
{
public:
- CResponse(cec_opcode opcode) :
- m_opcode(opcode){}
- ~CResponse(void)
- {
- Broadcast();
- }
-
- bool Wait(uint32_t iTimeout)
- {
- return m_event.Wait(iTimeout);
- }
-
- void Broadcast(void)
- {
- m_event.Broadcast();
- }
+ CResponse(cec_opcode opcode);
+ ~CResponse(void);
+
+ bool Wait(uint32_t iTimeout);
+ void Broadcast(void);
private:
cec_opcode m_opcode;
class CWaitForResponse
{
public:
- CWaitForResponse(void) {}
- ~CWaitForResponse(void)
- {
- Clear();
- }
-
- void Clear()
- {
- PLATFORM::CLockObject lock(m_mutex);
- for (std::map<cec_opcode, CResponse*>::iterator it = m_waitingFor.begin(); it != m_waitingFor.end(); it++)
- it->second->Broadcast();
- m_waitingFor.clear();
- }
-
- bool Wait(cec_opcode opcode, uint32_t iTimeout = CEC_DEFAULT_TRANSMIT_WAIT)
- {
- CResponse *response = GetEvent(opcode);
- return response ? response->Wait(iTimeout) : false;
- }
-
- void Received(cec_opcode opcode)
- {
- CResponse *response = GetEvent(opcode);
- if (response)
- response->Broadcast();
- }
+ CWaitForResponse(void);
+ ~CWaitForResponse(void);
+
+ void Clear();
+ bool Wait(cec_opcode opcode, uint32_t iTimeout = CEC_DEFAULT_TRANSMIT_WAIT);
+ void Received(cec_opcode opcode);
private:
- CResponse *GetEvent(cec_opcode opcode)
- {
- CResponse *retVal(NULL);
- {
- PLATFORM::CLockObject lock(m_mutex);
- std::map<cec_opcode, CResponse*>::iterator it = m_waitingFor.find(opcode);
- if (it != m_waitingFor.end())
- {
- retVal = it->second;
- }
- else
- {
- retVal = new CResponse(opcode);
- m_waitingFor[opcode] = retVal;
- }
- return retVal;
- }
- }
+ CResponse *GetEvent(cec_opcode opcode);
PLATFORM::CMutex m_mutex;
std::map<cec_opcode, CResponse*> m_waitingFor;
virtual void SetPowerStatus(const cec_power_status powerStatus);
virtual void OnImageViewOnSent(bool bSentByLibCEC);
virtual bool ImageViewOnSent(void);
- virtual bool RequestPowerStatus(const cec_logical_address initiator, bool bWaitForResponse = true);
+ virtual bool RequestPowerStatus(const cec_logical_address initiator, bool bUpdate, bool bWaitForResponse = true);
virtual bool TransmitPowerState(const cec_logical_address destination, bool bIsReply);
virtual cec_vendor_id GetCurrentVendorId(void);
return COMMAND_HANDLED;
}
-int CANCommandHandler::HandleVendorRemoteButtonUp(const cec_command &command)
-{
- return HandleUserControlRelease(command);
-}
-
bool CANCommandHandler::PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
if (iDestination == CECDEVICE_AUDIOSYSTEM)
return CCECCommandHandler::PowerOn(iInitiator, iDestination);
}
+
+int CANCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
+{
+ if (!m_processor->IsHandledByLibCEC(command.destination))
+ return CEC_ABORT_REASON_INVALID_OPERAND;
+
+ // samsung's vendor id
+ if (command.parameters[0] == 0x00 && command.parameters[1] == 0x00 && command.parameters[2] == 0xf0)
+ {
+ // unknown vendor command sent to devices
+ if (command.parameters[3] == 0x23)
+ {
+ cec_command response;
+ cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND_WITH_ID);
+
+ // samsung vendor id
+ response.parameters.PushBack(0x00); response.parameters.PushBack(0x00); response.parameters.PushBack(0xf0);
+
+ // XXX see bugzid 2164. reply sent back by audio systems, we might have to send something different
+ response.parameters.PushBack(0x24);
+ response.parameters.PushBack(0x00);
+ response.parameters.PushBack(0x80);
+
+ Transmit(response, false, true);
+ return COMMAND_HANDLED;
+ }
+ }
+ return CEC_ABORT_REASON_INVALID_OPERAND;
+}
virtual ~CANCommandHandler(void) {};
int HandleVendorRemoteButtonDown(const cec_command &command);
- int HandleVendorRemoteButtonUp(const cec_command &command);
+ int HandleDeviceVendorCommandWithId(const cec_command &command);
protected:
bool PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+#include "AQCommandHandler.h"
+
+#include "lib/devices/CECBusDevice.h"
+#include "lib/CECProcessor.h"
+#include "lib/LibCEC.h"
+#include "lib/CECClient.h"
+
+using namespace CEC;
+using namespace PLATFORM;
+
+#define LIB_CEC m_busDevice->GetProcessor()->GetLib()
+#define ToString(p) LIB_CEC->ToString(p)
+
+CAQCommandHandler::CAQCommandHandler(CCECBusDevice *busDevice,
+ int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */,
+ int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */,
+ int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */,
+ int64_t iActiveSourcePending /* = 0 */) :
+ CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending),
+ m_powerOnCheck(NULL)
+{
+ m_vendorId = CEC_VENDOR_SHARP;
+}
+
+CAQCommandHandler::~CAQCommandHandler(void)
+{
+ delete m_powerOnCheck;
+}
+
+bool CAQCommandHandler::PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
+{
+ bool bCheck(false);
+ bool bRetval(false);
+ if (m_busDevice->GetCurrentPowerStatus() != CEC_POWER_STATUS_ON && (!m_powerOnCheck || !m_powerOnCheck->IsRunning()))
+ bCheck = true;
+ bRetval = CCECCommandHandler::PowerOn(iInitiator, iDestination);
+
+ if (bRetval && bCheck)
+ {
+ if (!m_powerOnCheck)
+ m_powerOnCheck = new CAQPowerStatusCheck(this, iInitiator, iDestination);
+ if (m_powerOnCheck)
+ m_powerOnCheck->CreateThread();
+ }
+
+ return bRetval;
+}
+
+void* CAQPowerStatusCheck::Process(void)
+{
+ // sleep for 2 seconds and query the power status
+ Sleep(2000);
+ if (m_handler->m_busDevice->GetProcessor()->GetDevice(m_iDestination)->GetPowerStatus(m_iInitiator, true) == CEC_POWER_STATUS_STANDBY)
+ m_handler->m_busDevice->GetProcessor()->GetLib()->AddLog(CEC_LOG_WARNING, "AQUOS LINK 'auto power on' is disabled, which prevents the TV from being powered on. To correct this, press the menu button on your remote, go to 'link operation' -> 'AQUOS LINK setup' -> 'Auto power on' and set it to 'On'");
+ return NULL;
+}
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "CECCommandHandler.h"
+#include "lib/platform/threads/threads.h"
+
+namespace CEC
+{
+ class CAQPowerStatusCheck;
+
+ class CAQCommandHandler : public CCECCommandHandler
+ {
+ friend class CAQPowerStatusCheck;
+ public:
+ CAQCommandHandler(CCECBusDevice *busDevice,
+ int32_t iTransmitTimeout = CEC_DEFAULT_TRANSMIT_TIMEOUT,
+ int32_t iTransmitWait = CEC_DEFAULT_TRANSMIT_WAIT,
+ int8_t iTransmitRetries = CEC_DEFAULT_TRANSMIT_RETRIES,
+ int64_t iActiveSourcePending = 0);
+ virtual ~CAQCommandHandler(void);
+
+ protected:
+ virtual bool PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
+
+ private:
+ CAQPowerStatusCheck* m_powerOnCheck;
+ };
+
+ class CAQPowerStatusCheck : public PLATFORM::CThread
+ {
+ public:
+ CAQPowerStatusCheck(CAQCommandHandler* handler, cec_logical_address iInitiator, cec_logical_address iDestination) :
+ m_handler(handler),
+ m_iInitiator(iInitiator),
+ m_iDestination(iDestination) {}
+ virtual ~CAQPowerStatusCheck(void) {}
+
+ private:
+ void* Process(void);
+ CAQCommandHandler* m_handler;
+ cec_logical_address m_iInitiator;
+ cec_logical_address m_iDestination;
+ };
+};
int CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
{
SetVendorId(command);
+
+ if (command.initiator == CECDEVICE_TV)
+ {
+ CCECBusDevice* primary = m_processor->GetPrimaryDevice();
+ if (primary)
+ primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false);
+ }
+
return COMMAND_HANDLED;
}
{
uint16_t iNewAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
SetPhysicalAddress(command.initiator, iNewAddress);
+
+ if (command.initiator == CECDEVICE_TV)
+ {
+ CCECBusDevice* primary = m_processor->GetPrimaryDevice();
+ if (primary)
+ primary->TransmitPhysicalAddress(false);
+ }
return COMMAND_HANDLED;
}
return CEC_ABORT_REASON_INVALID_OPERAND;
if (device->IsHandledByLibCEC() && !device->IsActiveSource())
device->ActivateSource();
else
+ {
device->MarkAsActiveSource();
+ device->TransmitActiveSource(true);
+ }
return COMMAND_HANDLED;
}
}
return Transmit(command, !bWaitForResponse, false);
}
-bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse /* = true */)
+bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bUpdate, bool bWaitForResponse /* = true */)
{
if (iDestination == CECDEVICE_TV)
{
int64_t now(GetTimeMs());
- if (now - m_iPowerStatusRequested < REQUEST_POWER_STATUS_TIMEOUT)
+ if (!bUpdate && now - m_iPowerStatusRequested < REQUEST_POWER_STATUS_TIMEOUT)
return true;
m_iPowerStatusRequested = now;
}
bool bTvPresent = (tv && tv->GetStatus() == CEC_DEVICE_STATUS_PRESENT);
bool bActiveSourceFailed(false);
if (bTvPresent)
- bActiveSourceFailed = !m_busDevice->TransmitImageViewOn();
+ bActiveSourceFailed = !tv->PowerOn(m_busDevice->GetLogicalAddress());
else
LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV not present, not sending 'image view on'");
if (playbackDevice && SendDeckStatusUpdateOnActiveSource())
bActiveSourceFailed = !playbackDevice->TransmitDeckStatus(CECDEVICE_TV, false);
}
+
+ // update system audio mode for audiosystem devices
+ if (bTvPresent && !bActiveSourceFailed)
+ {
+ CCECAudioSystem* audioDevice = m_busDevice->AsAudioSystem();
+ if (audioDevice)
+ bActiveSourceFailed = !audioDevice->TransmitSetSystemAudioMode(CECDEVICE_TV, false);
+ }
}
// retry later
virtual bool HandleCommand(const cec_command &command);
virtual cec_vendor_id GetVendorId(void) { return m_vendorId; };
virtual void SetVendorId(cec_vendor_id vendorId) { m_vendorId = vendorId; }
- static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS;}
+ static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS || vendorId == CEC_VENDOR_SHARP;}
virtual bool InitHandler(void) { return true; }
virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false);
virtual bool TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true);
virtual bool TransmitRequestAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true);
virtual bool TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true);
- virtual bool TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true);
+ virtual bool TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bUpdate, bool bWaitForResponse = true);
virtual bool TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination, bool bWaitForResponse = true);
virtual bool TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply);
virtual bool TransmitCECVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_version cecVersion, bool bIsReply);
virtual int HandleUserControlRelease(const cec_command &command);
virtual int HandleVendorCommand(const cec_command &command);
virtual int HandleVendorRemoteButtonDown(const cec_command& command);
- virtual int HandleVendorRemoteButtonUp(const cec_command & UNUSED(command)) { return COMMAND_HANDLED; }
+ virtual int HandleVendorRemoteButtonUp(const cec_command& command) { return HandleUserControlRelease(command); }
virtual void UnhandledCommand(const cec_command &command, const cec_abort_reason reason);
virtual void RequestEmailFromCustomer(const cec_command& command);
return CCECCommandHandler::HandleDeviceVendorId(command);
}
-bool CPHCommandHandler::TransmitVendorID(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint64_t UNUSED(iVendorId), bool UNUSED(bIsReply))
+bool CPHCommandHandler::TransmitVendorID(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint64_t UNUSED(iVendorId), bool bIsReply)
{
- LIB_CEC->AddLog(CEC_LOG_DEBUG, "<< %s (%X) -> %s (%X): vendor id feature abort", ToString(iInitiator), iInitiator, ToString(iDestination), iDestination);
- m_processor->TransmitAbort(iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
- return true;
+ // XXX hack around the hack in CPHCommandHandler::InitHandler
+ return CCECCommandHandler::TransmitVendorID(iInitiator, iDestination, CEC_VENDOR_PULSE_EIGHT, bIsReply);
}
virtual int HandleUserControlRelease(const cec_command& command);
virtual bool TransmitVendorID(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint64_t iVendorId, bool bIsReply);
virtual int HandleDeviceVendorId(const cec_command& command);
- virtual int HandleVendorRemoteButtonUp(const cec_command & command) { return HandleUserControlRelease(command); }
uint8_t m_iLastKeyCode;
CImageViewOnCheck* m_imageViewOnCheck;
};
--- /dev/null
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "env.h"
+#include "RHCommandHandler.h"
+
+#include "lib/devices/CECBusDevice.h"
+#include "lib/CECProcessor.h"
+#include "lib/LibCEC.h"
+#include "lib/CECClient.h"
+
+using namespace CEC;
+
+#define LIB_CEC m_busDevice->GetProcessor()->GetLib()
+#define ToString(p) LIB_CEC->ToString(p)
+
+CRHCommandHandler::CRHCommandHandler(CCECBusDevice *busDevice,
+ int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */,
+ int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */,
+ int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */,
+ int64_t iActiveSourcePending /* = 0 */) :
+ CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending)
+{
+ m_vendorId = CEC_VENDOR_ONKYO;
+}
+
+int CRHCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
+{
+ // onkyo's vendor id
+ if (command.parameters[0] == 0x00 && command.parameters[1] == 0x09 && command.parameters[2] == 0xb0)
+ {
+ // ignore unknown vendor commands sent by onkyo devices, bugzid: 2559
+ }
+ return CEC_ABORT_REASON_INVALID_OPERAND;
+
+}
--- /dev/null
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing <license@pulse-eight.com>
+ * http://www.pulse-eight.com/
+ * http://www.pulse-eight.net/
+ */
+
+#include "CECCommandHandler.h"
+
+namespace CEC
+{
+ class CRHCommandHandler : public CCECCommandHandler
+ {
+ public:
+ CRHCommandHandler(CCECBusDevice *busDevice,
+ int32_t iTransmitTimeout = CEC_DEFAULT_TRANSMIT_TIMEOUT,
+ int32_t iTransmitWait = CEC_DEFAULT_TRANSMIT_WAIT,
+ int8_t iTransmitRetries = CEC_DEFAULT_TRANSMIT_RETRIES,
+ int64_t iActiveSourcePending = 0);
+ virtual ~CRHCommandHandler(void) {};
+
+ protected:
+ int HandleDeviceVendorCommandWithId(const cec_command &command);
+ };
+};
using namespace CEC;
using namespace PLATFORM;
-#define SL_COMMAND_UNKNOWN_01 0x01
-#define SL_COMMAND_UNKNOWN_02 0x02
-
#define SL_COMMAND_TYPE_HDDRECORDER_DISC 0x01
#define SL_COMMAND_TYPE_VCR 0x02
#define SL_COMMAND_TYPE_DVDPLAYER 0x03
#define SL_COMMAND_TYPE_HDDRECORDER_DISC2 0x04
#define SL_COMMAND_TYPE_HDDRECORDER 0x05
-#define SL_COMMAND_REQUEST_POWER_STATUS 0xa0
+#define SL_COMMAND_INIT 0x01
+#define SL_COMMAND_ACK_INIT 0x02
#define SL_COMMAND_POWER_ON 0x03
#define SL_COMMAND_CONNECT_REQUEST 0x04
#define SL_COMMAND_SET_DEVICE_MODE 0x05
+#define SL_COMMAND_REQUEST_POWER_STATUS 0xa0
#define LIB_CEC m_busDevice->GetProcessor()->GetLib()
#define ToString(p) LIB_CEC->ToString(p)
int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */,
int64_t iActiveSourcePending /* = 0 */) :
CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending),
- m_bSLEnabled(false),
- m_bActiveSourceSent(false)
+ m_bSLEnabled(false)
{
m_vendorId = CEC_VENDOR_LG;
primary->SetVendorId(CEC_VENDOR_LG);
primary->ReplaceHandler(false);
}
-
- if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
- {
- /* start as 'in transition standby->on' */
- primary->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
- primary->TransmitPowerState(CECDEVICE_TV, false);
-
- /* send the vendor id */
- primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false);
- }
}
return true;
}
-int CSLCommandHandler::HandleActiveSource(const cec_command &command)
-{
- if (command.parameters.size == 2)
- {
- uint16_t iAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
- CCECBusDevice *device = m_processor->GetDeviceByPhysicalAddress(iAddress);
- if (device)
- device->MarkAsActiveSource();
-
- {
- CLockObject lock(m_SLMutex);
- m_bActiveSourceSent = false;
- }
-
- return COMMAND_HANDLED;
- }
-
- return CEC_ABORT_REASON_INVALID_OPERAND;
-
-}
-
-int CSLCommandHandler::HandleDeviceVendorId(const cec_command &command)
-{
- SetVendorId(command);
-
- if (!SLInitialised() && command.initiator == CECDEVICE_TV)
- {
- CCECBusDevice *destination = m_processor->GetDevice(command.destination);
- if (destination && (destination->GetLogicalAddress() == CECDEVICE_BROADCAST || destination->IsHandledByLibCEC()))
- {
- cec_logical_address initiator = destination->GetLogicalAddress();
- if (initiator == CECDEVICE_BROADCAST)
- initiator = m_processor->GetPrimaryDevice()->GetLogicalAddress();
-
- cec_command response;
- cec_command::Format(response, initiator, command.initiator, CEC_OPCODE_FEATURE_ABORT);
- Transmit(response, false, true);
- return COMMAND_HANDLED;
- }
- }
-
- return CCECCommandHandler::HandleDeviceVendorId(command);
-}
-
int CSLCommandHandler::HandleVendorCommand(const cec_command &command)
{
if (!m_processor->IsHandledByLibCEC(command.destination))
return true;
if (command.parameters.size == 1 &&
- command.parameters[0] == SL_COMMAND_UNKNOWN_01)
+ command.parameters[0] == SL_COMMAND_INIT)
{
- HandleVendorCommand01(command);
+ HandleVendorCommandSLInit(command);
return COMMAND_HANDLED;
}
else if (command.parameters.size == 2 &&
return CCECCommandHandler::HandleVendorCommand(command);
}
-void CSLCommandHandler::HandleVendorCommand01(const cec_command &command)
+void CSLCommandHandler::HandleVendorCommandSLInit(const cec_command &command)
{
- m_processor->GetPrimaryDevice()->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
- TransmitVendorCommand0205(command.destination, command.initiator);
-
CCECBusDevice* dev = m_processor->GetDevice(command.destination);
- if (dev && dev->IsHandledByLibCEC() && dev->IsActiveSource())
- dev->TransmitActiveSource(false);
+ if (dev && dev->IsHandledByLibCEC())
+ {
+ if (!dev->IsActiveSource())
+ {
+ dev->SetPowerStatus(CEC_POWER_STATUS_STANDBY);
+ dev->TransmitPowerState(command.initiator, true);
+ }
+
+ TransmitVendorCommandSLAckInit(command.destination, command.initiator);
+ }
}
-void CSLCommandHandler::TransmitVendorCommand0205(const cec_logical_address iSource, const cec_logical_address iDestination)
+void CSLCommandHandler::TransmitVendorCommandSLAckInit(const cec_logical_address iSource, const cec_logical_address iDestination)
{
cec_command response;
cec_command::Format(response, iSource, iDestination, CEC_OPCODE_VENDOR_COMMAND);
- response.PushBack(SL_COMMAND_UNKNOWN_02);
+ response.PushBack(SL_COMMAND_ACK_INIT);
response.PushBack(SL_COMMAND_TYPE_HDDRECORDER);
Transmit(response, false, true);
device->SetPowerStatus(CEC_POWER_STATUS_ON);
device->TransmitPowerState(command.initiator, false);
device->TransmitPhysicalAddress(false);
- {
- CLockObject lock(m_SLMutex);
- m_bActiveSourceSent = false;
- }
+
+ if (device->IsActiveSource())
+ ActivateSource();
}
}
void CSLCommandHandler::HandleVendorCommandPowerOnStatus(const cec_command &command)
SetSLInitialised();
TransmitVendorCommandSetDeviceMode(command.destination, command.initiator, CEC_DEVICE_TYPE_RECORDING_DEVICE);
- ActivateSource();
+
+ if (m_processor->IsActiveSource(command.destination) && m_processor->IsHandledByLibCEC(command.destination))
+ {
+ CCECBusDevice* dev = m_processor->GetDevice(command.destination);
+ CCECPlaybackDevice* pb = dev->AsPlaybackDevice();
+ if (pb)
+ pb->TransmitDeckStatus(command.initiator, true);
+ dev->TransmitPowerState(command.initiator, true);
+ }
}
void CSLCommandHandler::TransmitVendorCommandSetDeviceMode(const cec_logical_address iSource, const cec_logical_address iDestination, const cec_device_type type)
if (command.parameters[0] == CEC_STATUS_REQUEST_ON)
{
device->TransmitDeckStatus(command.initiator, true);
- if (!ActiveSourceSent())
- ActivateSource();
+ ActivateSource();
return COMMAND_HANDLED;
}
else if (command.parameters[0] == CEC_STATUS_REQUEST_ONCE)
}
else
{
- if (!ActiveSourceSent())
- {
- device->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
- device->TransmitPowerState(command.initiator, true);
- ActivateSource();
- }
- else if (m_resetPowerState.IsSet() && m_resetPowerState.TimeLeft() > 0)
+ if (m_resetPowerState.IsSet() && m_resetPowerState.TimeLeft() > 0)
{
/* TODO assume that we've bugged out. the return button no longer works after this */
LIB_CEC->AddLog(CEC_LOG_WARNING, "FIXME: LG seems to have bugged out. resetting to 'in transition standby to on'. the return button will not work");
- {
- CLockObject lock(m_SLMutex);
- m_bActiveSourceSent = false;
- }
device->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
device->TransmitPowerState(command.initiator, true);
device->SetPowerStatus(CEC_POWER_STATUS_ON);
{
if (m_processor->CECInitialised())
{
- if (ActiveSourceSent())
- LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %i requests active source, ignored", (uint8_t) command.initiator);
- else
- ActivateSource();
- return COMMAND_HANDLED;
+ if (!SLInitialised())
+ TransmitVendorCommandSLAckInit(m_processor->GetPrimaryDevice()->GetLogicalAddress(), command.initiator);
+ CCECCommandHandler::HandleRequestActiveSource(command);
}
return CEC_ABORT_REASON_NOT_IN_CORRECT_MODE_TO_RESPOND;
}
int CSLCommandHandler::HandleFeatureAbort(const cec_command &command)
{
- if (command.parameters.size == 0 && m_processor->GetPrimaryDevice()->GetCurrentPowerStatus() == CEC_POWER_STATUS_ON && !SLInitialised() &&
+ CCECBusDevice* primary = m_processor->GetPrimaryDevice();
+ if (command.parameters.size == 0 && primary->GetLogicalAddress() != CECDEVICE_UNKNOWN &&
+ primary->GetCurrentPowerStatus() == CEC_POWER_STATUS_ON && !SLInitialised() &&
command.initiator == CECDEVICE_TV)
{
- m_processor->GetPrimaryDevice()->TransmitPowerState(command.initiator, false);
- m_processor->GetPrimaryDevice()->TransmitVendorID(CECDEVICE_BROADCAST, false, false);
+ if (!SLInitialised() && m_processor->IsActiveSource(command.destination))
+ {
+ TransmitVendorCommandSLAckInit(command.destination, command.initiator);
+ return COMMAND_HANDLED;
+ }
}
return CCECCommandHandler::HandleFeatureAbort(command);
int CSLCommandHandler::HandleStandby(const cec_command &command)
{
- if (command.initiator == CECDEVICE_TV)
- {
- CLockObject lock(m_SLMutex);
- m_bActiveSourceSent = false;
- }
+ ResetSLState();
return CCECCommandHandler::HandleStandby(command);
}
LIB_CEC->AddLog(CEC_LOG_NOTICE, "resetting SL initialised state");
CLockObject lock(m_SLMutex);
m_bSLEnabled = false;
- m_bActiveSourceSent = false;
m_processor->GetPrimaryDevice()->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
}
return m_bSLEnabled;
}
-bool CSLCommandHandler::ActiveSourceSent(void)
-{
- CLockObject lock(m_SLMutex);
- return m_bActiveSourceSent;
-}
-
bool CSLCommandHandler::PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
{
if (iDestination != CECDEVICE_TV)
return CCECCommandHandler::PowerOn(iInitiator, iDestination);
}
-void CSLCommandHandler::VendorPreActivateSourceHook(void)
+bool CSLCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = false */)
{
- CCECPlaybackDevice *device = m_busDevice->AsPlaybackDevice();
- if (device)
- device->SetDeckStatus(!device->IsActiveSource() ? CEC_DECK_INFO_OTHER_STATUS : CEC_DECK_INFO_OTHER_STATUS_LG);
+ if (m_busDevice->IsActiveSource() &&
+ m_busDevice->IsHandledByLibCEC())
+ {
+ {
+ CLockObject lock(m_mutex);
+ // check if we need to send a delayed source switch
+ if (bTransmitDelayedCommandsOnly)
+ {
+ if (m_iActiveSourcePending == 0 || GetTimeMs() < m_iActiveSourcePending)
+ return false;
+
+#ifdef CEC_DEBUGGING
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "transmitting delayed activate source command");
+#endif
+ }
+ }
+
+ CCECPlaybackDevice *device = m_busDevice->AsPlaybackDevice();
+ if (device)
+ device->SetDeckStatus(!device->IsActiveSource() ? CEC_DECK_INFO_OTHER_STATUS : CEC_DECK_INFO_OTHER_STATUS_LG);
+
+ // power on the TV
+ CCECBusDevice* tv = m_processor->GetDevice(CECDEVICE_TV);
+ bool bTvPresent = (tv && tv->GetStatus() == CEC_DEVICE_STATUS_PRESENT);
+ bool bActiveSourceFailed(false);
+ if (bTvPresent)
+ {
+ bActiveSourceFailed = !device->TransmitImageViewOn();
+ }
+ else
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "TV not present, not sending 'image view on'");
+ }
+
+ // check if we're allowed to switch sources
+ bool bSourceSwitchAllowed = SourceSwitchAllowed();
+ if (!bSourceSwitchAllowed)
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "source switch is currently not allowed by command handler");
+
+ // switch sources (if allowed)
+ if (!bActiveSourceFailed && bSourceSwitchAllowed)
+ {
+ bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false);
+ }
+
+ // retry later
+ if (bActiveSourceFailed || !bSourceSwitchAllowed)
+ {
+ LIB_CEC->AddLog(CEC_LOG_DEBUG, "failed to make '%s' the active source. will retry later", m_busDevice->GetLogicalAddressName());
+ int64_t now(GetTimeMs());
+ CLockObject lock(m_mutex);
+ if (m_iActiveSourcePending == 0 || m_iActiveSourcePending < now)
+ m_iActiveSourcePending = now + (int64_t)CEC_ACTIVE_SOURCE_SWITCH_RETRY_TIME_MS;
+ return false;
+ }
+ else
+ {
+ CLockObject lock(m_mutex);
+ // clear previous pending active source command
+ m_iActiveSourcePending = 0;
+ }
+
+ // mark the handler as initialised
+ CLockObject lock(m_mutex);
+ m_bHandlerInited = true;
+ }
+ return true;
}
virtual ~CSLCommandHandler(void) {};
bool InitHandler(void);
+ bool ActivateSource(bool bTransmitDelayedCommandsOnly = false);
protected:
- int HandleActiveSource(const cec_command &command);
- int HandleDeviceVendorId(const cec_command &command);
int HandleVendorCommand(const cec_command &command);
- void HandleVendorCommand01(const cec_command &command);
- void TransmitVendorCommand0205(const cec_logical_address iSource, const cec_logical_address iDestination);
+ void HandleVendorCommandSLInit(const cec_command &command);
+ void TransmitVendorCommandSLAckInit(const cec_logical_address iSource, const cec_logical_address iDestination);
void HandleVendorCommandPowerOn(const cec_command &command);
void HandleVendorCommandPowerOnStatus(const cec_command &command);
int HandleStandby(const cec_command &command);
bool TransmitMenuState(const cec_logical_address UNUSED(iInitiator), const cec_logical_address UNUSED(iDestination), cec_menu_state UNUSED(menuState), bool UNUSED(bIsReply)) { return true; }
bool PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination);
- int HandleVendorRemoteButtonUp(const cec_command& command) { return HandleUserControlRelease(command); }
void ResetSLState(void);
bool SLInitialised(void);
void SetSLInitialised(void);
- bool ActiveSourceSent(void);
-
- void VendorPreActivateSourceHook(void);
bool m_bSLEnabled;
- bool m_bActiveSourceSent;
PLATFORM::CTimeout m_resetPowerState;
PLATFORM::CMutex m_SLMutex;
};
command.parameters[2] != 0x45)
return CEC_ABORT_REASON_INVALID_OPERAND;
- // XXX this is also sent when the TV is powered off
-#if 0
if (command.initiator == CECDEVICE_TV &&
command.parameters.At(3) == VL_UNKNOWN1)
{
- // set the power up event time
+ if (command.parameters.size >= 5 && command.parameters.At(4) == 0x05)
{
- CLockObject lock(m_mutex);
- if (m_iPowerUpEventReceived == 0)
- m_iPowerUpEventReceived = GetTimeMs();
+ // set the power up event time
+ {
+ CLockObject lock(m_mutex);
+ if (m_iPowerUpEventReceived == 0)
+ m_iPowerUpEventReceived = GetTimeMs();
+ }
+ // mark the TV as powered on
+ m_processor->GetTV()->SetPowerStatus(CEC_POWER_STATUS_ON);
+
+ CCECBusDevice* dev = m_processor->GetPrimaryDevice();
+ if (dev && dev->IsActiveSource())
+ dev->TransmitActiveSource(false);
+
+ return COMMAND_HANDLED;
}
- // mark the TV as powered on
- m_processor->GetTV()->SetPowerStatus(CEC_POWER_STATUS_ON);
}
- else
-#endif
- if (command.initiator == CECDEVICE_TV &&
+ else if (command.initiator == CECDEVICE_TV &&
command.destination == CECDEVICE_BROADCAST &&
command.parameters.At(3) == VL_POWER_CHANGE)
{
if (command.parameters.size == 3 &&
command.parameters[0] == 0x10 &&
command.parameters[1] == 0x01 &&
- command.parameters[2] == 0x05 &&
m_processor->IsHandledByLibCEC(command.destination))
{
+ // XXX i've seen 0x05 and 0x03 as third param. these probably indicate different types of TVs/capabilities
+ // when we feature abort this, then the TV will try the same thing with a vendor command with id
SendVendorCommandCapabilities(m_processor->GetLogicalAddress(), command.initiator);
+
+ CCECBusDevice* dev = m_processor->GetDevice(command.destination);
+ if (dev && dev->IsActiveSource())
+ dev->ActivateSource(500);
return COMMAND_HANDLED;
}
bool CVLCommandHandler::SourceSwitchAllowed(void)
{
if (!PowerUpEventReceived())
- TransmitRequestPowerStatus(m_processor->GetPrimaryDevice()->GetLogicalAddress(), CECDEVICE_TV, false);
+ TransmitRequestPowerStatus(m_processor->GetPrimaryDevice()->GetLogicalAddress(), CECDEVICE_TV, false, false);
return PowerUpEventReceived();
}
#include "../lib/platform/os.h"
#include "../lib/implementations/CECCommandHandler.h"
#include "../lib/platform/util/StdString.h"
+#include "../lib/platform/threads/threads.h"
using namespace CEC;
using namespace std;
#include "../../include/cecloader.h"
+static void PrintToStdOut(const char *strFormat, ...);
+
ICECCallbacks g_callbacks;
libcec_configuration g_config;
int g_cecLogLevel(-1);
bool g_bExit(false);
bool g_bHardExit(false);
CMutex g_outputMutex;
+ICECAdapter* g_parser;
+
+class CReconnect : public PLATFORM::CThread
+{
+public:
+ static CReconnect& Get(void)
+ {
+ static CReconnect _instance;
+ return _instance;
+ }
+
+ virtual ~CReconnect(void) {}
+
+ void* Process(void)
+ {
+ if (g_parser)
+ {
+ g_parser->Close();
+ if (!g_parser->Open(g_strPort.c_str()))
+ {
+ PrintToStdOut("Failed to reconnect\n");
+ g_bExit = true;
+ }
+ }
+ return NULL;
+ }
+
+private:
+ CReconnect(void) {}
+};
-inline void PrintToStdOut(const char *strFormat, ...)
+static void PrintToStdOut(const char *strFormat, ...)
{
CStdString strLog;
switch (type)
{
case CEC_ALERT_CONNECTION_LOST:
- PrintToStdOut("Connection lost - exiting\n");
- g_bExit = true;
+ if (!CReconnect::Get().IsRunning())
+ {
+ PrintToStdOut("Connection lost - trying to reconnect\n");
+ CReconnect::Get().CreateThread(false);
+ }
break;
default:
break;
g_config.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
}
- ICECAdapter *parser = LibCecInitialise(&g_config);
- if (!parser)
+ g_parser = LibCecInitialise(&g_config);
+ if (!g_parser)
{
#ifdef __WINDOWS__
cout << "Cannot load libcec.dll" << endl;
cout << "Cannot load libcec.so" << endl;
#endif
- if (parser)
- UnloadLibCec(parser);
+ if (g_parser)
+ UnloadLibCec(g_parser);
return 1;
}
// init video on targets that need this
- parser->InitVideoStandalone();
+ g_parser->InitVideoStandalone();
if (!g_bSingleCommand)
{
CStdString strLog;
- strLog.Format("CEC Parser created - libCEC version %s", parser->ToString((cec_server_version)g_config.serverVersion));
+ strLog.Format("CEC Parser created - libCEC version %s", g_parser->ToString((cec_server_version)g_config.serverVersion));
cout << strLog.c_str() << endl;
//make stdin non-blocking
if (!g_bSingleCommand)
cout << "no serial port given. trying autodetect: ";
cec_adapter devices[10];
- uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
+ uint8_t iDevicesFound = g_parser->FindAdapters(devices, 10, NULL);
if (iDevicesFound <= 0)
{
if (g_bSingleCommand)
cout << "autodetect ";
cout << "FAILED" << endl;
- UnloadLibCec(parser);
+ UnloadLibCec(g_parser);
return 1;
}
else
PrintToStdOut("opening a connection to the CEC adapter...");
- if (!parser->Open(g_strPort.c_str()))
+ if (!g_parser->Open(g_strPort.c_str()))
{
PrintToStdOut("unable to open the device on port %s", g_strPort.c_str());
- UnloadLibCec(parser);
+ UnloadLibCec(g_parser);
return 1;
}
getline(cin, input);
cin.clear();
- if (ProcessConsoleCommand(parser, input) && !g_bSingleCommand && !g_bExit && !g_bHardExit)
+ if (ProcessConsoleCommand(g_parser, input) && !g_bSingleCommand && !g_bExit && !g_bHardExit)
{
if (!input.empty())
PrintToStdOut("waiting for input");
CEvent::Sleep(50);
}
- parser->Close();
- UnloadLibCec(parser);
+ g_parser->Close();
+ UnloadLibCec(g_parser);
if (g_logOutput.is_open())
g_logOutput.close();