diff --git a/.gitignore b/.gitignore index 8c3b8d7a..1307d72f 100644 --- a/.gitignore +++ b/.gitignore @@ -86,9 +86,7 @@ project/RPi/firmware project/RPi/deps src/libcec/libcec.pc - -src/CecSharpTester/bin -src/CecSharpTester/obj +src/libcec/libcec.rc src/cec-config-gui/obj src/cec-config/cec-config @@ -106,3 +104,4 @@ src/libcec-wmc/obj /src/EventGhost/egplugin_sources/PulseEight/cec /src/EventGhost/pulse_eight.egplugin +/src/dotnetlib/LibCecSharp/LibCecSharp.rc diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c5314b4..9256ab4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ project(libcec) cmake_minimum_required(VERSION 3.12.0) -set(LIBCEC_VERSION_MAJOR 5) +set(LIBCEC_VERSION_MAJOR 6) set(LIBCEC_VERSION_MINOR 0) set(LIBCEC_VERSION_PATCH 0) @@ -27,8 +27,8 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in if(WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/project/nsis/libcec-version.nsh.in ${CMAKE_CURRENT_SOURCE_DIR}/project/nsis/libcec-version.nsh) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharp/project/LibCecSharp.rc.in - ${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharp/project/LibCecSharp.rc) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharp/LibCecSharp.rc.in + ${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharp/LibCecSharp.rc) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharp/AssemblyInfo.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharp/AssemblyInfo.cpp) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/dotnetlib/LibCecSharpCore/AssemblyInfo.cpp.in diff --git a/debian/changelog.in b/debian/changelog.in index 8749666c..f425a577 100644 --- a/debian/changelog.in +++ b/debian/changelog.in @@ -1,3 +1,31 @@ +libcec (6.0.0.1~#DIST#) #DIST#; urgency=medium + + * fixed: + * eventghost installation + * loading and storing settings in eeprom + * LibCecSharp callbacks could crash + * updating the hdmi port setting or physical address while libCEC is + running + * various small robustness improvements and cosmetic changes + * icons are no longer black transperant (and nearly invisible) + * added: + * v2.0 CEC version + * new/missing functions and fields in LibCecSharp + * firmware can now be upgraded in cec-tray + * screensaver functionality in cec-tray + * MuteAudio() command + * removed: + * CanPersistConfiguration() - use CanSaveConfiguration() instead + * PersistConfiguration() - SetConfiguration() now stores the cfg in eeprom + if available + * EnableCallbacks() - use SetCallbacks() and DisableCallbacks()instead + * changed: + * unified LibCecSharp and LibCecSharpCore + * try to init submodules when not found while creating an installer. abort + if platform failed to compile + + -- Pulse-Eight Packaging Mon, 9 Jul 2020 23:37:00 +0100 + libcec (5.0.0.1~#DIST#) #DIST#; urgency=medium * fixed: diff --git a/include/cec.h b/include/cec.h index 607d05a0..a7c66a88 100644 --- a/include/cec.h +++ b/include/cec.h @@ -239,6 +239,14 @@ namespace CEC */ virtual uint8_t VolumeDown(bool bSendRelease = true) = 0; +#if CEC_LIB_VERSION_MAJOR >= 5 + /*! + * @brief Toggles the mute status of an audiosystem, if it's present + * @return The new audio status. + */ + virtual uint8_t MuteAudio(void) = 0; +#endif + /*! * @brief Send a keypress to a device on the CEC bus. * @param iDestination The logical address of the device to send the message to. @@ -303,23 +311,28 @@ namespace CEC virtual bool GetCurrentConfiguration(libcec_configuration *configuration) = 0; /*! - * @brief Change libCEC's configuration. + * @brief Change libCEC's configuration. Store it updated settings in the eeprom of the device (if supported) * @param configuration The new configuration. * @return True when the configuration was changed successfully, false otherwise. */ virtual bool SetConfiguration(const libcec_configuration *configuration) = 0; /*! - * @return True when this CEC adapter can persist the user configuration, false otherwise. + * @return True if this CEC adapter can save the user configuration, false otherwise. */ +#if CEC_LIB_VERSION_MAJOR >= 5 + virtual bool CanSaveConfiguration(void) = 0; +#else virtual bool CanPersistConfiguration(void) = 0; /*! - * @brief Persist the given configuration in adapter (if supported) + * @deprecated Use SetConfiguration() instead + * @brief Change libCEC's configuration. Store it updated settings in the eeprom of the device (if supported) * @brief configuration The configuration to store. * @return True when the configuration was persisted, false otherwise. */ virtual bool PersistConfiguration(libcec_configuration *configuration) = 0; +#endif /*! * @brief Tell libCEC to poll for active devices on the bus. @@ -340,13 +353,30 @@ namespace CEC */ virtual bool GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs = 10000) = 0; +#if CEC_LIB_VERSION_MAJOR >= 5 /*! - * @brief Set and enable the callback methods. If this method is not called, the GetNext...() methods will have to be used. + * @brief Set and enable the callback methods + * @param callbacks The callbacks to set. + * @param cbParam Parameter to pass to callback methods. + * @return True if enabled, false otherwise. + */ + virtual bool SetCallbacks(ICECCallbacks *callbacks, void *cbParam) = 0; + + /*! + * @brief Disable all callbacks + * @return True if disabled, false otherwise. + */ + virtual bool DisableCallbacks(void) = 0; +#else + /*! + * @deprecated + * @brief Set and enable the callback methods. * @param cbParam Parameter to pass to callback methods. * @param callbacks The callbacks to set. * @return True when enabled, false otherwise. */ virtual bool EnableCallbacks(void *cbParam, ICECCallbacks *callbacks) = 0; +#endif /*! * @brief Changes the active HDMI port. @@ -438,7 +468,7 @@ namespace CEC * @param bQuickScan True to do a "quick scan", which will not open a connection to the adapter. Firmware version information and the exact device type will be missing * @return The number of devices that were found, or -1 when an error occurred. */ - virtual int8_t DetectAdapters(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL, bool bQuickScan = false) = 0; + virtual int8_t DetectAdapters(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = nullptr, bool bQuickScan = false) = 0; /*! * Create a new cec_command from a string @@ -468,7 +498,7 @@ extern "C" DECLSPEC void CECDestroy(CEC::ICECAdapter *instance); /*! * @brief Load the CEC adapter library. * @param configuration The configuration to pass to libCEC - * @return An instance of ICECAdapter or NULL on error. + * @return An instance of ICECAdapter or nullptr on error. */ extern "C" DECLSPEC CEC::ICECAdapter* CECInitialise(CEC::libcec_configuration *configuration); diff --git a/include/cecc.h b/include/cecc.h index 83a75e2e..c63611c7 100644 --- a/include/cecc.h +++ b/include/cecc.h @@ -53,7 +53,12 @@ extern DECLSPEC void libcec_destroy(libcec_connection_t connection); extern DECLSPEC int libcec_open(libcec_connection_t connection, const char* strPort, uint32_t iTimeout); extern DECLSPEC void libcec_close(libcec_connection_t connection); extern DECLSPEC void libcec_clear_configuration(CEC_NAMESPACE libcec_configuration* configuration); +#if CEC_LIB_VERSION_MAJOR >= 5 +extern DECLSPEC int libcec_set_callbacks(libcec_connection_t connection, CEC_NAMESPACE ICECCallbacks* callbacks, void* cbParam); +extern DECLSPEC int libcec_disabled_callbacks(libcec_connection_t connection); +#else extern DECLSPEC int libcec_enable_callbacks(libcec_connection_t connection, void* cbParam, CEC_NAMESPACE ICECCallbacks* callbacks); +#endif extern DECLSPEC int8_t libcec_find_adapters(libcec_connection_t connection, CEC_NAMESPACE cec_adapter* deviceList, uint8_t iBufSize, const char* strDevicePath); extern DECLSPEC int libcec_ping_adapters(libcec_connection_t connection); extern DECLSPEC int libcec_start_bootloader(libcec_connection_t connection); @@ -83,7 +88,9 @@ extern DECLSPEC int libcec_is_active_device_type(libcec_connection_t connection, extern DECLSPEC int libcec_set_hdmi_port(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address baseDevice, uint8_t iPort); extern DECLSPEC int libcec_volume_up(libcec_connection_t connection, int bSendRelease); extern DECLSPEC int libcec_volume_down(libcec_connection_t connection, int bSendRelease); +#if CEC_LIB_VERSION_MAJOR >= 5 extern DECLSPEC int libcec_mute_audio(libcec_connection_t connection, int bSendRelease); +#endif extern DECLSPEC int libcec_send_keypress(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iDestination, CEC_NAMESPACE cec_user_control_code key, int bWait); extern DECLSPEC int libcec_send_key_release(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iDestination, int bWait); extern DECLSPEC int libcec_get_device_osd_name(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iAddress, CEC_NAMESPACE cec_osd_name name); @@ -91,8 +98,12 @@ extern DECLSPEC int libcec_set_stream_path_logical(libcec_connection_t connectio extern DECLSPEC int libcec_set_stream_path_physical(libcec_connection_t connection, uint16_t iPhysicalAddress); extern DECLSPEC CEC_NAMESPACE cec_logical_addresses libcec_get_logical_addresses(libcec_connection_t connection); extern DECLSPEC int libcec_get_current_configuration(libcec_connection_t connection, CEC_NAMESPACE libcec_configuration* configuration); +#if CEC_LIB_VERSION_MAJOR >= 5 +extern DECLSPEC int libcec_can_save_configuration(libcec_connection_t connection); +#else extern DECLSPEC int libcec_can_persist_configuration(libcec_connection_t connection); extern DECLSPEC int libcec_persist_configuration(libcec_connection_t connection, CEC_NAMESPACE libcec_configuration* configuration); +#endif extern DECLSPEC int libcec_set_configuration(libcec_connection_t connection, const CEC_NAMESPACE libcec_configuration* configuration); extern DECLSPEC void libcec_rescan_devices(libcec_connection_t connection); extern DECLSPEC int libcec_is_libcec_active_source(libcec_connection_t connection); diff --git a/include/cectypes.h b/include/cectypes.h index 35e44ea4..e585f2fe 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -375,7 +375,8 @@ typedef enum cec_version CEC_VERSION_1_2A = 0x02, CEC_VERSION_1_3 = 0x03, CEC_VERSION_1_3A = 0x04, - CEC_VERSION_1_4 = 0x05 + CEC_VERSION_1_4 = 0x05, + CEC_VERSION_2_0 = 0x06, } cec_version; typedef enum cec_channel_identifier @@ -886,7 +887,7 @@ typedef enum cec_adapter_type ADAPTERTYPE_EXYNOS = 0x300, ADAPTERTYPE_LINUX = 0x400, ADAPTERTYPE_AOCEC = 0x500, - ADAPTERTYPE_IMX = 0x600 + ADAPTERTYPE_IMX = 0x600 } cec_adapter_type; /** force exporting through swig */ @@ -1502,7 +1503,7 @@ struct libcec_configuration uint8_t bMonitorOnly; /*!< won't allocate a CCECClient when starting the connection when set (same as monitor mode). added in 1.6.3 */ cec_version cecVersion; /*!< CEC spec version to use by libCEC. defaults to v1.4. added in 1.8.0 */ cec_adapter_type adapterType; /*!< type of the CEC adapter that we're connected to. added in 1.8.2 */ - cec_user_control_code comboKey; /*!< key code that initiates combo keys. defaults to CEC_USER_CONTROL_CODE_F1_BLUE. CEC_USER_CONTROL_CODE_UNKNOWN to disable. added in 2.0.5 */ + cec_user_control_code comboKey; /*!< key code that initiates combo keys. defaults to CEC_USER_CONTROL_CODE_STOP. CEC_USER_CONTROL_CODE_UNKNOWN to disable. added in 2.0.5 */ uint32_t iComboKeyTimeoutMs; /*!< timeout until the combo key is sent as normal keypress */ uint32_t iButtonRepeatRateMs; /*!< rate at which buttons autorepeat. 0 means rely on CEC device */ uint32_t iButtonReleaseDelayMs;/*!< duration after last update until a button is considered released */ @@ -1584,7 +1585,7 @@ struct libcec_configuration iButtonReleaseDelayMs = CEC_BUTTON_TIMEOUT; bAutoWakeAVR = 0; #if CEC_LIB_VERSION_MAJOR >= 5 - bAutoPowerOn = 0; + bAutoPowerOn = 2; #endif strDeviceName[0] = (char)0; diff --git a/project/favicon.ico b/project/favicon.ico index dc1baae9..01fc1932 100644 Binary files a/project/favicon.ico and b/project/favicon.ico differ diff --git a/project/libcec.sln b/project/libcec.sln index cc64f743..36af5089 100644 --- a/project/libcec.sln +++ b/project/libcec.sln @@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30011.22 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCecSharp", "..\src\dotnetlib\LibCecSharp\project\LibCecSharp.vcxproj", "{E54D4581-CD59-4687-BB10-694B8192EABA}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCecSharp", "..\src\dotnetlib\LibCecSharp\LibCecSharp.vcxproj", "{E54D4581-CD59-4687-BB10-694B8192EABA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B119505D-5CD1-48E4-BED1-9C2BF26153D5}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCecSharpCore", "..\src\dotnetlib\LibCecSharpCore\project\LibCecSharpCore.vcxproj", "{E8C30CBD-64D1-44F8-9172-82B728986DCC}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibCecSharpCore", "..\src\dotnetlib\LibCecSharpCore\LibCecSharpCore.vcxproj", "{E8C30CBD-64D1-44F8-9172-82B728986DCC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/project/nsis/cec-tray.nsh b/project/nsis/cec-tray.nsh new file mode 100644 index 00000000..d59bd0d7 --- /dev/null +++ b/project/nsis/cec-tray.nsh @@ -0,0 +1,25 @@ +Section "libCEC Tray" SecTray + SetShellVarContext current + SectionIn 1 + + ; Copy to the installation directory + SetOutPath "$INSTDIR\x86\netfx" + File "..\build\x86\cec-tray.exe" + SetOutPath "$INSTDIR\x64\netfx" + File /nonfatal "..\build\amd64\cec-tray.exe" + + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + SetOutPath "$INSTDIR" + + CreateDirectory "$SMPROGRAMS\$StartMenuFolder" + ${If} ${RunningX64} + CreateShortCut "$SMPROGRAMS\$StartMenuFolder\cec-tray.lnk" "$INSTDIR\x64\netfx\cec-tray.exe" \ + "" "$INSTDIR\x64\netfx\cec-tray.exe" 0 SW_SHOWNORMAL \ + "" "Start libCEC Tray (x64)." + ${Else} + CreateShortCut "$SMPROGRAMS\$StartMenuFolder\cec-tray.lnk" "$INSTDIR\x86\netfx\cec-tray.exe" \ + "" "$INSTDIR\netfx\cec-tray.exe" 0 SW_SHOWNORMAL \ + "" "Start libCEC Tray." + ${EndIf} + !insertmacro MUI_STARTMENU_WRITE_END +SectionEnd diff --git a/project/nsis/functions.nsh b/project/nsis/functions.nsh index 718896ca..1dedbb66 100644 --- a/project/nsis/functions.nsh +++ b/project/nsis/functions.nsh @@ -12,31 +12,3 @@ !undef _TEMPFILE !macroend !define !defineifexist "!insertmacro !defineifexist" - -; Function used to get the parent directory of the installer -Function GetParentDirectory - - Exch $R0 - Push $R1 - Push $R2 - Push $R3 - - StrCpy $R1 0 - StrLen $R2 $R0 - - loop: - IntOp $R1 $R1 + 1 - IntCmp $R1 $R2 get 0 get - StrCpy $R3 $R0 1 -$R1 - StrCmp $R3 "\" get - Goto loop - - get: - StrCpy $R0 $R0 -$R1 - - Pop $R3 - Pop $R2 - Pop $R1 - Exch $R0 - -FunctionEnd \ No newline at end of file diff --git a/project/nsis/sections.nsh b/project/nsis/sections.nsh index 63efb783..b582be46 100644 --- a/project/nsis/sections.nsh +++ b/project/nsis/sections.nsh @@ -7,7 +7,6 @@ Section "USB-CEC driver" SecDriver File "..\build\p8-usbcec-driver-installer.exe" ;install driver ExecWait '"$INSTDIR\driver\p8-usbcec-driver-installer.exe" /S' - Delete "$INSTDIR\driver\p8-usbcec-driver-installer.exe" SectionEnd Section "libCEC" SecLibCec @@ -21,18 +20,6 @@ Section "libCEC" SecLibCec Delete "$INSTDIR\x64\libcec.dll" ${EndIf} - ; Moved to netfx subdir - Delete "$INSTDIR\CecSharpTester.exe" - Delete "$INSTDIR\cec-tray.exe" - Delete "$INSTDIR\LibCecSharp.dll" - Delete "$INSTDIR\LibCecSharp.xml" - ${If} ${RunningX64} - Delete "$INSTDIR\x64\CecSharpTester.exe" - Delete "$INSTDIR\x64\cec-tray.exe" - Delete "$INSTDIR\x64\LibCecSharp.dll" - Delete "$INSTDIR\x64\LibCecSharp.xml" - ${EndIf} - ; Copy to the installation directory SetOutPath "$INSTDIR" File "..\ChangeLog" @@ -40,6 +27,8 @@ Section "libCEC" SecLibCec File "..\docs\README.developers.md" File "..\docs\README.windows.md" File "..\build\x86\cec.dll" + File "..\support\windows\tv_on.cmd" + File "..\support\windows\tv_off.cmd" SetOutPath "$INSTDIR\x64" File /nonfatal "..\build\amd64\cec.dll" @@ -61,7 +50,6 @@ Section "libCEC" SecLibCec File $%TEMP%\uninstall_libcec.exe !endif - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application SetOutPath "$INSTDIR" @@ -110,70 +98,71 @@ Section "libCEC for .Net Framework" SecDotNet SetShellVarContext current SectionIn 1 2 + ; Moved to x86\netfx subdir + RMDIR /R "$INSTDIR\netfx" + Delete "$INSTDIR\CecSharpTester.exe" + Delete "$INSTDIR\cec-tray.exe" + Delete "$INSTDIR\LibCecSharp.dll" + Delete "$INSTDIR\LibCecSharp.xml" + ; Copy to the installation directory - SetOutPath "$INSTDIR\netfx" + SetOutPath "$INSTDIR\x86\netfx" File "..\build\x86\LibCecSharp.dll" File "..\build\x86\LibCecSharp.xml" - File "..\build\x86\CecSharpTester.exe" - SetOutPath "$INSTDIR\x64\netfx" - File /nonfatal "..\build\amd64\CecSharpTester.exe" - File /nonfatal "..\build\amd64\LibCecSharp.dll" - File /nonfatal "..\build\amd64\LibCecSharp.xml" + File /nonfatal "..\build\x86\CecSharpTester.exe" + + ${If} ${RunningX64} + ; Moved to netfx subdir + Delete "$INSTDIR\x64\CecSharpTester.exe" + Delete "$INSTDIR\x64\cec-tray.exe" + Delete "$INSTDIR\x64\LibCecSharp.dll" + Delete "$INSTDIR\x64\LibCecSharp.xml" + + ; Copy to the installation directory + SetOutPath "$INSTDIR\x64\netfx" + File /nonfatal "..\build\amd64\CecSharpTester.exe" + File /nonfatal "..\build\amd64\LibCecSharp.dll" + File /nonfatal "..\build\amd64\LibCecSharp.xml" + ${EndIf} SectionEnd Section "libCEC for .Net Core" SecDotNetCore SetShellVarContext current SectionIn 1 2 + ; Moved to x86\netcore subdir + RMDIR /R "$INSTDIR\netcore" + ; Copy to the installation directory - SetOutPath "$INSTDIR\netcore" + SetOutPath "$INSTDIR\x86\netcore" File "..\build\x86\netcore\LibCecSharpCore.deps.json" File "..\build\x86\netcore\LibCecSharpCore.dll" File "..\build\x86\netcore\LibCecSharpCore.runtimeconfig.json" File "..\build\x86\netcore\LibCecSharpCore.xml" - File "..\build\x86\netcore\CecSharpCoreTester.exe" - File "..\build\x86\netcore\CecSharpCoreTester.deps.json" - File "..\build\x86\netcore\CecSharpCoreTester.dll" - File "..\build\x86\netcore\CecSharpCoreTester.runtimeconfig.json" - File "..\build\x86\netcore\Ijwhost.dll" - SetOutPath "$INSTDIR\x64\netcore" - File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.deps.json" - File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.dll" - File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.runtimeconfig.json" - File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.xml" - File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.exe" - File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.deps.json" - File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.dll" - File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.runtimeconfig.json" - File /nonfatal "..\build\amd64\netcore\Ijwhost.dll" -SectionEnd + File /nonfatal "..\build\x86\netcore\CecSharpCoreTester.exe" + File /nonfatal "..\build\x86\netcore\CecSharpCoreTester.deps.json" + File /nonfatal "..\build\x86\netcore\CecSharpCoreTester.dll" + File /nonfatal "..\build\x86\netcore\CecSharpCoreTester.runtimeconfig.json" + File /nonfatal "..\build\x86\netcore\Ijwhost.dll" -Section "libCEC Tray" SecTray - SetShellVarContext current - SectionIn 1 - - ; Copy to the installation directory - SetOutPath "$INSTDIR\netfx" - File "..\build\x86\cec-tray.exe" - SetOutPath "$INSTDIR\x64\netfx" - File /nonfatal "..\build\amd64\cec-tray.exe" - - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application - SetOutPath "$INSTDIR" - - CreateDirectory "$SMPROGRAMS\$StartMenuFolder" ${If} ${RunningX64} - CreateShortCut "$SMPROGRAMS\$StartMenuFolder\cec-tray.lnk" "$INSTDIR\x64\netfx\cec-tray.exe" \ - "" "$INSTDIR\x64\netfx\cec-tray.exe" 0 SW_SHOWNORMAL \ - "" "Start libCEC Tray (x64)." - ${Else} - CreateShortCut "$SMPROGRAMS\$StartMenuFolder\cec-tray.lnk" "$INSTDIR\netfx\cec-tray.exe" \ - "" "$INSTDIR\netfx\cec-tray.exe" 0 SW_SHOWNORMAL \ - "" "Start libCEC Tray." + SetOutPath "$INSTDIR\x64\netcore" + File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.deps.json" + File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.dll" + File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.runtimeconfig.json" + File /nonfatal "..\build\amd64\netcore\LibCecSharpCore.xml" + File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.exe" + File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.deps.json" + File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.dll" + File /nonfatal "..\build\amd64\netcore\CecSharpCoreTester.runtimeconfig.json" + File /nonfatal "..\build\amd64\netcore\Ijwhost.dll" ${EndIf} - !insertmacro MUI_STARTMENU_WRITE_END SectionEnd +!ifdef NSISDOTNETAPPS +!include "nsis\cec-tray.nsh" +!endif + Section "libCEC client (cec-client)" SecCecClient SetShellVarContext current SectionIn 1 @@ -211,6 +200,24 @@ Section "Python client" SecPythonCecClient File "..\build\x86\python\pyCecClient.py" SectionEnd +Section "Adapter Firmware" SecFwUpgrade + SetShellVarContext current + SectionIn 1 + + ; Copy the driver installer + SetOutPath "$INSTDIR\driver" + File "..\build\p8-usbcec-bootloader-driver-installer.exe" + ;install driver + ExecWait '"$INSTDIR\driver\p8-usbcec-bootloader-driver-installer.exe" /S' + + SetOutPath "$INSTDIR" + NSISdl::download https://p8.opdenkamp.eu/cec/cec-firmware-latest.exe cec-firmware-latest.exe + + CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Firmware Upgrade.lnk" "$INSTDIR\cec-firmware-latest.exe" \ + "" "$INSTDIR\cec-firmware-latest.exe" 0 SW_SHOWNORMAL \ + "" "Upgrade the firmware of the CEC adapter to the latest version." +SectionEnd + !define KODI_X86_SECTIONNAME "Kodi integration (x86)" Section "" SecLibCecKodi86 SetShellVarContext current @@ -234,15 +241,11 @@ Section "" SecEvGhostCec SetShellVarContext current SectionIn 1 + SetOutPath "$INSTDIR\EventGhost" + File "..\build\EventGhost\pulse_eight.egplugin" + ${If} $EventGhostLocation != "" - ; We get the directory of the installer then pass it to GetParentDirectory - ; which we then append the path to the plugin file to the returned value - ; This is done because EventGhost needs to see the full path to the plugin - ; file. - Push $EXEDIR - Call GetParentDirectory - Pop $R0 - ExecWait '"$EventGhostLocation\eventghost.exe" $R0\src\EventGhost\pulse_eight.egplugin' + ExecWait '"$EventGhostLocation\eventghost.exe" "$INSTDIR\EventGhost\pulse_eight.egplugin"' ${EndIf} SectionEnd @@ -284,6 +287,7 @@ SectionEnd ; Required options Function .onSelChange +!ifdef NSISDOTNETAPPS ${If} ${SectionIsSelected} ${SecTray} !define /math MYSECTIONFLAGS ${SF_SELECTED} | ${SF_RO} !insertmacro SetSectionFlag ${SecDotNet} ${MYSECTIONFLAGS} @@ -291,6 +295,7 @@ ${If} ${SectionIsSelected} ${SecTray} ${Else} !insertmacro ClearSectionFlag ${SecDotNet} ${SF_RO} ${EndIf} +!endif ${If} ${SectionIsSelected} ${SecPythonCecClient} !define /math MYSECTIONFLAGS ${SF_SELECTED} | ${SF_RO} diff --git a/src/cec-client/cec-client.cpp b/src/cec-client/cec-client.cpp index 63daf16b..b209b1ee 100644 --- a/src/cec-client/cec-client.cpp +++ b/src/cec-client/cec-client.cpp @@ -302,7 +302,7 @@ void ShowHelpCommandLine(const char* strExec) " -b --base {int} The logical address of the device to which this " << std::endl << " adapter is connected." << std::endl << " -f --log-file {file} Writes all libCEC log message to a file" << std::endl << - " -r --rom Read persisted settings from the EEPROM" << std::endl << + " -r --rom Read saved settings from the EEPROM" << std::endl << " -sf --short-log-file {file} Writes all libCEC log message without timestamps" << std::endl << " and log levels to a file." << std::endl << " -d --log-level {level} Sets the log level. See cectypes.h for values." << std::endl << diff --git a/src/dotnet b/src/dotnet index 3b371d0c..1a284e8b 160000 --- a/src/dotnet +++ b/src/dotnet @@ -1 +1 @@ -Subproject commit 3b371d0cec8c8fe94fe6f6785ea0f2e1c59aeec1 +Subproject commit 1a284e8bf1c722e8530236fe9ced8e5d207e360d diff --git a/src/dotnetlib/CecSharpTypes.h b/src/dotnetlib/CecSharpTypes.h index 8af13278..b3c745f3 100644 --- a/src/dotnetlib/CecSharpTypes.h +++ b/src/dotnetlib/CecSharpTypes.h @@ -2,7 +2,7 @@ /* * 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 Copyright (C) 2011-2020 Pulse-Eight Limited. All rights reserved. * libCEC(R) is an original work, containing original code. * * libCEC(R) is a trademark of Pulse-Eight Limited. @@ -29,9 +29,13 @@ * Pulse-Eight Licensing * http://www.pulse-eight.com/ * http://www.pulse-eight.net/ +* +* Author: Lars Op den Kamp +* */ #include "p8-platform/threads/mutex.h" +#include "CecSharpTypesUnmanaged.h" #include #include #include "../../include/cec.h" @@ -316,7 +320,11 @@ namespace CecSharp /// /// Version 1.4 /// - V1_4 = 0x05 + V1_4 = 0x05, + /// + /// Version 2.0 + /// + V2_0 = 0x06 }; /// @@ -808,7 +816,7 @@ namespace CecSharp Sharp = 0x08001F, Sony = 0x080046, Broadcom = 0x18C086, - Sharp2 = 0x534850, + Sharp2 = 0x534850, Vizio = 0x6B746D, Benq = 0x8065E9, HarmanKardon = 0x9C645E, @@ -1119,6 +1127,27 @@ namespace CecSharp On = 1 }; +#if CEC_LIB_VERSION_MAJOR >= 5 + /// + /// A setting that can be enabled, disabled or not changed + /// + public enum class BoolSetting + { + /// + /// Setting disabled + /// + Disabled = 0, + /// + /// Setting enabled + /// + Enabled = 1, + /// + /// Don't change the value of the setting / setting value not known + /// + NotSet = 2 + }; +#endif + /// /// Type of adapter to which libCEC is connected /// @@ -1219,6 +1248,14 @@ namespace CecSharp CecDeviceTypeList(void) { Types = gcnew array(5); + Clear(); + } + + /// + /// Clear this list + /// + void Clear(void) + { for (unsigned int iPtr = 0; iPtr < 5; iPtr++) Types[iPtr] = CecDeviceType::Reserved; } @@ -1286,7 +1323,6 @@ namespace CecSharp property array ^ Addresses; }; - /// /// Byte array used for CEC command parameters /// @@ -1521,6 +1557,51 @@ namespace CecSharp property int64_t Time; }; +#if CEC_LIB_VERSION_MAJOR >= 5 + public ref class CecAdapterStats + { + public: + CecAdapterStats(const struct CEC::cec_adapter_stats* stats) + { + if (!!stats) + { + TxAck = stats->tx_ack; + TxNack = stats->tx_nack; + TxError = stats->tx_error; + RxTotal = stats->rx_total; + RxError = stats->rx_error; + } else { + TxAck = 0; + TxNack = 0; + TxError = 0; + RxTotal = 0; + RxError = 0; + } + } + + /// + /// Frames sent and acked + /// + property unsigned int TxAck; + /// + /// Frames sent but not acked + /// + property unsigned int TxNack; + /// + /// Frames that couldn't be sent because of a transmission error + /// + property unsigned int TxError; + /// + /// Full frames received + /// + property unsigned int RxTotal; + /// + /// Frames that couldn't be received (fully) because of a transmission error + /// + property unsigned int RxError; + }; +#endif + ref class CecCallbackMethods; //forward declaration /// @@ -1559,46 +1640,34 @@ namespace CecSharp LogicalAddresses = gcnew CecLogicalAddresses(); FirmwareVersion = 1; - DeviceLanguage = ""; + DeviceLanguage = CEC_DEFAULT_DEVICE_LANGUAGE; FirmwareBuildDate = gcnew System::DateTime(1970,1,1,0,0,0,0); CECVersion = (CecVersion)CEC_DEFAULT_SETTING_CEC_VERSION; AdapterType = CecAdapterType::Unknown; - } - - static uint32_t CurrentVersion = _LIBCEC_VERSION_CURRENT; - /// - /// Change the callback method pointers in this configuration instance. - /// - /// The new callbacks - void SetCallbacks(CecCallbackMethods ^callbacks) - { - Callbacks = callbacks; + ComboKey = CecUserControlCode::Stop; + ComboKeyTimeoutMs = CEC_DEFAULT_COMBO_TIMEOUT_MS; + ButtonRepeatRateMs = 0; + ButtonReleaseDelayMs = CEC_BUTTON_TIMEOUT; + DoubleTapTimeoutMs = 0; + AutoWakeAVR = false; +#if CEC_LIB_VERSION_MAJOR >= 5 + AutoPowerOn = BoolSetting::NotSet; +#endif } + static uint32_t CurrentVersion = _LIBCEC_VERSION_CURRENT; + /// /// Update this configuration with data received from libCEC /// /// The configuration that was received from libCEC void Update(const CEC::libcec_configuration &config) { - DeviceName = gcnew System::String(config.strDeviceName); - + DeviceTypes->Clear(); for (unsigned int iPtr = 0; iPtr < 5; iPtr++) DeviceTypes->Types[iPtr] = (CecDeviceType)config.deviceTypes.types[iPtr]; - AutodetectAddress = config.bAutodetectAddress == 1; - PhysicalAddress = config.iPhysicalAddress; - BaseDevice = (CecLogicalAddress)config.baseDevice; - HDMIPort = config.iHDMIPort; - ClientVersion = config.clientVersion; - ServerVersion = config.serverVersion; - TvVendor = (CecVendorId)config.tvVendor; - - // player specific settings - GetSettingsFromROM = config.bGetSettingsFromROM == 1; - ActivateSource = config.bActivateSource == 1; - WakeDevices->Clear(); for (uint8_t iPtr = 0; iPtr <= 16; iPtr++) if (config.wakeDevices[iPtr]) @@ -1609,22 +1678,76 @@ namespace CecSharp if (config.powerOffDevices[iPtr]) PowerOffDevices->Set((CecLogicalAddress)iPtr); - PowerOffOnStandby = config.bPowerOffOnStandby == 1; - - LogicalAddresses->Clear(); + LogicalAddresses->Clear(); for (uint8_t iPtr = 0; iPtr <= 16; iPtr++) if (config.logicalAddresses[iPtr]) LogicalAddresses->Set((CecLogicalAddress)iPtr); - FirmwareVersion = config.iFirmwareVersion; - - DeviceLanguage = gcnew System::String(config.strDeviceLanguage); - FirmwareBuildDate = gcnew System::DateTime(1970,1,1,0,0,0,0); - FirmwareBuildDate = FirmwareBuildDate->AddSeconds(config.iFirmwareBuildDate); + DeviceName = gcnew System::String(config.strDeviceName); + AutodetectAddress = (config.bAutodetectAddress == 1); + PhysicalAddress = config.iPhysicalAddress; + BaseDevice = (CecLogicalAddress)config.baseDevice; + HDMIPort = config.iHDMIPort; + ClientVersion = config.clientVersion; + ServerVersion = config.serverVersion; + TvVendor = (CecVendorId)config.tvVendor; + GetSettingsFromROM = (config.bGetSettingsFromROM == 1); + ActivateSource = (config.bActivateSource == 1); + + PowerOffOnStandby = (config.bPowerOffOnStandby == 1); + FirmwareVersion = config.iFirmwareVersion; + + DeviceLanguage = gcnew System::String(config.strDeviceLanguage); + FirmwareBuildDate = gcnew System::DateTime(1970,1,1,0,0,0,0); + FirmwareBuildDate = FirmwareBuildDate->AddSeconds(config.iFirmwareBuildDate); + + MonitorOnlyClient = (config.bMonitorOnly == 1); + CECVersion = (CecVersion)config.cecVersion; + AdapterType = (CecAdapterType)config.adapterType; + + ComboKey = (CecUserControlCode)config.comboKey; + ComboKeyTimeoutMs = config.iComboKeyTimeoutMs; + ButtonRepeatRateMs = config.iButtonRepeatRateMs; + ButtonReleaseDelayMs = config.iButtonReleaseDelayMs; + DoubleTapTimeoutMs = config.iDoubleTapTimeoutMs; + AutoWakeAVR = (config.bAutoWakeAVR == 1); +#if CEC_LIB_VERSION_MAJOR >= 5 + AutoPowerOn = (config.bAutoPowerOn == 1) ? BoolSetting::Enabled : BoolSetting::Disabled; +#endif + } - MonitorOnlyClient = config.bMonitorOnly == 1; - CECVersion = (CecVersion)config.cecVersion; - AdapterType = (CecAdapterType)config.adapterType; + void Update(LibCECConfiguration ^ config) + { + DeviceTypes = config->DeviceTypes; + WakeDevices = config->WakeDevices; + PowerOffDevices = config->PowerOffDevices; + LogicalAddresses = config->LogicalAddresses; + DeviceName = config->DeviceName; + AutodetectAddress = config->AutodetectAddress; + PhysicalAddress = config->PhysicalAddress; + BaseDevice = config->BaseDevice; + HDMIPort = config->HDMIPort; + ClientVersion = config->ClientVersion; + ServerVersion = config->ServerVersion; + TvVendor = config->TvVendor; + GetSettingsFromROM = config->GetSettingsFromROM; + ActivateSource = config->ActivateSource; + PowerOffOnStandby = config->PowerOffOnStandby; + FirmwareVersion = config->FirmwareVersion; + DeviceLanguage = config->DeviceLanguage; + FirmwareBuildDate = config->FirmwareBuildDate; + MonitorOnlyClient = config->MonitorOnlyClient; + CECVersion = config->CECVersion; + AdapterType = config->AdapterType; + ComboKey = config->ComboKey; + ComboKeyTimeoutMs = config->ComboKeyTimeoutMs; + ButtonRepeatRateMs = config->ButtonRepeatRateMs; + ButtonReleaseDelayMs = config->ButtonReleaseDelayMs; + DoubleTapTimeoutMs = config->DoubleTapTimeoutMs; + AutoWakeAVR = config->AutoWakeAVR; +#if CEC_LIB_VERSION_MAJOR >= 5 + AutoPowerOn = config->AutoPowerOn; +#endif } /// @@ -1706,7 +1829,7 @@ namespace CecSharp /// The firmware version of the adapter to which libCEC is connected /// property uint16_t FirmwareVersion; - + /// /// True to start a monitor-only client, false to start a standard client. /// @@ -1738,174 +1861,45 @@ namespace CecSharp /// property CecAdapterType AdapterType; - }; - - // the callback methods are called by unmanaged code, so we need some delegates for this -#pragma unmanaged - // unmanaged callback methods - typedef void (__stdcall *LOGCB) (const CEC::cec_log_message* message); - typedef void (__stdcall *KEYCB) (const CEC::cec_keypress* key); - typedef void (__stdcall *COMMANDCB)(const CEC::cec_command* command); - typedef void (__stdcall *CONFIGCB) (const CEC::libcec_configuration* config); - typedef void (__stdcall *ALERTCB) (const CEC::libcec_alert, const CEC::libcec_parameter &data); - typedef int (__stdcall *MENUCB) (const CEC::cec_menu_state newVal); - typedef void (__stdcall *ACTICB) (const CEC::cec_logical_address logicalAddress, const uint8_t bActivated); - - /// - /// libCEC callback methods. Unmanaged code. - /// - typedef struct - { /// - /// Log message callback + /// Key code that initiates combo keys. + /// Defaults to CecUserControlCode::Stop. CecUserControlCode::Unknown to disable /// - LOGCB logCB; + property CecUserControlCode ComboKey; + /// - /// Key press/release callback + /// Timeout in ms until the combo key is sent as normal keypress. /// - KEYCB keyCB; + property uint32_t ComboKeyTimeoutMs; + /// - /// Raw CEC data callback + /// Rate at which buttons autorepeat. 0 means rely on CEC device. /// - COMMANDCB commandCB; + property uint32_t ButtonRepeatRateMs; + /// - /// Updated configuration callback + /// Duration after last update until a button is considered released. /// - CONFIGCB configCB; + property uint32_t ButtonReleaseDelayMs; + /// - /// Alert message callback + /// Prevent double taps within this timeout. defaults to 200ms. /// - ALERTCB alertCB; + property uint32_t DoubleTapTimeoutMs; + /// - /// Menu status change callback + /// Set to true to automatically waking an AVR when the source is activated /// - MENUCB menuCB; + property bool AutoWakeAVR; + +#if CEC_LIB_VERSION_MAJOR >= 5 /// - /// Source (de)activated callback + /// Set to Enabled and save eeprom config to wake the tv when usb is powered. Requires firmware v9+ /// - ACTICB sourceActivatedCB; - } UnmanagedCecCallbacks; - - static P8PLATFORM::CMutex g_callbackMutex; - static std::vector g_unmanagedCallbacks; - static CEC::ICECCallbacks g_cecCallbacks; - - /// - /// Called by libCEC to send back a log message to the application - /// - /// Pointer to the callback struct - /// The log message - void CecLogMessageCB(void *cbParam, const CEC::cec_log_message* message) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - g_unmanagedCallbacks[iPtr].logCB(message); - } - } - - /// - /// Called by libCEC to send back a key press or release to the application - /// - /// Pointer to the callback struct - /// The key press command that libCEC received - void CecKeyPressCB(void *cbParam, const CEC::cec_keypress* key) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - g_unmanagedCallbacks[iPtr].keyCB(key); - } - } - - /// - /// Called by libCEC to send back raw CEC data to the application - /// - /// Pointer to the callback struct - /// The raw CEC data - void CecCommandCB(void *cbParam, const CEC::cec_command* command) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - g_unmanagedCallbacks[iPtr].commandCB(command); - } - } - - /// - /// Called by libCEC to send back an updated configuration to the application - /// - /// Pointer to the callback struct - /// The new configuration - void CecConfigCB(void *cbParam, const CEC::libcec_configuration* config) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - g_unmanagedCallbacks[iPtr].configCB(config); - } - } - - /// - /// Called by libCEC to send back an alert message to the application - /// - /// Pointer to the callback struct - /// The alert message - void CecAlertCB(void *cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter data) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - g_unmanagedCallbacks[iPtr].alertCB(alert, data); - } - } - - /// - /// Called by libCEC to send back a menu state change to the application - /// - /// Pointer to the callback struct - /// The new menu state - /// 1 when handled, 0 otherwise - int CecMenuCB(void *cbParam, const CEC::cec_menu_state newVal) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - return g_unmanagedCallbacks[iPtr].menuCB(newVal); - } - return 0; - } - - /// - /// Called by libCEC to notify the application that the source that is handled by libCEC was (de)activated - /// - /// Pointer to the callback struct - /// The logical address that was (de)activated - /// True when activated, false when deactivated - void CecSourceActivatedCB(void *cbParam, const CEC::cec_logical_address logicalAddress, const uint8_t activated) - { - if (cbParam) - { - size_t iPtr = (size_t)cbParam; - P8PLATFORM::CLockObject lock(g_callbackMutex); - if (iPtr >= 0 && iPtr < g_unmanagedCallbacks.size()) - g_unmanagedCallbacks[iPtr].sourceActivatedCB(logicalAddress, activated); - } - } + property BoolSetting AutoPowerOn; +#endif + }; -#pragma managed /// /// Delegate method for the CecLogMessageCB callback in CecCallbackMethods /// @@ -1935,20 +1929,6 @@ namespace CecSharp /// public delegate void CecSourceActivatedManagedDelegate(const CEC::cec_logical_address, const uint8_t); - /// - /// Assign the callback methods in the g_cecCallbacks struct - /// - void AssignCallbacks() - { - g_cecCallbacks.logMessage = CecLogMessageCB; - g_cecCallbacks.keyPress = CecKeyPressCB; - g_cecCallbacks.commandReceived = CecCommandCB; - g_cecCallbacks.configurationChanged = CecConfigCB; - g_cecCallbacks.alert = CecAlertCB; - g_cecCallbacks.menuStateChanged = CecMenuCB; - g_cecCallbacks.sourceActivated = CecSourceActivatedCB; - } - /// /// The callback methods that libCEC uses /// @@ -1957,59 +1937,61 @@ namespace CecSharp public: CecCallbackMethods(void) { - m_iCallbackPtr = -1; - AssignCallbacks(); - m_bHasCallbacks = false; - m_bDelegatesCreated = false; + msclr::interop::marshal_context^ context = gcnew msclr::interop::marshal_context(); + struct UnmanagedCecCallbacks* unmanagedCallbacks; + if (!(m_unmanagedCallbacks = calloc(1, sizeof(struct UnmanagedCecCallbacks)))) { + throw gcnew System::Exception("Could not initialise LibCecSharp: oom"); + } + unmanagedCallbacks = (struct UnmanagedCecCallbacks*)m_unmanagedCallbacks; + + // create the delegate method for the log message callback + m_logMessageDelegate = gcnew CecLogMessageManagedDelegate(this, &CecCallbackMethods::CecLogMessageManaged); + m_logMessageGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_logMessageDelegate); + unmanagedCallbacks->logCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer()); + + // create the delegate method for the keypress callback + m_keypressDelegate = gcnew CecKeyPressManagedDelegate(this, &CecCallbackMethods::CecKeyPressManaged); + m_keypressGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_keypressDelegate); + unmanagedCallbacks->keyCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer()); + + // create the delegate method for the command callback + m_commandDelegate = gcnew CecCommandManagedDelegate(this, &CecCallbackMethods::CecCommandManaged); + m_commandGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_commandDelegate); + unmanagedCallbacks->commandCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer()); + + // create the delegate method for the configuration change callback + m_configDelegate = gcnew CecConfigManagedDelegate(this, &CecCallbackMethods::CecConfigManaged); + m_configGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_configDelegate); + unmanagedCallbacks->configCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_configDelegate).ToPointer()); + + // create the delegate method for the alert callback + m_alertDelegate = gcnew CecAlertManagedDelegate(this, &CecCallbackMethods::CecAlertManaged); + m_alertGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_alertDelegate); + unmanagedCallbacks->alertCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_alertDelegate).ToPointer()); + + // create the delegate method for the menu callback + m_menuDelegate = gcnew CecMenuManagedDelegate(this, &CecCallbackMethods::CecMenuManaged); + m_menuGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_menuDelegate); + unmanagedCallbacks->menuCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_menuDelegate).ToPointer()); + + // create the delegate method for the source activated callback + m_sourceActivatedDelegate = gcnew CecSourceActivatedManagedDelegate(this, &CecCallbackMethods::CecSourceActivatedManaged); + m_sourceActivatedGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_sourceActivatedDelegate); + unmanagedCallbacks->sourceActivatedCB = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_sourceActivatedDelegate).ToPointer()); + + delete context; } ~CecCallbackMethods(void) { - DestroyDelegates(); - } - - /// - /// Pointer to the callbacks struct entry - /// - size_t GetCallbackPtr(void) - { - P8PLATFORM::CLockObject lock(g_callbackMutex); - return m_iCallbackPtr; } protected: !CecCallbackMethods(void) { - DestroyDelegates(); } public: - /// - /// Disable callback methods - /// - virtual void DisableCallbacks(void) - { - DestroyDelegates(); - } - - /// - /// Enable callback methods - /// - /// Callback methods to activate - /// true when handled, false otherwise - virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) - { - CreateDelegates(); - if (!m_bHasCallbacks) - { - m_bHasCallbacks = true; - m_callbacks = callbacks; - return true; - } - - return false; - } - /// /// Called by libCEC to send back a log message to the application. /// Override in the application to handle this callback. @@ -2086,188 +2068,115 @@ namespace CecSharp { } + void* Get(void) + { + return m_unmanagedCallbacks; + } + + void Destroy() + { + m_logMessageGCHandle.Free(); + m_keypressGCHandle.Free(); + m_commandGCHandle.Free(); + m_alertGCHandle.Free(); + m_menuGCHandle.Free(); + m_sourceActivatedGCHandle.Free(); + } + protected: // managed callback methods int CecLogMessageManaged(const CEC::cec_log_message &message) { - int iReturn(0); - if (m_bHasCallbacks) - iReturn = m_callbacks->ReceiveLogMessage(gcnew CecLogMessage(gcnew System::String(message.message), (CecLogLevel)message.level, message.time)); - return iReturn; + try { + ReceiveLogMessage(gcnew CecLogMessage(gcnew System::String(message.message), (CecLogLevel)message.level, message.time)); + } catch (...) {} + return 0; } int CecKeyPressManaged(const CEC::cec_keypress &key) { - int iReturn(0); - if (m_bHasCallbacks) - iReturn = m_callbacks->ReceiveKeypress(gcnew CecKeypress((CecUserControlCode)key.keycode, key.duration)); - return iReturn; + try { + ReceiveKeypress(gcnew CecKeypress((CecUserControlCode)key.keycode, key.duration)); + } catch (...) {} + return 0; } int CecCommandManaged(const CEC::cec_command &command) { - int iReturn(0); - if (m_bHasCallbacks) - { - CecCommand ^ newCommand = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout); + try { + CecCommand^ newCommand = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout); for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++) newCommand->Parameters->PushBack(command.parameters[iPtr]); - iReturn = m_callbacks->ReceiveCommand(newCommand); + return ReceiveCommand(newCommand); } - return iReturn; + catch (...) {} + return 0; } int CecConfigManaged(const CEC::libcec_configuration &config) { - int iReturn(0); - if (m_bHasCallbacks) - { - LibCECConfiguration ^netConfig = gcnew LibCECConfiguration(); + try { + LibCECConfiguration^ netConfig = gcnew LibCECConfiguration(); netConfig->Update(config); - iReturn = m_callbacks->ConfigurationChanged(netConfig); + return ConfigurationChanged(netConfig); } - return iReturn; + catch (...) {} + return 0; } int CecAlertManaged(const CEC::libcec_alert alert, const CEC::libcec_parameter &data) { - int iReturn(0); - if (m_bHasCallbacks) - { + try { CecParameterType newType = (CecParameterType)data.paramType; if (newType == CecParameterType::ParameterTypeString) { - 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); + System::String^ newData = gcnew System::String(data.paramData ? (const char*)data.paramData : "", 0, 128); + CecParameter^ newParam = gcnew CecParameter(newType, newData); + return ReceiveAlert((CecAlert)alert, newParam); } } - return iReturn; + catch (...) {} + return 0; } int CecMenuManaged(const CEC::cec_menu_state newVal) { - int iReturn(0); - if (m_bHasCallbacks) - { - iReturn = m_callbacks->ReceiveMenuStateChange((CecMenuState)newVal); + try { + return ReceiveMenuStateChange((CecMenuState)newVal); } - return iReturn; + catch (...) {} + return 0; } void CecSourceActivatedManaged(const CEC::cec_logical_address logicalAddress, const uint8_t bActivated) { - if (m_bHasCallbacks) - m_callbacks->SourceActivated((CecLogicalAddress)logicalAddress, bActivated == 1); - } - - void DestroyDelegates() - { - m_bHasCallbacks = false; - if (m_bDelegatesCreated) - { - m_bDelegatesCreated = false; - m_logMessageGCHandle.Free(); - m_keypressGCHandle.Free(); - m_commandGCHandle.Free(); - m_alertGCHandle.Free(); - m_menuGCHandle.Free(); - m_sourceActivatedGCHandle.Free(); - } - } - - void CreateDelegates() - { - DestroyDelegates(); - - if (!m_bDelegatesCreated) - { - msclr::interop::marshal_context ^ context = gcnew msclr::interop::marshal_context(); - - // create the delegate method for the log message callback - m_logMessageDelegate = gcnew CecLogMessageManagedDelegate(this, &CecCallbackMethods::CecLogMessageManaged); - m_logMessageGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_logMessageDelegate); - m_logMessageCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer()); - - // create the delegate method for the keypress callback - m_keypressDelegate = gcnew CecKeyPressManagedDelegate(this, &CecCallbackMethods::CecKeyPressManaged); - m_keypressGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_keypressDelegate); - m_keypressCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer()); - - // create the delegate method for the command callback - m_commandDelegate = gcnew CecCommandManagedDelegate(this, &CecCallbackMethods::CecCommandManaged); - m_commandGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_commandDelegate); - m_commandCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer()); - - // create the delegate method for the configuration change callback - m_configDelegate = gcnew CecConfigManagedDelegate(this, &CecCallbackMethods::CecConfigManaged); - m_configGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_configDelegate); - m_configCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_configDelegate).ToPointer()); - - // create the delegate method for the alert callback - m_alertDelegate = gcnew CecAlertManagedDelegate(this, &CecCallbackMethods::CecAlertManaged); - m_alertGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_alertDelegate); - m_alertCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_alertDelegate).ToPointer()); - - // create the delegate method for the menu callback - m_menuDelegate = gcnew CecMenuManagedDelegate(this, &CecCallbackMethods::CecMenuManaged); - m_menuGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_menuDelegate); - m_menuCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_menuDelegate).ToPointer()); - - // create the delegate method for the source activated callback - m_sourceActivatedDelegate = gcnew CecSourceActivatedManagedDelegate(this, &CecCallbackMethods::CecSourceActivatedManaged); - m_sourceActivatedGCHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_sourceActivatedDelegate); - m_sourceActivatedCallback = static_cast(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(m_sourceActivatedDelegate).ToPointer()); - - delete context; - - UnmanagedCecCallbacks unmanagedCallbacks; - unmanagedCallbacks.logCB = m_logMessageCallback; - unmanagedCallbacks.keyCB = m_keypressCallback; - unmanagedCallbacks.commandCB = m_commandCallback; - unmanagedCallbacks.configCB = m_configCallback; - unmanagedCallbacks.alertCB = m_alertCallback; - unmanagedCallbacks.menuCB = m_menuCallback; - unmanagedCallbacks.sourceActivatedCB = m_sourceActivatedCallback; - - P8PLATFORM::CLockObject lock(g_callbackMutex); - g_unmanagedCallbacks.push_back(unmanagedCallbacks); - m_iCallbackPtr = g_unmanagedCallbacks.size() - 1; - m_bDelegatesCreated = true; + try { + SourceActivated((CecLogicalAddress)logicalAddress, bActivated == 1); } + catch (...) {} } CecLogMessageManagedDelegate ^ m_logMessageDelegate; static System::Runtime::InteropServices::GCHandle m_logMessageGCHandle; - LOGCB m_logMessageCallback; CecKeyPressManagedDelegate ^ m_keypressDelegate; static System::Runtime::InteropServices::GCHandle m_keypressGCHandle; - KEYCB m_keypressCallback; CecCommandManagedDelegate ^ m_commandDelegate; static System::Runtime::InteropServices::GCHandle m_commandGCHandle; - COMMANDCB m_commandCallback; CecConfigManagedDelegate ^ m_configDelegate; static System::Runtime::InteropServices::GCHandle m_configGCHandle; - CONFIGCB m_configCallback; CecAlertManagedDelegate ^ m_alertDelegate; static System::Runtime::InteropServices::GCHandle m_alertGCHandle; - ALERTCB m_alertCallback; CecMenuManagedDelegate ^ m_menuDelegate; static System::Runtime::InteropServices::GCHandle m_menuGCHandle; - MENUCB m_menuCallback; CecSourceActivatedManagedDelegate ^ m_sourceActivatedDelegate; static System::Runtime::InteropServices::GCHandle m_sourceActivatedGCHandle; - ACTICB m_sourceActivatedCallback; - CecCallbackMethods ^ m_callbacks; - bool m_bHasCallbacks; - bool m_bDelegatesCreated; - size_t m_iCallbackPtr; + void* m_unmanagedCallbacks; }; } diff --git a/src/dotnetlib/CecSharpTypesUnmanaged.h b/src/dotnetlib/CecSharpTypesUnmanaged.h new file mode 100644 index 00000000..53ff9bd6 --- /dev/null +++ b/src/dotnetlib/CecSharpTypesUnmanaged.h @@ -0,0 +1,204 @@ +#pragma once +/* +* This file is part of the libCEC(R) library. +* +* libCEC(R) is Copyright (C) 2011-2020 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 +* http://www.pulse-eight.com/ +* http://www.pulse-eight.net/ +* +* Author: Lars Op den Kamp +* +*/ + +#include "p8-platform/threads/mutex.h" +#include +#include +#include "../../include/cec.h" +#include + +#using + +/// +/// LibCecSharp namespace +/// +/// +namespace CecSharp +{ +#pragma unmanaged + struct UnmanagedCecCallbacks; + + static P8PLATFORM::CMutex g_callbackMutex; + static std::vector g_unmanagedCallbacks; + static CEC::ICECCallbacks g_cecCallbacks; + + // unmanaged callback methods + typedef void (__stdcall *LOGCB) (const CEC::cec_log_message* message); + typedef void (__stdcall *KEYCB) (const CEC::cec_keypress* key); + typedef void (__stdcall *COMMANDCB)(const CEC::cec_command* command); + typedef void (__stdcall *CONFIGCB) (const CEC::libcec_configuration* config); + typedef void (__stdcall *ALERTCB) (const CEC::libcec_alert, const CEC::libcec_parameter &data); + typedef int (__stdcall *MENUCB) (const CEC::cec_menu_state newVal); + typedef void (__stdcall *ACTICB) (const CEC::cec_logical_address logicalAddress, const uint8_t bActivated); + + /// + /// libCEC callback methods. Unmanaged code. + /// + struct UnmanagedCecCallbacks + { + /// + /// Log message callback + /// + LOGCB logCB; + /// + /// Key press/release callback + /// + KEYCB keyCB; + /// + /// Raw CEC data callback + /// + COMMANDCB commandCB; + /// + /// Updated configuration callback + /// + CONFIGCB configCB; + /// + /// Alert message callback + /// + ALERTCB alertCB; + /// + /// Menu status change callback + /// + MENUCB menuCB; + /// + /// Source (de)activated callback + /// + ACTICB sourceActivatedCB; + }; + + /// + /// Called by libCEC to send back a log message to the application + /// + /// Pointer to the callback struct + /// The log message + static void CecLogMessageCB(void* cbParam, const CEC::cec_log_message* message) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->logCB) + cb->logCB(message); + } + + /// + /// Called by libCEC to send back a key press or release to the application + /// + /// Pointer to the callback struct + /// The key press command that libCEC received + static void CecKeyPressCB(void* cbParam, const CEC::cec_keypress* key) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->keyCB) + cb->keyCB(key); + } + + /// + /// Called by libCEC to send back raw CEC data to the application + /// + /// Pointer to the callback struct + /// The raw CEC data + static void CecCommandCB(void* cbParam, const CEC::cec_command* command) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->commandCB) + cb->commandCB(command); + } + + /// + /// Called by libCEC to send back an updated configuration to the application + /// + /// Pointer to the callback struct + /// The new configuration + static void CecConfigCB(void* cbParam, const CEC::libcec_configuration* config) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->configCB) + cb->configCB(config); + } + + /// + /// Called by libCEC to send back an alert message to the application + /// + /// Pointer to the callback struct + /// The alert message + static void CecAlertCB(void* cbParam, const CEC::libcec_alert alert, const CEC::libcec_parameter data) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->alertCB) + cb->alertCB(alert, data); + } + + /// + /// Called by libCEC to send back a menu state change to the application + /// + /// Pointer to the callback struct + /// The new menu state + /// 1 when handled, 0 otherwise + static int CecMenuCB(void* cbParam, const CEC::cec_menu_state newVal) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->menuCB) + return cb->menuCB(newVal); + return 0; + } + + /// + /// Called by libCEC to notify the application that the source that is handled by libCEC was (de)activated + /// + /// Pointer to the callback struct + /// The logical address that was (de)activated + /// True when activated, false when deactivated + static void CecSourceActivatedCB(void* cbParam, const CEC::cec_logical_address logicalAddress, const uint8_t activated) + { + struct UnmanagedCecCallbacks* cb = static_cast(cbParam); + if (!!cb && !!cb->sourceActivatedCB) + cb->sourceActivatedCB(logicalAddress, activated); + } + + /// + /// Assign the callback methods in the g_cecCallbacks struct and return a pointer to it + /// + static CEC::ICECCallbacks* GetLibCecCallbacks() + { + g_cecCallbacks.logMessage = CecLogMessageCB; + g_cecCallbacks.keyPress = CecKeyPressCB; + g_cecCallbacks.commandReceived = CecCommandCB; + g_cecCallbacks.configurationChanged = CecConfigCB; + g_cecCallbacks.alert = CecAlertCB; + g_cecCallbacks.menuStateChanged = CecMenuCB; + g_cecCallbacks.sourceActivated = CecSourceActivatedCB; + return &g_cecCallbacks; + } +#pragma managed +} diff --git a/src/dotnetlib/LibCecSharp/LibCecSharp.cpp b/src/dotnetlib/LibCecSharp.cpp similarity index 77% rename from src/dotnetlib/LibCecSharp/LibCecSharp.cpp rename to src/dotnetlib/LibCecSharp.cpp index 590a893d..59ac8f8b 100644 --- a/src/dotnetlib/LibCecSharp/LibCecSharp.cpp +++ b/src/dotnetlib/LibCecSharp.cpp @@ -1,7 +1,7 @@ /* * 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 Copyright (C) 2011-2020 Pulse-Eight Limited. All rights reserved. * libCEC(R) is an original work, containing original code. * * libCEC(R) is a trademark of Pulse-Eight Limited. @@ -28,6 +28,9 @@ * Pulse-Eight Licensing * http://www.pulse-eight.com/ * http://www.pulse-eight.net/ +* +* Author: Lars Op den Kamp +* */ #include "CecSharpTypes.h" @@ -50,25 +53,30 @@ namespace CecSharp /// to the application via callback methods. The callback methods can be /// found in CecSharpTypes.h, CecCallbackMethods. /// - public ref class LibCecSharp : public CecCallbackMethods + public ref class LibCecSharp { public: /// /// Create a new LibCecSharp instance. /// /// The configuration to pass to libCEC. - LibCecSharp(LibCECConfiguration ^config) + LibCecSharp(CecCallbackMethods^ callbacks, LibCECConfiguration^ config) { - m_callbacks = config->Callbacks; - CecCallbackMethods::EnableCallbacks(m_callbacks); - if (!InitialiseLibCec(config)) + marshal_context^ context = gcnew marshal_context(); + libcec_configuration libCecConfig; + m_callbacks = callbacks; + ConvertConfiguration(context, config, libCecConfig); + m_libCec = (ICECAdapter*)CECInitialise(&libCecConfig); + if (!m_libCec) throw gcnew Exception("Could not initialise LibCecSharp"); + + config->Update(libCecConfig); + delete context; } ~LibCecSharp(void) { - Close(); - m_libCec = NULL; + Destroy(); } /// @@ -102,8 +110,8 @@ namespace CecSharp /// True when a connection was opened, false otherwise. bool Open(String ^ strPort, int iTimeoutMs) { - CecCallbackMethods::EnableCallbacks(m_callbacks); - EnableCallbacks(m_callbacks); + if (!m_libCec) + return false; marshal_context ^ context = gcnew marshal_context(); const char* strPortC = context->marshal_as(strPort); bool bReturn = m_libCec->Open(strPortC, iTimeoutMs); @@ -116,32 +124,32 @@ namespace CecSharp /// void Close(void) { - DisableCallbacks(); - m_libCec->Close(); + if (!!m_libCec) + m_libCec->Close(); } - /// - /// Disable all calls to callback methods. - /// - virtual void DisableCallbacks(void) override + void EnableCallbacks(void) { - // delete the callbacks, since these might already have been destroyed in .NET - CecCallbackMethods::DisableCallbacks(); - if (m_libCec) - m_libCec->EnableCallbacks(NULL, NULL); + if (!!m_libCec) + { +#if CEC_LIB_VERSION_MAJOR >= 5 + m_libCec->SetCallbacks(GetLibCecCallbacks(), m_callbacks->Get()); +#else + m_libCec->EnableCallbacks(m_callbacks->Get(), GetLibCecCallbacks()); +#endif + } } - /// - /// Enable or change the callback methods that libCEC uses to send changes to the client application. - /// - /// The new callback methods to use. - /// True when the callbacks were changed, false otherwise - virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override + void DisableCallbacks(void) { - if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks)) - return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks); - - return false; + if (!!m_libCec) + { +#if CEC_LIB_VERSION_MAJOR >= 5 + m_libCec->DisableCallbacks(); +#else + m_libCec->EnableCallbacks(nullptr, nullptr); +#endif + } } /// @@ -150,7 +158,7 @@ namespace CecSharp /// True when the ping was successful, false otherwise bool PingAdapter(void) { - return m_libCec->PingAdapter(); + return !!m_libCec && m_libCec->PingAdapter(); } /// @@ -159,7 +167,7 @@ namespace CecSharp /// True when the command was sent successfully, false otherwise. bool StartBootloader(void) { - return m_libCec->StartBootloader(); + return !!m_libCec && m_libCec->StartBootloader(); } /// @@ -169,6 +177,9 @@ namespace CecSharp /// True when the data was sent and acked, false otherwise. bool Transmit(CecCommand ^ command) { + if (!m_libCec) { + return false; + } cec_command ccommand; cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode); ccommand.transmit_timeout = command->TransmitTimeout; @@ -187,7 +198,7 @@ namespace CecSharp /// True when the logical address was set successfully, false otherwise. bool SetLogicalAddress(CecLogicalAddress logicalAddress) { - return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress); + return !!m_libCec && m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress); } /// @@ -197,7 +208,7 @@ namespace CecSharp /// True when the physical address was set successfully, false otherwise. bool SetPhysicalAddress(uint16_t physicalAddress) { - return m_libCec->SetPhysicalAddress(physicalAddress); + return !!m_libCec && m_libCec->SetPhysicalAddress(physicalAddress); } /// @@ -207,7 +218,7 @@ namespace CecSharp /// True when the command was sent successfully, false otherwise. bool PowerOnDevices(CecLogicalAddress logicalAddress) { - return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress); + return !!m_libCec && m_libCec->PowerOnDevices((cec_logical_address) logicalAddress); } /// @@ -217,7 +228,7 @@ namespace CecSharp /// True when the command was sent successfully, false otherwise. bool StandbyDevices(CecLogicalAddress logicalAddress) { - return m_libCec->StandbyDevices((cec_logical_address) logicalAddress); + return !!m_libCec && m_libCec->StandbyDevices((cec_logical_address) logicalAddress); } /// @@ -227,7 +238,7 @@ namespace CecSharp /// True if the POLL was acked, false otherwise. bool PollDevice(CecLogicalAddress logicalAddress) { - return m_libCec->PollDevice((cec_logical_address) logicalAddress); + return !!m_libCec && m_libCec->PollDevice((cec_logical_address) logicalAddress); } /// @@ -237,7 +248,7 @@ namespace CecSharp /// True when the command was sent successfully, false otherwise. bool SetActiveSource(CecDeviceType type) { - return m_libCec->SetActiveSource((cec_device_type) type); + return !!m_libCec && m_libCec->SetActiveSource((cec_device_type) type); } /// @@ -248,7 +259,7 @@ namespace CecSharp /// True if set, false otherwise. bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate) { - return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate); + return !!m_libCec && m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate); } /// @@ -259,7 +270,7 @@ namespace CecSharp /// True if set, false otherwise. bool SetDeckInfo(CecDeckInfo info, bool sendUpdate) { - return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate); + return !!m_libCec && m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate); } /// @@ -268,7 +279,7 @@ namespace CecSharp /// True when the command was sent successfully, false otherwise. bool SetInactiveView(void) { - return m_libCec->SetInactiveView(); + return !!m_libCec && m_libCec->SetInactiveView(); } /// @@ -279,7 +290,7 @@ namespace CecSharp /// True if set, false otherwise. bool SetMenuState(CecMenuState state, bool sendUpdate) { - return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate); + return !!m_libCec && m_libCec->SetMenuState((cec_menu_state) state, sendUpdate); } /// @@ -291,6 +302,9 @@ namespace CecSharp /// True when the command was sent, false otherwise. bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message) { + if (!m_libCec) { + return false; + } marshal_context ^ context = gcnew marshal_context(); const char* strMessageC = context->marshal_as(message); @@ -307,7 +321,7 @@ namespace CecSharp /// True when switched successfully, false otherwise. bool SwitchMonitoring(bool enable) { - return m_libCec->SwitchMonitoring(enable); + return !!m_libCec && m_libCec->SwitchMonitoring(enable); } /// @@ -317,6 +331,9 @@ namespace CecSharp /// The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched. CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress) { + if (!m_libCec) { + return CecVersion::Unknown; + } return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress); } @@ -327,7 +344,10 @@ namespace CecSharp /// The requested menu language. String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress) { - std::string strLang = m_libCec->GetDeviceMenuLanguage((cec_logical_address)logicalAddress); + if (!m_libCec) { + return gcnew String("not connected"); + } + std::string strLang = m_libCec->GetDeviceMenuLanguage((cec_logical_address)logicalAddress); return gcnew String(strLang.c_str()); } @@ -338,6 +358,9 @@ namespace CecSharp /// The vendor ID or 0 if it wasn't found. CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress) { + if (!m_libCec) { + return CecVendorId::Unknown; + } return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress); } @@ -348,6 +371,9 @@ namespace CecSharp /// The power status or CEC_POWER_STATUS_UNKNOWN if it wasn't found. CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress) { + if (!m_libCec) { + return CecPowerStatus::Unknown; + } return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress); } @@ -356,7 +382,9 @@ namespace CecSharp /// void RescanActiveDevices(void) { - m_libCec->RescanActiveDevices(); + if (!!m_libCec) { + m_libCec->RescanActiveDevices(); + } } /// @@ -366,6 +394,9 @@ namespace CecSharp CecLogicalAddresses ^ GetActiveDevices(void) { CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses(); + if (!m_libCec) { + return retVal; + } unsigned int iDevices = 0; cec_logical_addresses activeDevices = m_libCec->GetActiveDevices(); @@ -384,7 +415,7 @@ namespace CecSharp /// True when active, false otherwise. bool IsActiveDevice(CecLogicalAddress logicalAddress) { - return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); + return !!m_libCec && m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); } /// @@ -394,7 +425,7 @@ namespace CecSharp /// True when active, false otherwise. bool IsActiveDeviceType(CecDeviceType type) { - return m_libCec->IsActiveDeviceType((cec_device_type)type); + return !!m_libCec && m_libCec->IsActiveDeviceType((cec_device_type)type); } /// @@ -405,7 +436,7 @@ namespace CecSharp /// True when changed, false otherwise. bool SetHDMIPort(CecLogicalAddress address, uint8_t port) { - return m_libCec->SetHDMIPort((cec_logical_address)address, port); + return !!m_libCec && m_libCec->SetHDMIPort((cec_logical_address)address, port); } /// @@ -415,6 +446,9 @@ namespace CecSharp /// The new audio status. uint8_t VolumeUp(bool sendRelease) { + if (!m_libCec) { + return 0; + } return m_libCec->VolumeUp(sendRelease); } @@ -425,6 +459,9 @@ namespace CecSharp /// The new audio status. uint8_t VolumeDown(bool sendRelease) { + if (!m_libCec) { + return 0; + } return m_libCec->VolumeDown(sendRelease); } @@ -434,6 +471,9 @@ namespace CecSharp /// The new audio status. uint8_t MuteAudio() { + if (!m_libCec) { + return 0; + } return m_libCec->AudioToggleMute(); } @@ -446,7 +486,7 @@ namespace CecSharp /// True when the keypress was acked, false otherwise. bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait) { - return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait); + return !!m_libCec && m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait); } /// @@ -457,7 +497,7 @@ namespace CecSharp /// True when the key release was acked, false otherwise. bool SendKeyRelease(CecLogicalAddress destination, bool wait) { - return m_libCec->SendKeyRelease((cec_logical_address)destination, wait); + return !!m_libCec && m_libCec->SendKeyRelease((cec_logical_address)destination, wait); } /// @@ -467,10 +507,13 @@ namespace CecSharp /// The OSD name. String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress) { + if (!m_libCec) { + return gcnew String("disconnected"); + } std::string osdName = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress); // we need to terminate with \0, and we only got 14 chars in osd.name char strOsdName[15]; - strncpy(strOsdName, osdName.c_str(), 15); + strncpy_s(strOsdName, osdName.c_str(), 15); return gcnew String(strOsdName); } @@ -480,6 +523,9 @@ namespace CecSharp /// The active source or CECDEVICE_UNKNOWN when unknown. CecLogicalAddress GetActiveSource() { + if (!m_libCec) { + return CecLogicalAddress::Unknown; + } return (CecLogicalAddress)m_libCec->GetActiveSource(); } @@ -490,7 +536,7 @@ namespace CecSharp /// True when it is the active source, false otherwise. bool IsActiveSource(CecLogicalAddress logicalAddress) { - return m_libCec->IsActiveSource((cec_logical_address)logicalAddress); + return !!m_libCec && m_libCec->IsActiveSource((cec_logical_address)logicalAddress); } /// @@ -500,6 +546,9 @@ namespace CecSharp /// The physical address or 0 if it wasn't found. uint16_t GetDevicePhysicalAddress(CecLogicalAddress address) { + if (!m_libCec) { + return 0xFFFF; + } return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address); } @@ -510,7 +559,7 @@ namespace CecSharp /// True when the command was sent, false otherwise. bool SetStreamPath(CecLogicalAddress address) { - return m_libCec->SetStreamPath((cec_logical_address)address); + return !!m_libCec && m_libCec->SetStreamPath((cec_logical_address)address); } /// @@ -520,7 +569,7 @@ namespace CecSharp /// True when the command was sent, false otherwise. bool SetStreamPath(uint16_t physicalAddress) { - return m_libCec->SetStreamPath(physicalAddress); + return !!m_libCec && m_libCec->SetStreamPath(physicalAddress); } /// @@ -530,6 +579,9 @@ namespace CecSharp CecLogicalAddresses ^GetLogicalAddresses(void) { CecLogicalAddresses ^addr = gcnew CecLogicalAddresses(); + if (!m_libCec) { + return addr; + } cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses(); for (unsigned int iPtr = 0; iPtr < 16; iPtr++) addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr]; @@ -544,6 +596,9 @@ namespace CecSharp /// True when the configuration was updated, false otherwise. bool GetCurrentConfiguration(LibCECConfiguration ^configuration) { + if (!m_libCec) { + return false; + } libcec_configuration config; config.Clear(); @@ -556,41 +611,43 @@ namespace CecSharp } /// - /// Check whether the CEC adapter can persist a configuration. + /// Check whether the CEC adapter can save a configuration. /// - /// True when this CEC adapter can persist the user configuration, false otherwise. + /// True when this CEC adapter can save the user configuration, false otherwise. +#if CEC_LIB_VERSION_MAJOR >= 5 + bool CanSaveConfiguration(void) + { + return !!m_libCec && + m_libCec->CanSaveConfiguration(); + } +#else bool CanPersistConfiguration(void) { - return m_libCec->CanPersistConfiguration(); + return !!m_libCec && + m_libCec->CanPersistConfiguration(); } - /// - /// Persist the given configuration in adapter (if supported) - /// - /// The configuration to store. - /// True when the configuration was persisted, false otherwise. bool PersistConfiguration(LibCECConfiguration ^configuration) { - marshal_context ^ context = gcnew marshal_context(); - libcec_configuration config; - ConvertConfiguration(context, configuration, config); - - bool bReturn = m_libCec->PersistConfiguration(&config); - - delete context; - return bReturn; + return SetConfiguration(configuration); } +#endif /// - /// Change libCEC's configuration. + /// Change libCEC's configuration. Store it updated settings in the eeprom of the device (if supported) /// /// The new configuration. /// True when the configuration was changed successfully, false otherwise. bool SetConfiguration(LibCECConfiguration ^configuration) { + if (!m_libCec) { + return false; + } marshal_context ^ context = gcnew marshal_context(); libcec_configuration config; ConvertConfiguration(context, configuration, config); + // don't update callbacks + config.callbacks = NULL; bool bReturn = m_libCec->SetConfiguration(&config); @@ -604,7 +661,7 @@ namespace CecSharp /// True when libCEC is the active source on the bus, false otherwise. bool IsLibCECActiveSource() { - return m_libCec->IsLibCECActiveSource(); + return !!m_libCec && m_libCec->IsLibCECActiveSource(); } /// @@ -616,6 +673,9 @@ namespace CecSharp /// True when the device was found, false otherwise bool GetDeviceInformation(String ^ port, LibCECConfiguration ^configuration, uint32_t timeoutMs) { + if (!m_libCec) { + return false; + } bool bReturn(false); marshal_context ^ context = gcnew marshal_context(); @@ -636,77 +696,113 @@ namespace CecSharp String ^ ToString(CecLogicalAddress iAddress) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_logical_address)iAddress); return gcnew String(retVal); } String ^ ToString(CecVendorId iVendorId) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId); return gcnew String(retVal); } String ^ ToString(CecVersion iVersion) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_version)iVersion); return gcnew String(retVal); } String ^ ToString(CecPowerStatus iState) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_power_status)iState); return gcnew String(retVal); } String ^ ToString(CecMenuState iState) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_menu_state)iState); return gcnew String(retVal); } String ^ ToString(CecDeckControlMode iMode) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode); return gcnew String(retVal); } String ^ ToString(CecDeckInfo status) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_deck_info)status); return gcnew String(retVal); } String ^ ToString(CecOpcode opcode) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_opcode)opcode); return gcnew String(retVal); } String ^ ToString(CecSystemAudioStatus mode) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_system_audio_status)mode); return gcnew String(retVal); } String ^ ToString(CecAudioStatus status) { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->ToString((cec_audio_status)status); return gcnew String(retVal); } String ^ VersionToString(uint32_t version) { + if (!m_libCec) { + return gcnew String("disconnected"); + } char buf[20]; m_libCec->PrintVersion(version, buf, 20); return gcnew String(buf); } - String ^ PhysicalAddressToString(uint16_t physicalAddress) - { - char buf[8]; - snprintf(buf, 8, "%X.%X.%X.%X", (physicalAddress >> 12) & 0xF, (physicalAddress >> 8) & 0xF, (physicalAddress >> 4) & 0xF, physicalAddress & 0xF); - return gcnew String(buf); - } + String^ PhysicalAddressToString(uint16_t physicalAddress) + { + if (!m_libCec) { + return gcnew String("disconnected"); + } + char buf[8]; + _snprintf_s(buf, 8, "%X.%X.%X.%X", (physicalAddress >> 12) & 0xF, (physicalAddress >> 8) & 0xF, (physicalAddress >> 4) & 0xF, physicalAddress & 0xF); + return gcnew String(buf); + } /// /// Get a string with information about how libCEC was compiled. @@ -714,6 +810,9 @@ namespace CecSharp /// A string with information about how libCEC was compiled. String ^ GetLibInfo() { + if (!m_libCec) { + return gcnew String("disconnected"); + } const char *retVal = m_libCec->GetLibInfo(); return gcnew String(retVal); } @@ -727,8 +826,22 @@ namespace CecSharp /// Should be called as first call to libCEC, directly after CECInitialise() and before using Open() void InitVideoStandalone() { - m_libCec->InitVideoStandalone(); + if (!!m_libCec) { + m_libCec->InitVideoStandalone(); + } + } + +#if CEC_LIB_VERSION_MAJOR >= 5 + /// + /// Get statistics about traffic on the CEC line + /// + /// The requested statistics + CecAdapterStats ^GetStats(void) + { + struct cec_adapter_stats cstats; + return gcnew CecAdapterStats((!!m_libCec && m_libCec->GetStats(&cstats)) ? &cstats : NULL); } +#endif /// /// Get the (virtual) USB vendor id @@ -736,6 +849,9 @@ namespace CecSharp /// The (virtual) USB vendor id uint16_t GetAdapterVendorId() { + if (!m_libCec) { + return 0; + } return m_libCec->GetAdapterVendorId(); } @@ -745,27 +861,24 @@ namespace CecSharp /// The (virtual) USB product id uint16_t GetAdapterProductId() { + if (!m_libCec) { + return 0; + } return m_libCec->GetAdapterProductId(); } - private: + protected: !LibCecSharp(void) { - Close(); - m_libCec = NULL; + Destroy(); } - bool InitialiseLibCec(LibCECConfiguration ^config) + private: + void Destroy(void) { - marshal_context ^ context = gcnew marshal_context(); - libcec_configuration libCecConfig; - ConvertConfiguration(context, config, libCecConfig); - - m_libCec = (ICECAdapter *) CECInitialise(&libCecConfig); - config->Update(libCecConfig); - - delete context; - return m_libCec != NULL; + Close(); + m_callbacks->Destroy(); + m_libCec = NULL; } void ConvertConfiguration(marshal_context ^context, LibCECConfiguration ^netConfig, CEC::libcec_configuration &config) @@ -777,14 +890,24 @@ namespace CecSharp for (unsigned int iPtr = 0; iPtr < 5; iPtr++) config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr]; - config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0; - config.iPhysicalAddress = netConfig->PhysicalAddress; - config.baseDevice = (cec_logical_address)netConfig->BaseDevice; - config.iHDMIPort = netConfig->HDMIPort; - config.clientVersion = netConfig->ClientVersion; - config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0; - config.bActivateSource = netConfig->ActivateSource ? 1 : 0; - config.tvVendor = (cec_vendor_id)netConfig->TvVendor; + config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0; + config.iPhysicalAddress = netConfig->PhysicalAddress; + config.baseDevice = (cec_logical_address)netConfig->BaseDevice; + config.iHDMIPort = netConfig->HDMIPort; + config.clientVersion = netConfig->ClientVersion; + config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0; + config.bActivateSource = netConfig->ActivateSource ? 1 : 0; + config.tvVendor = (cec_vendor_id)netConfig->TvVendor; + config.comboKey = (cec_user_control_code)netConfig->ComboKey; + config.iComboKeyTimeoutMs = netConfig->ComboKeyTimeoutMs; + config.iButtonRepeatRateMs = netConfig->ButtonRepeatRateMs; + config.iButtonReleaseDelayMs = netConfig->ButtonReleaseDelayMs; + config.iDoubleTapTimeoutMs = netConfig->DoubleTapTimeoutMs; + config.bAutoWakeAVR = netConfig->AutoWakeAVR ? 1 : 0; +#if CEC_LIB_VERSION_MAJOR >= 5 + config.bAutoPowerOn = (uint8_t)netConfig->AutoPowerOn; +#endif + config.wakeDevices.Clear(); for (int iPtr = 0; iPtr < 16; iPtr++) { @@ -802,11 +925,12 @@ namespace CecSharp memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3); config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0; config.cecVersion = (cec_version)netConfig->CECVersion; - config.callbacks = &g_cecCallbacks; - } + config.callbacks = GetLibCecCallbacks(); + config.callbackParam = m_callbacks->Get(); + } - ICECAdapter * m_libCec; + ICECAdapter* m_libCec; CecCallbackMethods ^ m_callbacks; }; } diff --git a/src/dotnetlib/LibCecSharp/.gitignore b/src/dotnetlib/LibCecSharp/.gitignore index 18f55fdd..97a6b300 100644 --- a/src/dotnetlib/LibCecSharp/.gitignore +++ b/src/dotnetlib/LibCecSharp/.gitignore @@ -1,6 +1,7 @@ AssemblyInfo.cpp -project/*.user -project/.vs -project/Release -project/Debug -project/x64 \ No newline at end of file +*.vcxproj.user +*.aps +.vs +Release +Debug +x64 \ No newline at end of file diff --git a/src/dotnetlib/LibCecSharp/project/LibCecSharp.rc.in b/src/dotnetlib/LibCecSharp/LibCecSharp.rc.in similarity index 100% rename from src/dotnetlib/LibCecSharp/project/LibCecSharp.rc.in rename to src/dotnetlib/LibCecSharp/LibCecSharp.rc.in diff --git a/src/dotnetlib/LibCecSharp/project/LibCecSharp.vcxproj b/src/dotnetlib/LibCecSharp/LibCecSharp.vcxproj similarity index 97% rename from src/dotnetlib/LibCecSharp/project/LibCecSharp.vcxproj rename to src/dotnetlib/LibCecSharp/LibCecSharp.vcxproj index 394d24fe..d3574550 100644 --- a/src/dotnetlib/LibCecSharp/project/LibCecSharp.vcxproj +++ b/src/dotnetlib/LibCecSharp/LibCecSharp.vcxproj @@ -193,14 +193,15 @@ - + - - - - + + + + + diff --git a/src/dotnetlib/LibCecSharp/project/LibCecSharp.vcxproj.filters b/src/dotnetlib/LibCecSharp/LibCecSharp.vcxproj.filters similarity index 76% rename from src/dotnetlib/LibCecSharp/project/LibCecSharp.vcxproj.filters rename to src/dotnetlib/LibCecSharp/LibCecSharp.vcxproj.filters index 903f6f4e..e2d03b30 100644 --- a/src/dotnetlib/LibCecSharp/project/LibCecSharp.vcxproj.filters +++ b/src/dotnetlib/LibCecSharp/LibCecSharp.vcxproj.filters @@ -11,7 +11,7 @@ - + Source Files @@ -19,16 +19,19 @@ - + Header Files - + Header Files - + Header Files - + + Header Files + + Header Files diff --git a/src/dotnetlib/LibCecSharp/project/resource.h b/src/dotnetlib/LibCecSharp/resource.h similarity index 100% rename from src/dotnetlib/LibCecSharp/project/resource.h rename to src/dotnetlib/LibCecSharp/resource.h diff --git a/src/dotnetlib/LibCecSharpCore/.gitignore b/src/dotnetlib/LibCecSharpCore/.gitignore index 18f55fdd..deec40e6 100644 --- a/src/dotnetlib/LibCecSharpCore/.gitignore +++ b/src/dotnetlib/LibCecSharpCore/.gitignore @@ -1,6 +1,6 @@ AssemblyInfo.cpp -project/*.user -project/.vs -project/Release -project/Debug -project/x64 \ No newline at end of file +*.vcxproj.user +.vs +Release +Debug +x64 \ No newline at end of file diff --git a/src/dotnetlib/LibCecSharpCore/AssemblyInfo.cpp.in b/src/dotnetlib/LibCecSharpCore/AssemblyInfo.cpp.in index 0cc3bc39..9c5d8230 100644 --- a/src/dotnetlib/LibCecSharpCore/AssemblyInfo.cpp.in +++ b/src/dotnetlib/LibCecSharpCore/AssemblyInfo.cpp.in @@ -1,5 +1,3 @@ -#include "pch.h" - using namespace System; using namespace System::Reflection; using namespace System::Runtime::CompilerServices; diff --git a/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.cpp b/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.cpp deleted file mode 100644 index 911b30ca..00000000 --- a/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.cpp +++ /dev/null @@ -1,783 +0,0 @@ -#include "pch.h" - -#include "LibCecSharpCore.h" -#include "CecSharpTypes.h" -#using - -using namespace System; -using namespace System::Runtime::InteropServices; -using namespace CEC; -using namespace msclr::interop; - -namespace CecSharp -{ - /// - /// Create a LibCecSharp instance and pass the configuration as argument. - /// Then call Open() to open a connection to the adapter. Close() closes the - /// connection. - /// - /// libCEC can send commands to other devices on the CEC bus via the methods - /// on this interface, and all commands that libCEC received are sent back - /// to the application via callback methods. The callback methods can be - /// found in CecSharpTypes.h, CecCallbackMethods. - /// - public ref class LibCecSharp : public CecCallbackMethods - { - public: - /// - /// Create a new LibCecSharp instance. - /// - /// The configuration to pass to libCEC. - LibCecSharp(LibCECConfiguration^ config) - { - m_callbacks = config->Callbacks; - CecCallbackMethods::EnableCallbacks(m_callbacks); - if (!InitialiseLibCec(config)) - throw gcnew Exception("Could not initialise LibCecSharp"); - } - - ~LibCecSharp(void) - { - Close(); - m_libCec = NULL; - } - - /// - /// Try to find all connected CEC adapters. - /// - /// The path filter for adapters. Leave empty to return all adapters. - /// The adapters that were found. - array^ FindAdapters(String^ path) - { - cec_adapter_descriptor* devices = new cec_adapter_descriptor[10]; - - marshal_context^ context = gcnew marshal_context(); - const char* strPathC = path->Length > 0 ? context->marshal_as(path) : NULL; - - uint8_t iDevicesFound = m_libCec->DetectAdapters(devices, 10, NULL, false); - - array^ adapters = gcnew array(iDevicesFound); - for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++) - adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].strComPath), gcnew String(devices[iPtr].strComName), devices[iPtr].iVendorId, devices[iPtr].iProductId, devices[iPtr].iFirmwareVersion, devices[iPtr].iFirmwareBuildDate, devices[iPtr].iPhysicalAddress); - - delete devices; - delete context; - return adapters; - } - - /// - /// Open a connection to the CEC adapter. - /// - /// The COM port of the adapter - /// Connection timeout in milliseconds - /// True when a connection was opened, false otherwise. - bool Open(String^ strPort, int iTimeoutMs) - { - CecCallbackMethods::EnableCallbacks(m_callbacks); - EnableCallbacks(m_callbacks); - marshal_context^ context = gcnew marshal_context(); - const char* strPortC = context->marshal_as(strPort); - bool bReturn = m_libCec->Open(strPortC, iTimeoutMs); - delete context; - return bReturn; - } - - /// - /// Close the connection to the CEC adapter - /// - void Close(void) - { - DisableCallbacks(); - m_libCec->Close(); - } - - /// - /// Disable all calls to callback methods. - /// - virtual void DisableCallbacks(void) override - { - // delete the callbacks, since these might already have been destroyed in .NET - CecCallbackMethods::DisableCallbacks(); - if (m_libCec) - m_libCec->EnableCallbacks(NULL, NULL); - } - - /// - /// Enable or change the callback methods that libCEC uses to send changes to the client application. - /// - /// The new callback methods to use. - /// True when the callbacks were changed, false otherwise - virtual bool EnableCallbacks(CecCallbackMethods^ callbacks) override - { - if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks)) - return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks); - - return false; - } - - /// - /// Sends a ping command to the adapter, to check if it's responding. - /// - /// True when the ping was successful, false otherwise - bool PingAdapter(void) - { - return m_libCec->PingAdapter(); - } - - /// - /// Start the bootloader of the CEC adapter. Closes the connection when successful. - /// - /// True when the command was sent successfully, false otherwise. - bool StartBootloader(void) - { - return m_libCec->StartBootloader(); - } - - /// - /// Transmit a raw CEC command over the CEC line. - /// - /// The command to transmit - /// True when the data was sent and acked, false otherwise. - bool Transmit(CecCommand^ command) - { - cec_command ccommand; - cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode); - ccommand.transmit_timeout = command->TransmitTimeout; - ccommand.eom = command->Eom; - ccommand.ack = command->Ack; - for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++) - ccommand.parameters.PushBack(command->Parameters->Data[iPtr]); - - return m_libCec->Transmit(ccommand); - } - - /// - /// Change the logical address on the CEC bus of the CEC adapter. libCEC automatically assigns a logical address, and this method is only available for debugging purposes. - /// - /// The CEC adapter's new logical address. - /// True when the logical address was set successfully, false otherwise. - bool SetLogicalAddress(CecLogicalAddress logicalAddress) - { - return m_libCec->SetLogicalAddress((cec_logical_address)logicalAddress); - } - - /// - /// Change the physical address (HDMI port) of the CEC adapter. libCEC will try to autodetect the physical address when connecting. If it did, it's set in libcec_configuration. - /// - /// The CEC adapter's new physical address. - /// True when the physical address was set successfully, false otherwise. - bool SetPhysicalAddress(uint16_t physicalAddress) - { - return m_libCec->SetPhysicalAddress(physicalAddress); - } - - /// - /// Power on the given CEC capable devices. If CECDEVICE_BROADCAST is used, then wakeDevice in libcec_configuration will be used. - /// - /// The logical address to power on. - /// True when the command was sent successfully, false otherwise. - bool PowerOnDevices(CecLogicalAddress logicalAddress) - { - return m_libCec->PowerOnDevices((cec_logical_address)logicalAddress); - } - - /// - /// Put the given CEC capable devices in standby mode. If CECDEVICE_BROADCAST is used, then standbyDevices in libcec_configuration will be used. - /// - /// The logical address of the device to put in standby. - /// True when the command was sent successfully, false otherwise. - bool StandbyDevices(CecLogicalAddress logicalAddress) - { - return m_libCec->StandbyDevices((cec_logical_address)logicalAddress); - } - - /// - /// Sends a POLL message to a device, to check if it's present and responding. - /// - /// The device to send the message to. - /// True if the POLL was acked, false otherwise. - bool PollDevice(CecLogicalAddress logicalAddress) - { - return m_libCec->PollDevice((cec_logical_address)logicalAddress); - } - - /// - /// Change the active source to a device type handled by libCEC. Use CEC_DEVICE_TYPE_RESERVED to make the default type used by libCEC active. - /// - /// The new active source. Use CEC_DEVICE_TYPE_RESERVED to use the primary type - /// True when the command was sent successfully, false otherwise. - bool SetActiveSource(CecDeviceType type) - { - return m_libCec->SetActiveSource((cec_device_type)type); - } - - /// - /// Change the deck control mode, if this adapter is registered as playback or recording device. - /// - /// The new control mode. - /// True to send the new status over the CEC line. - /// True if set, false otherwise. - bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate) - { - return m_libCec->SetDeckControlMode((cec_deck_control_mode)mode, sendUpdate); - } - - /// - /// Change the deck info, if this adapter is a playback or recording device. - /// - /// The new deck info. - /// True to send the new status over the CEC line. - /// True if set, false otherwise. - bool SetDeckInfo(CecDeckInfo info, bool sendUpdate) - { - return m_libCec->SetDeckInfo((cec_deck_info)info, sendUpdate); - } - - /// - /// Broadcast a message that notifies connected CEC capable devices that this device is no longer the active source. - /// - /// True when the command was sent successfully, false otherwise. - bool SetInactiveView(void) - { - return m_libCec->SetInactiveView(); - } - - /// - /// Change the menu state. This value is already changed by libCEC automatically if a device is (de)activated. - /// - /// The new state. - /// True to send the new status over the CEC line. - /// True if set, false otherwise. - bool SetMenuState(CecMenuState state, bool sendUpdate) - { - return m_libCec->SetMenuState((cec_menu_state)state, sendUpdate); - } - - /// - /// Display a message on the device with the given logical address. Not supported by most TVs. - /// - /// The logical address of the device to display the message on. - /// The duration of the message - /// The message to display. - /// True when the command was sent, false otherwise. - bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String^ message) - { - marshal_context^ context = gcnew marshal_context(); - const char* strMessageC = context->marshal_as(message); - - bool bReturn = m_libCec->SetOSDString((cec_logical_address)logicalAddress, (cec_display_control)duration, strMessageC); - - delete context; - return bReturn; - } - - /// - /// Enable or disable monitoring mode, for debugging purposes. If monitoring mode is enabled, libCEC won't respond to any command, but only log incoming data. - /// - /// True to enable, false to disable. - /// True when switched successfully, false otherwise. - bool SwitchMonitoring(bool enable) - { - return m_libCec->SwitchMonitoring(enable); - } - - /// - /// Get the CEC version of the device with the given logical address - /// - /// The logical address of the device to get the CEC version for. - /// The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched. - CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress) - { - return (CecVersion)m_libCec->GetDeviceCecVersion((cec_logical_address)logicalAddress); - } - - /// - /// Get the menu language of the device with the given logical address - /// - /// The logical address of the device to get the menu language for. - /// The requested menu language. - String^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress) - { - std::string strLang = m_libCec->GetDeviceMenuLanguage((cec_logical_address)logicalAddress); - return gcnew String(strLang.c_str()); - } - - /// - /// Get the vendor ID of the device with the given logical address. - /// - /// The logical address of the device to get the vendor ID for. - /// The vendor ID or 0 if it wasn't found. - CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress) - { - return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address)logicalAddress); - } - - /// - /// Get the power status of the device with the given logical address. - /// - /// The logical address of the device to get the power status for. - /// The power status or CEC_POWER_STATUS_UNKNOWN if it wasn't found. - CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress) - { - return (CecPowerStatus)m_libCec->GetDevicePowerStatus((cec_logical_address)logicalAddress); - } - - /// - /// Tell libCEC to poll for active devices on the bus. - /// - void RescanActiveDevices(void) - { - m_libCec->RescanActiveDevices(); - } - - /// - /// Get the logical addresses of the devices that are active on the bus, including those handled by libCEC. - /// - /// The logical addresses of the active devices - CecLogicalAddresses^ GetActiveDevices(void) - { - CecLogicalAddresses^ retVal = gcnew CecLogicalAddresses(); - unsigned int iDevices = 0; - - cec_logical_addresses activeDevices = m_libCec->GetActiveDevices(); - - for (uint8_t iPtr = 0; iPtr < 16; iPtr++) - if (activeDevices[iPtr]) - retVal->Set((CecLogicalAddress)iPtr); - - return retVal; - } - - /// - /// Check whether a device is active on the bus. - /// - /// The address to check. - /// True when active, false otherwise. - bool IsActiveDevice(CecLogicalAddress logicalAddress) - { - return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); - } - - /// - /// Check whether a device of the given type is active on the bus. - /// - /// The type to check. - /// True when active, false otherwise. - bool IsActiveDeviceType(CecDeviceType type) - { - return m_libCec->IsActiveDeviceType((cec_device_type)type); - } - - /// - /// Changes the active HDMI port. - /// - /// The device to which this libCEC is connected. - /// The new port number. - /// True when changed, false otherwise. - bool SetHDMIPort(CecLogicalAddress address, uint8_t port) - { - return m_libCec->SetHDMIPort((cec_logical_address)address, port); - } - - /// - /// Sends a volume up keypress to an audiosystem if it's present. - /// - /// Send a key release after the keypress. - /// The new audio status. - uint8_t VolumeUp(bool sendRelease) - { - return m_libCec->VolumeUp(sendRelease); - } - - /// - /// Sends a volume down keypress to an audiosystem if it's present. - /// - /// Send a key release after the keypress. - /// The new audio status. - uint8_t VolumeDown(bool sendRelease) - { - return m_libCec->VolumeDown(sendRelease); - } - - /// - /// Sends a mute keypress to an audiosystem if it's present. - /// - /// The new audio status. - uint8_t MuteAudio() - { - return m_libCec->AudioToggleMute(); - } - - /// - /// Send a keypress to a device on the CEC bus. - /// - /// The logical address of the device to send the message to. - /// The key to send. - /// True to wait for a response, false otherwise. - /// True when the keypress was acked, false otherwise. - bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait) - { - return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait); - } - - /// - /// Send a key release to a device on the CEC bus. - /// - /// The logical address of the device to send the message to. - /// True to wait for a response, false otherwise. - /// True when the key release was acked, false otherwise. - bool SendKeyRelease(CecLogicalAddress destination, bool wait) - { - return m_libCec->SendKeyRelease((cec_logical_address)destination, wait); - } - - /// - /// Get the OSD name of a device on the CEC bus. - /// - /// The logical address of the device to get the OSD name for. - /// The OSD name. - String^ GetDeviceOSDName(CecLogicalAddress logicalAddress) - { - std::string osdName = m_libCec->GetDeviceOSDName((cec_logical_address)logicalAddress); - // we need to terminate with \0, and we only got 14 chars in osd.name - char strOsdName[15]; - strncpy(strOsdName, osdName.c_str(), 15); - return gcnew String(strOsdName); - } - - /// - /// Get the logical address of the device that is currently the active source on the CEC bus. - /// - /// The active source or CECDEVICE_UNKNOWN when unknown. - CecLogicalAddress GetActiveSource() - { - return (CecLogicalAddress)m_libCec->GetActiveSource(); - } - - /// - /// Check whether a device is currently the active source on the CEC bus. - /// - /// The logical address of the device to check. - /// True when it is the active source, false otherwise. - bool IsActiveSource(CecLogicalAddress logicalAddress) - { - return m_libCec->IsActiveSource((cec_logical_address)logicalAddress); - } - - /// - /// Get the physical address of the device with the given logical address. - /// - /// The logical address of the device to get the physical address for. - /// The physical address or 0 if it wasn't found. - uint16_t GetDevicePhysicalAddress(CecLogicalAddress address) - { - return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address); - } - - /// - /// Sets the stream path to the device on the given logical address. - /// - /// The address to activate. - /// True when the command was sent, false otherwise. - bool SetStreamPath(CecLogicalAddress address) - { - return m_libCec->SetStreamPath((cec_logical_address)address); - } - - /// - /// Sets the stream path to the device on the given physical address. - /// - /// The address to activate. - /// True when the command was sent, false otherwise. - bool SetStreamPath(uint16_t physicalAddress) - { - return m_libCec->SetStreamPath(physicalAddress); - } - - /// - /// Get the list of logical addresses that libCEC is controlling - /// - /// The list of logical addresses that libCEC is controlling - CecLogicalAddresses^ GetLogicalAddresses(void) - { - CecLogicalAddresses^ addr = gcnew CecLogicalAddresses(); - cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses(); - for (unsigned int iPtr = 0; iPtr < 16; iPtr++) - addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr]; - addr->Primary = (CecLogicalAddress)libAddr.primary; - return addr; - } - - /// - /// Get libCEC's current configuration. - /// - /// The configuration. - /// True when the configuration was updated, false otherwise. - bool GetCurrentConfiguration(LibCECConfiguration^ configuration) - { - libcec_configuration config; - config.Clear(); - - if (m_libCec->GetCurrentConfiguration(&config)) - { - configuration->Update(config); - return true; - } - return false; - } - - /// - /// Check whether the CEC adapter can persist a configuration. - /// - /// True when this CEC adapter can persist the user configuration, false otherwise. - bool CanPersistConfiguration(void) - { - return m_libCec->CanPersistConfiguration(); - } - - /// - /// Persist the given configuration in adapter (if supported) - /// - /// The configuration to store. - /// True when the configuration was persisted, false otherwise. - bool PersistConfiguration(LibCECConfiguration^ configuration) - { - marshal_context^ context = gcnew marshal_context(); - libcec_configuration config; - ConvertConfiguration(context, configuration, config); - - bool bReturn = m_libCec->PersistConfiguration(&config); - - delete context; - return bReturn; - } - - /// - /// Change libCEC's configuration. - /// - /// The new configuration. - /// True when the configuration was changed successfully, false otherwise. - bool SetConfiguration(LibCECConfiguration^ configuration) - { - marshal_context^ context = gcnew marshal_context(); - libcec_configuration config; - ConvertConfiguration(context, configuration, config); - - bool bReturn = m_libCec->SetConfiguration(&config); - - delete context; - return bReturn; - } - - /// - /// Check whether libCEC is the active source on the bus. - /// - /// True when libCEC is the active source on the bus, false otherwise. - bool IsLibCECActiveSource() - { - return m_libCec->IsLibCECActiveSource(); - } - - /// - /// Get information about the given CEC adapter. - /// - /// The COM port to which the device is connected - /// The device configuration - /// The timeout in milliseconds - /// True when the device was found, false otherwise - bool GetDeviceInformation(String^ port, LibCECConfiguration^ configuration, uint32_t timeoutMs) - { - bool bReturn(false); - marshal_context^ context = gcnew marshal_context(); - - libcec_configuration config; - config.Clear(); - - const char* strPortC = port->Length > 0 ? context->marshal_as(port) : NULL; - - if (m_libCec->GetDeviceInformation(strPortC, &config, timeoutMs)) - { - configuration->Update(config); - bReturn = true; - } - - delete context; - return bReturn; - } - - String^ ToString(CecLogicalAddress iAddress) - { - const char* retVal = m_libCec->ToString((cec_logical_address)iAddress); - return gcnew String(retVal); - } - - String^ ToString(CecVendorId iVendorId) - { - const char* retVal = m_libCec->ToString((cec_vendor_id)iVendorId); - return gcnew String(retVal); - } - - String^ ToString(CecVersion iVersion) - { - const char* retVal = m_libCec->ToString((cec_version)iVersion); - return gcnew String(retVal); - } - - String^ ToString(CecPowerStatus iState) - { - const char* retVal = m_libCec->ToString((cec_power_status)iState); - return gcnew String(retVal); - } - - String^ ToString(CecMenuState iState) - { - const char* retVal = m_libCec->ToString((cec_menu_state)iState); - return gcnew String(retVal); - } - - String^ ToString(CecDeckControlMode iMode) - { - const char* retVal = m_libCec->ToString((cec_deck_control_mode)iMode); - return gcnew String(retVal); - } - - String^ ToString(CecDeckInfo status) - { - const char* retVal = m_libCec->ToString((cec_deck_info)status); - return gcnew String(retVal); - } - - String^ ToString(CecOpcode opcode) - { - const char* retVal = m_libCec->ToString((cec_opcode)opcode); - return gcnew String(retVal); - } - - String^ ToString(CecSystemAudioStatus mode) - { - const char* retVal = m_libCec->ToString((cec_system_audio_status)mode); - return gcnew String(retVal); - } - - String^ ToString(CecAudioStatus status) - { - const char* retVal = m_libCec->ToString((cec_audio_status)status); - return gcnew String(retVal); - } - - String^ VersionToString(uint32_t version) - { - char buf[20]; - m_libCec->PrintVersion(version, buf, 20); - return gcnew String(buf); - } - - String^ PhysicalAddressToString(uint16_t physicalAddress) - { - char buf[8]; - snprintf(buf, 8, "%X.%X.%X.%X", (physicalAddress >> 12) & 0xF, (physicalAddress >> 8) & 0xF, (physicalAddress >> 4) & 0xF, physicalAddress & 0xF); - return gcnew String(buf); - } - - /// - /// Get a string with information about how libCEC was compiled. - /// - /// A string with information about how libCEC was compiled. - String^ GetLibInfo() - { - const char* retVal = m_libCec->GetLibInfo(); - return gcnew String(retVal); - } - - /// - /// Calling this method will initialise the host on which libCEC is running. - /// On the RPi, it calls bcm_host_init(), which may only be called once per process, and is called by any process using - /// the video api on that system. So only call this method if libCEC is used in an application that - /// does not already initialise the video api. - /// - /// Should be called as first call to libCEC, directly after CECInitialise() and before using Open() - void InitVideoStandalone() - { - m_libCec->InitVideoStandalone(); - } - - /// - /// Get the (virtual) USB vendor id - /// - /// The (virtual) USB vendor id - uint16_t GetAdapterVendorId() - { - return m_libCec->GetAdapterVendorId(); - } - - /// - /// Get the (virtual) USB product id - /// - /// The (virtual) USB product id - uint16_t GetAdapterProductId() - { - return m_libCec->GetAdapterProductId(); - } - - private: - !LibCecSharp(void) - { - Close(); - m_libCec = NULL; - } - - bool InitialiseLibCec(LibCECConfiguration^ config) - { - marshal_context^ context = gcnew marshal_context(); - libcec_configuration libCecConfig; - ConvertConfiguration(context, config, libCecConfig); - - m_libCec = (ICECAdapter*)CECInitialise(&libCecConfig); - config->Update(libCecConfig); - - delete context; - return m_libCec != NULL; - } - - void ConvertConfiguration(marshal_context^ context, LibCECConfiguration^ netConfig, CEC::libcec_configuration& config) - { - config.Clear(); - - const char* strDeviceName = context->marshal_as(netConfig->DeviceName); - memcpy_s(config.strDeviceName, 13, strDeviceName, 13); - for (unsigned int iPtr = 0; iPtr < 5; iPtr++) - config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr]; - - config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0; - config.iPhysicalAddress = netConfig->PhysicalAddress; - config.baseDevice = (cec_logical_address)netConfig->BaseDevice; - config.iHDMIPort = netConfig->HDMIPort; - config.clientVersion = netConfig->ClientVersion; - config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0; - config.bActivateSource = netConfig->ActivateSource ? 1 : 0; - config.tvVendor = (cec_vendor_id)netConfig->TvVendor; - config.wakeDevices.Clear(); - for (int iPtr = 0; iPtr < 16; iPtr++) - { - if (netConfig->WakeDevices->IsSet((CecLogicalAddress)iPtr)) - config.wakeDevices.Set((cec_logical_address)iPtr); - } - config.powerOffDevices.Clear(); - for (int iPtr = 0; iPtr < 16; iPtr++) - { - if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr)) - config.powerOffDevices.Set((cec_logical_address)iPtr); - } - config.bPowerOffOnStandby = netConfig->PowerOffOnStandby ? 1 : 0; - const char* strDeviceLanguage = context->marshal_as(netConfig->DeviceLanguage); - memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3); - config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0; - config.cecVersion = (cec_version)netConfig->CECVersion; - config.callbacks = &g_cecCallbacks; - } - - - ICECAdapter* m_libCec; - CecCallbackMethods^ m_callbacks; - }; -} diff --git a/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.h b/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.h deleted file mode 100644 index f446616c..00000000 --- a/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -//using namespace System; -// -//namespace LibCecSharpUWP { -// public ref class Class1 -// { -// // TODO: Add your methods for this class here. -// }; -//} diff --git a/src/dotnetlib/LibCecSharpCore/project/LibCecSharpCore.vcxproj b/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.vcxproj similarity index 85% rename from src/dotnetlib/LibCecSharpCore/project/LibCecSharpCore.vcxproj rename to src/dotnetlib/LibCecSharpCore/LibCecSharpCore.vcxproj index 16c5bfc1..5efce721 100644 --- a/src/dotnetlib/LibCecSharpCore/project/LibCecSharpCore.vcxproj +++ b/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.vcxproj @@ -91,8 +91,7 @@ - Use - pch.h + Level3 WIN32;NDEBUG;%(PreprocessorDefinitions) $(SolutionDir)..\include;$(SolutionDir)..\src;$(SolutionDir)..\src\dotnetlib;%(AdditionalIncludeDirectories) @@ -104,8 +103,7 @@ - Use - pch.h + Level3 WIN32;_HAS_ITERATOR_DEBUGGING=0;_DEBUG;%(PreprocessorDefinitions) $(SolutionDir)..\include;$(SolutionDir)..\src;$(SolutionDir)..\src\dotnetlib;%(AdditionalIncludeDirectories) @@ -116,8 +114,7 @@ - Use - pch.h + Level3 _DEBUG;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions) $(SolutionDir)..\include;$(SolutionDir)..\src;$(SolutionDir)..\src\dotnetlib;%(AdditionalIncludeDirectories) @@ -128,8 +125,7 @@ - Use - pch.h + Level3 NDEBUG;%(PreprocessorDefinitions) $(SolutionDir)..\include;$(SolutionDir)..\src;$(SolutionDir)..\src\dotnetlib;%(AdditionalIncludeDirectories) @@ -140,29 +136,19 @@ - - - - - + + + + - - - - Create - Create - Create - Create - + + - - - diff --git a/src/dotnetlib/LibCecSharpCore/project/LibCecSharpCore.vcxproj.filters b/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.vcxproj.filters similarity index 73% rename from src/dotnetlib/LibCecSharpCore/project/LibCecSharpCore.vcxproj.filters rename to src/dotnetlib/LibCecSharpCore/LibCecSharpCore.vcxproj.filters index 97f4f781..96b34a82 100644 --- a/src/dotnetlib/LibCecSharpCore/project/LibCecSharpCore.vcxproj.filters +++ b/src/dotnetlib/LibCecSharpCore/LibCecSharpCore.vcxproj.filters @@ -15,22 +15,19 @@ - - Header Files - Header Files - + Header Files - + Header Files - + Header Files - + Header Files @@ -38,10 +35,7 @@ Source Files - - Source Files - - + Source Files @@ -50,9 +44,4 @@ Resource Files - - - Resource Files - - \ No newline at end of file diff --git a/src/dotnetlib/LibCecSharpCore/project/Resource.h b/src/dotnetlib/LibCecSharpCore/Resource.h similarity index 100% rename from src/dotnetlib/LibCecSharpCore/project/Resource.h rename to src/dotnetlib/LibCecSharpCore/Resource.h diff --git a/src/dotnetlib/LibCecSharpCore/project/app.rc b/src/dotnetlib/LibCecSharpCore/app.rc similarity index 100% rename from src/dotnetlib/LibCecSharpCore/project/app.rc rename to src/dotnetlib/LibCecSharpCore/app.rc diff --git a/src/dotnetlib/LibCecSharpCore/project/pch.cpp b/src/dotnetlib/LibCecSharpCore/project/pch.cpp deleted file mode 100644 index 64b7eef6..00000000 --- a/src/dotnetlib/LibCecSharpCore/project/pch.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// pch.cpp: source file corresponding to the pre-compiled header - -#include "pch.h" - -// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/src/dotnetlib/LibCecSharpCore/project/pch.h b/src/dotnetlib/LibCecSharpCore/project/pch.h deleted file mode 100644 index 9d715b06..00000000 --- a/src/dotnetlib/LibCecSharpCore/project/pch.h +++ /dev/null @@ -1,12 +0,0 @@ -// pch.h: This is a precompiled header file. -// Files listed below are compiled only once, improving build performance for future builds. -// This also affects IntelliSense performance, including code completion and many code browsing features. -// However, files listed here are ALL re-compiled if any one of them is updated between builds. -// Do not add files here that you will be updating frequently as this negates the performance advantage. - -#ifndef PCH_H -#define PCH_H - -// add headers that you want to pre-compile here - -#endif //PCH_H diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp index ea72091e..b4167a14 100644 --- a/src/libcec/CECClient.cpp +++ b/src/libcec/CECClient.cpp @@ -143,7 +143,7 @@ bool CCECClient::OnRegister(void) if (m_configuration.bActivateSource == 1) GetPrimaryDevice()->ActivateSource(500); - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); return true; } @@ -167,6 +167,7 @@ bool CCECClient::SetHDMIPort(const cec_logical_address iBaseDevice, const uint8_ return true; m_configuration.baseDevice = iBaseDevice; m_configuration.iHDMIPort = iPort; + m_configuration.bAutodetectAddress = 0; } LIB_CEC->AddLog(CEC_LOG_NOTICE, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice); @@ -202,7 +203,7 @@ bool CCECClient::SetHDMIPort(const cec_logical_address iBaseDevice, const uint8_ uint16_t iEepromAddress = m_processor->GetPhysicalAddressFromEeprom(); if (CLibCEC::IsValidPhysicalAddress(iEepromAddress)) { - LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the value that was persisted in the eeprom, %04X", iPhysicalAddress, iEepromAddress); + LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the value that was saved in the eeprom: %04X", iPhysicalAddress, iEepromAddress); iPhysicalAddress = iEepromAddress; bReturn = true; } @@ -223,64 +224,70 @@ bool CCECClient::SetHDMIPort(const cec_logical_address iBaseDevice, const uint8_ void CCECClient::ResetPhysicalAddress(void) { - SetPhysicalAddress(CEC_DEFAULT_PHYSICAL_ADDRESS); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "resetting HDMI port and base device to defaults"); + SetHDMIPort(CECDEVICE_TV, CEC_DEFAULT_HDMI_PORT); } -void CCECClient::SetPhysicalAddress(const libcec_configuration &configuration) +bool CCECClient::SetPhysicalAddress(const libcec_configuration &configuration) { - bool bPASet(false); - // override the physical address from configuration.iPhysicalAddress if it's set - if (!bPASet && CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress)) - bPASet = SetPhysicalAddress(configuration.iPhysicalAddress); + if (CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress) && + (configuration.iPhysicalAddress != CEC_PHYSICAL_ADDRESS_TV) && + SetPhysicalAddress(configuration.iPhysicalAddress)) + { + if (m_configuration.bAutodetectAddress == 0) + LIB_CEC->AddLog(CEC_LOG_DEBUG, "using provided physical address %04X", configuration.iPhysicalAddress); + CLockObject lock(m_mutex); + m_configuration.baseDevice = CECDEVICE_UNKNOWN; + m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; + m_configuration.iPhysicalAddress = configuration.iPhysicalAddress; + return true; + } // try to autodetect the address - if (!bPASet && m_processor->CECInitialised()) + if (AutodetectPhysicalAddress()) { - bPASet = AutodetectPhysicalAddress(); - if (bPASet) - SetDevicePhysicalAddress(m_configuration.iPhysicalAddress); - m_configuration.bAutodetectAddress = bPASet ? 1 : 0; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "using auto-detected physical address %04X", m_configuration.iPhysicalAddress); + { + CLockObject lock(m_mutex); + m_configuration.baseDevice = CECDEVICE_UNKNOWN; + m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; + m_configuration.iPhysicalAddress = configuration.iPhysicalAddress; + } + SetDevicePhysicalAddress(m_configuration.iPhysicalAddress); + return true; } // use the base device + hdmi port settings - if (!bPASet) - bPASet = SetHDMIPort(configuration.baseDevice, configuration.iHDMIPort); - - // reset to defaults if something went wrong - if (!bPASet) + if ((configuration.baseDevice != CECDEVICE_UNKNOWN) && + (configuration.iHDMIPort != CEC_HDMI_PORTNUMBER_NONE) && + SetHDMIPort(configuration.baseDevice, configuration.iHDMIPort)) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - resetting HDMI port and base device to defaults", __FUNCTION__); - m_configuration.baseDevice = CECDEVICE_UNKNOWN; - m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "using device/input physical address %04X", m_configuration.iPhysicalAddress); + return true; } + + // reset to defaults if something went wrong + ResetPhysicalAddress(); + return false; } bool CCECClient::SetPhysicalAddress(const uint16_t iPhysicalAddress) { // update the configuration - bool bChanged(true); { CLockObject lock(m_mutex); if (m_configuration.iPhysicalAddress == iPhysicalAddress) - bChanged = false; - else - m_configuration.iPhysicalAddress = iPhysicalAddress; - } - if (!bChanged) - { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "physical address unchanged (%04X)", iPhysicalAddress); - return true; + return true; + m_configuration.iPhysicalAddress = iPhysicalAddress; } - - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting physical address to '%04X'", iPhysicalAddress); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "changing physical address to %04X", iPhysicalAddress); // set the physical address for each device SetDevicePhysicalAddress(iPhysicalAddress); // and send back the updated configuration QueueConfigurationChanged(m_configuration); - return true; } @@ -310,8 +317,7 @@ void CCECClient::SetSupportedDeviceTypes(void) // set the new type list m_configuration.deviceTypes = types; - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); } bool CCECClient::AllocateLogicalAddresses(void) @@ -360,8 +366,7 @@ bool CCECClient::AllocateLogicalAddresses(void) m_configuration.logicalAddresses.Set(address); } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); return true; } @@ -477,8 +482,7 @@ bool CCECClient::ChangeDeviceType(const cec_device_type from, const cec_device_t if (!m_processor->RegisterClient(this)) return false; - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); return true; } @@ -498,9 +502,8 @@ bool CCECClient::SetLogicalAddress(const cec_logical_address iLogicalAddress) bReturn = m_processor->RegisterClient(this); - // persist the new configuration if (bReturn) - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); } return bReturn; @@ -846,7 +849,6 @@ bool CCECClient::SendKeyRelease(const cec_logical_address iDestination, bool bWa bool CCECClient::GetCurrentConfiguration(libcec_configuration &configuration) { CLockObject lock(m_mutex); - snprintf(configuration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", m_configuration.strDeviceName); configuration.deviceTypes = m_configuration.deviceTypes; configuration.bAutodetectAddress = m_configuration.bAutodetectAddress; @@ -854,7 +856,7 @@ bool CCECClient::GetCurrentConfiguration(libcec_configuration &configuration) configuration.baseDevice = m_configuration.baseDevice; configuration.iHDMIPort = m_configuration.iHDMIPort; configuration.clientVersion = m_configuration.clientVersion; - configuration.serverVersion = m_configuration.serverVersion; + configuration.serverVersion = LIBCEC_VERSION_CURRENT; configuration.tvVendor = m_configuration.tvVendor; configuration.bGetSettingsFromROM = m_configuration.bGetSettingsFromROM; configuration.bActivateSource = m_configuration.bActivateSource; @@ -871,6 +873,9 @@ bool CCECClient::GetCurrentConfiguration(libcec_configuration &configuration) configuration.iButtonRepeatRateMs = m_configuration.iButtonRepeatRateMs; configuration.iButtonReleaseDelayMs = m_configuration.iButtonReleaseDelayMs; configuration.bAutoWakeAVR = m_configuration.bAutoWakeAVR; +#if CEC_LIB_VERSION_MAJOR >= 5 + configuration.bAutoPowerOn = m_configuration.bAutoPowerOn; +#endif return true; } @@ -883,7 +888,7 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) uint16_t iPA = primary ? primary->GetCurrentPhysicalAddress() : CEC_INVALID_PHYSICAL_ADDRESS; // update the callbacks - if (configuration.callbacks) + if (!!configuration.callbacks) EnableCallbacks(configuration.callbackParam, configuration.callbacks); // update the client version @@ -908,21 +913,23 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) m_configuration.cecVersion = configuration.cecVersion; m_configuration.adapterType = configuration.adapterType; m_configuration.iDoubleTapTimeoutMs = configuration.iDoubleTapTimeoutMs; - m_configuration.deviceTypes.Add(configuration.deviceTypes[0]); + m_configuration.deviceTypes = configuration.deviceTypes; m_configuration.comboKey = configuration.comboKey; m_configuration.iComboKeyTimeoutMs = configuration.iComboKeyTimeoutMs; m_configuration.iButtonRepeatRateMs = configuration.iButtonRepeatRateMs; m_configuration.iButtonReleaseDelayMs = configuration.iButtonReleaseDelayMs; m_configuration.bAutoWakeAVR = configuration.bAutoWakeAVR; #if CEC_LIB_VERSION_MAJOR >= 5 - m_configuration.bAutoPowerOn = configuration.bAutoPowerOn; + if ((configuration.bAutoPowerOn == 0) || (configuration.bAutoPowerOn == 1)) + m_configuration.bAutoPowerOn = configuration.bAutoPowerOn; #endif } bool bNeedReinit(false); // device types - if (SetDeviceTypes(configuration.deviceTypes)) + if (m_processor->CECInitialised() && + SetDeviceTypes(configuration.deviceTypes)) { // the device type changed. just copy the rest, and re-register { @@ -933,14 +940,21 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) bNeedReinit = true; } } + else if ( + configuration.baseDevice != CECDEVICE_UNKNOWN && + configuration.iHDMIPort > 0 && + configuration.iHDMIPort <= 0xF) + { + // set the configured device+port + SetHDMIPort(configuration.baseDevice, configuration.iHDMIPort); + } else { // set the physical address SetPhysicalAddress(configuration); } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); if (!primary) primary = GetPrimaryDevice(); @@ -956,7 +970,7 @@ bool CCECClient::SetConfiguration(const libcec_configuration &configuration) primary->ActivateSource(); } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: %d:%d:%d", __FUNCTION__, DoubleTapTimeoutMS(), m_configuration.iButtonRepeatRateMs, m_configuration.iButtonReleaseDelayMs); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: double tap timeout = %ums, repeat rate = %ums, release delay = %ums", __FUNCTION__, DoubleTapTimeoutMS(), m_configuration.iButtonRepeatRateMs, m_configuration.iButtonReleaseDelayMs); return true; } @@ -1260,8 +1274,7 @@ void CCECClient::SetTVVendorOverride(const cec_vendor_id id) tv->SetVendorId((uint32_t)id); } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); } cec_vendor_id CCECClient::GetTVVendorOverride(void) @@ -1274,6 +1287,7 @@ void CCECClient::SetOSDName(const std::string &strDeviceName) { { CLockObject lock(m_mutex); + if (!strncmp(m_configuration.strDeviceName, strDeviceName.c_str(), LIBCEC_OSD_NAME_SIZE)) return; snprintf(m_configuration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", strDeviceName.c_str()); } @@ -1287,8 +1301,7 @@ void CCECClient::SetOSDName(const std::string &strDeviceName) primary->TransmitOSDName(CECDEVICE_TV, false); } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); } std::string CCECClient::GetOSDName(void) @@ -1304,8 +1317,7 @@ void CCECClient::SetWakeDevices(const cec_logical_addresses &addresses) CLockObject lock(m_mutex); m_configuration.wakeDevices = addresses; } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); } cec_logical_addresses CCECClient::GetWakeDevices(void) @@ -1316,21 +1328,22 @@ cec_logical_addresses CCECClient::GetWakeDevices(void) bool CCECClient::AutodetectPhysicalAddress(void) { - bool bPhysicalAutodetected(false); - uint16_t iPhysicalAddress = m_processor ? m_processor->GetDetectedPhysicalAddress() : CEC_INVALID_PHYSICAL_ADDRESS; - - if (CLibCEC::IsValidPhysicalAddress(iPhysicalAddress) && iPhysicalAddress != 0) + uint16_t iPhysicalAddress = !!m_processor ? + m_processor->GetDetectedPhysicalAddress() : + CEC_INVALID_PHYSICAL_ADDRESS; + CLockObject lock(m_mutex); + if (CLibCEC::IsValidPhysicalAddress(iPhysicalAddress) && + (iPhysicalAddress != CEC_PHYSICAL_ADDRESS_TV)) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - autodetected physical address '%04X'", __FUNCTION__, iPhysicalAddress); - - CLockObject lock(m_mutex); - m_configuration.iPhysicalAddress = iPhysicalAddress; - m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; - m_configuration.baseDevice = CECDEVICE_UNKNOWN; - bPhysicalAutodetected = true; + m_configuration.iPhysicalAddress = iPhysicalAddress; + m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; + m_configuration.baseDevice = CECDEVICE_UNKNOWN; + m_configuration.bAutodetectAddress = 1; + return true; } - return bPhysicalAutodetected; + m_configuration.bAutodetectAddress = 0; + return false; } void CCECClient::SetClientVersion(uint32_t version) @@ -1358,8 +1371,7 @@ bool CCECClient::SetDeviceTypes(const cec_device_type_list &deviceTypes) m_configuration.deviceTypes = deviceTypes; } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); if (bNeedReinit) LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using primary device type '%s'", __FUNCTION__, ToString(deviceTypes[0])); @@ -1415,8 +1427,7 @@ bool CCECClient::SetDevicePhysicalAddress(const uint16_t iPhysicalAddress) device->ActivateSource(); } - // persist the new configuration - PersistConfiguration(m_configuration); + SaveConfiguration(m_configuration); return true; } @@ -1510,15 +1521,15 @@ cec_logical_addresses CCECClient::GetLogicalAddresses(void) return addresses; } -bool CCECClient::CanPersistConfiguration(void) +bool CCECClient::CanSaveConfiguration(void) { - return m_processor ? m_processor->CanPersistConfiguration() : false; + return m_processor ? m_processor->CanSaveConfiguration() : false; } -bool CCECClient::PersistConfiguration(const libcec_configuration &configuration) +bool CCECClient::SaveConfiguration(const libcec_configuration &configuration) { return m_processor && IsRegistered() ? - m_processor->PersistConfiguration(configuration) : + m_processor->SaveConfiguration(configuration) : false; } @@ -1562,7 +1573,7 @@ void CCECClient::CallbackAddCommand(const cec_command &command) uint32_t CCECClient::DoubleTapTimeoutMS(void) { - CLockObject lock(m_cbMutex); + CLockObject lock(m_mutex); return m_configuration.iDoubleTapTimeoutMs; } @@ -1613,35 +1624,42 @@ void* CCECClient::Process(void) { if (m_callbackCalls.Pop(cb, 500)) { - switch (cb->m_type) + try { - case CCallbackWrap::CEC_CB_LOG_MESSAGE: - CallbackAddLog(cb->m_message); - break; - case CCallbackWrap::CEC_CB_KEY_PRESS: - CallbackAddKey(cb->m_key); - break; - case CCallbackWrap::CEC_CB_COMMAND: - AddCommand(cb->m_command); - break; - case CCallbackWrap::CEC_CB_ALERT: - CallbackAlert(cb->m_alertType, cb->m_alertParam); - break; - case CCallbackWrap::CEC_CB_CONFIGURATION: - CallbackConfigurationChanged(cb->m_config); - break; - case CCallbackWrap::CEC_CB_MENU_STATE: - cb->Report(CallbackMenuStateChanged(cb->m_menuState)); - break; - case CCallbackWrap::CEC_CB_SOURCE_ACTIVATED: - CallbackSourceActivated(cb->m_bActivated, cb->m_logicalAddress); - break; - default: - break; - } + switch (cb->m_type) + { + case CCallbackWrap::CEC_CB_LOG_MESSAGE: + CallbackAddLog(cb->m_message); + break; + case CCallbackWrap::CEC_CB_KEY_PRESS: + CallbackAddKey(cb->m_key); + break; + case CCallbackWrap::CEC_CB_COMMAND: + AddCommand(cb->m_command); + break; + case CCallbackWrap::CEC_CB_ALERT: + CallbackAlert(cb->m_alertType, cb->m_alertParam); + break; + case CCallbackWrap::CEC_CB_CONFIGURATION: + CallbackConfigurationChanged(cb->m_config); + break; + case CCallbackWrap::CEC_CB_MENU_STATE: + cb->Report(CallbackMenuStateChanged(cb->m_menuState)); + break; + case CCallbackWrap::CEC_CB_SOURCE_ACTIVATED: + CallbackSourceActivated(cb->m_bActivated, cb->m_logicalAddress); + break; + default: + break; + } - if (!cb->m_keepResult) - delete cb; + if (!cb->m_keepResult) + delete cb; + } catch (...) + { + // don't log a warning but let the app deal with this + delete cb; + } } } return NULL; @@ -1650,14 +1668,18 @@ void* CCECClient::Process(void) void CCECClient::CallbackAddKey(const cec_keypress &key) { CLockObject lock(m_cbMutex); - if (m_configuration.callbacks && !!m_configuration.callbacks->keyPress) - m_configuration.callbacks->keyPress(m_configuration.callbackParam, &key); + if (!!m_configuration.callbacks && + !!m_configuration.callbacks->keyPress) + { + m_configuration.callbacks->keyPress(m_configuration.callbackParam, &key); + } } void CCECClient::CallbackAddLog(const cec_log_message_cpp &message) { CLockObject lock(m_cbMutex); - if (m_configuration.callbacks && !!m_configuration.callbacks->logMessage) + if (!!m_configuration.callbacks && + !!m_configuration.callbacks->logMessage) { cec_log_message toClient; toClient.level = message.level; @@ -1670,24 +1692,32 @@ void CCECClient::CallbackAddLog(const cec_log_message_cpp &message) void CCECClient::CallbackConfigurationChanged(const libcec_configuration &config) { CLockObject lock(m_cbMutex); - if (m_configuration.callbacks && + if (!!m_configuration.callbacks && !!m_configuration.callbacks->configurationChanged && m_processor->CECInitialised()) + { m_configuration.callbacks->configurationChanged(m_configuration.callbackParam, &config); + } } void CCECClient::CallbackSourceActivated(bool bActivated, const cec_logical_address logicalAddress) { CLockObject lock(m_cbMutex); - if (m_configuration.callbacks && !!m_configuration.callbacks->sourceActivated) + if (!!m_configuration.callbacks && + !!m_configuration.callbacks->sourceActivated) + { m_configuration.callbacks->sourceActivated(m_configuration.callbackParam, logicalAddress, bActivated ? 1 : 0); + } } void CCECClient::CallbackAlert(const libcec_alert type, const libcec_parameter ¶m) { CLockObject lock(m_cbMutex); - if (m_configuration.callbacks && !!m_configuration.callbacks->alert) + if (!!m_configuration.callbacks && + !!m_configuration.callbacks->alert) + { m_configuration.callbacks->alert(m_configuration.callbackParam, type, param); + } } int CCECClient::CallbackMenuStateChanged(const cec_menu_state newState) @@ -1695,8 +1725,11 @@ int CCECClient::CallbackMenuStateChanged(const cec_menu_state newState) LIB_CEC->AddLog(CEC_LOG_DEBUG, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST), ToString(newState)); CLockObject lock(m_cbMutex); - if (m_configuration.callbacks && !!m_configuration.callbacks->menuStateChanged) + if (!!m_configuration.callbacks && + !!m_configuration.callbacks->menuStateChanged) + { return m_configuration.callbacks->menuStateChanged(m_configuration.callbackParam, newState); + } return 0; } diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h index ff71e848..1c23ee19 100644 --- a/src/libcec/CECClient.h +++ b/src/libcec/CECClient.h @@ -303,9 +303,9 @@ namespace CEC // configuration virtual bool GetCurrentConfiguration(libcec_configuration &configuration); virtual bool SetConfiguration(const libcec_configuration &configuration); - virtual bool CanPersistConfiguration(void); - virtual bool PersistConfiguration(const libcec_configuration &configuration); - virtual void SetPhysicalAddress(const libcec_configuration &configuration); + virtual bool CanSaveConfiguration(void); + virtual bool SaveConfiguration(const libcec_configuration &configuration); + virtual bool SetPhysicalAddress(const libcec_configuration &configuration); void QueueAddCommand(const cec_command& command); void QueueAddKey(const cec_keypress& key); diff --git a/src/libcec/CECProcessor.cpp b/src/libcec/CECProcessor.cpp index 116c153d..b6b473f6 100644 --- a/src/libcec/CECProcessor.cpp +++ b/src/libcec/CECProcessor.cpp @@ -674,22 +674,26 @@ bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator) return !device || !device->HandleReceiveFailed(); } -bool CCECProcessor::CanPersistConfiguration(void) +bool CCECProcessor::CanSaveConfiguration(void) { - return m_communication ? m_communication->GetFirmwareVersion() >= 2 : false; + return !!m_communication ? + m_communication->GetFirmwareVersion() >= 2 : + false; } -bool CCECProcessor::PersistConfiguration(const libcec_configuration &configuration) +bool CCECProcessor::SaveConfiguration(const libcec_configuration &configuration) { - libcec_configuration persistConfiguration = configuration; + libcec_configuration save_config = configuration; if (!CLibCEC::IsValidPhysicalAddress(configuration.iPhysicalAddress)) { CCECBusDevice *device = GetPrimaryDevice(); - if (device) - persistConfiguration.iPhysicalAddress = device->GetCurrentPhysicalAddress(); + if (!!device) + save_config.iPhysicalAddress = device->GetCurrentPhysicalAddress(); } - return m_communication ? m_communication->PersistConfiguration(persistConfiguration) : false; + return !!m_communication ? + m_communication->SaveConfiguration(save_config) : + false; } bool CCECProcessor::SetAutoMode(bool automode) @@ -872,7 +876,7 @@ bool CCECProcessor::RegisterClient(CECClientPtr client) } // get the configuration from the client - m_libcec->AddLog(CEC_LOG_NOTICE, "registering new CEC client - v%s", CCECTypeUtils::VersionToString(configuration.clientVersion).c_str()); + m_libcec->AddLog(CEC_LOG_DEBUG, "registering new CEC client - v%s", CCECTypeUtils::VersionToString(configuration.clientVersion).c_str()); // get the current ackmask, so we can restore it if polling fails cec_logical_addresses previousMask = GetLogicalAddresses(); @@ -880,6 +884,28 @@ bool CCECProcessor::RegisterClient(CECClientPtr client) // mark as uninitialised client->SetInitialised(false); + // get the settings from eeprom + { + libcec_configuration config; config.Clear(); + m_communication->GetConfiguration(config); + { + CLockObject lock(m_mutex); + if (configuration.bGetSettingsFromROM == 1) + { + if (!config.deviceTypes.IsEmpty()) + configuration.deviceTypes = config.deviceTypes; + if (CLibCEC::IsValidPhysicalAddress(config.iPhysicalAddress)) + configuration.iPhysicalAddress = config.iPhysicalAddress; + snprintf(configuration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", config.strDeviceName); + } +#if CEC_LIB_VERSION_MAJOR >= 5 + // always load the configured auto power on setting + configuration.bAutoPowerOn = config.bAutoPowerOn; +#endif + } + client->SetConfiguration(configuration); + } + // find logical addresses for this client if (!AllocateLogicalAddresses(client)) { @@ -888,20 +914,6 @@ bool CCECProcessor::RegisterClient(CECClientPtr client) return false; } - // get the settings from the rom - if (configuration.bGetSettingsFromROM == 1) - { - libcec_configuration config; config.Clear(); - m_communication->GetConfiguration(config); - - CLockObject lock(m_mutex); - if (!config.deviceTypes.IsEmpty()) - configuration.deviceTypes = config.deviceTypes; - if (CLibCEC::IsValidPhysicalAddress(config.iPhysicalAddress)) - configuration.iPhysicalAddress = config.iPhysicalAddress; - snprintf(configuration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", config.strDeviceName); - } - // set the firmware version and build date configuration.serverVersion = LIBCEC_VERSION_CURRENT; configuration.iFirmwareVersion = m_communication->GetFirmwareVersion(); @@ -945,7 +957,6 @@ bool CCECProcessor::RegisterClient(CECClientPtr client) // request the power status of the TV tv->RequestPowerStatus(sourceAddress, true, true); - return bReturn; } diff --git a/src/libcec/CECProcessor.h b/src/libcec/CECProcessor.h index 8b4f0e0a..1e106857 100644 --- a/src/libcec/CECProcessor.h +++ b/src/libcec/CECProcessor.h @@ -131,8 +131,8 @@ namespace CEC uint8_t GetStandardLineTimeout(void); void SetRetryLineTimeout(uint8_t iTimeout); uint8_t GetRetryLineTimeout(void); - bool CanPersistConfiguration(void); - bool PersistConfiguration(const libcec_configuration &configuration); + bool CanSaveConfiguration(void); + bool SaveConfiguration(const libcec_configuration &configuration); bool SetAutoMode(bool automode); void RescanActiveDevices(void); diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h index 60f35efb..a3e27fd9 100644 --- a/src/libcec/CECTypeUtils.h +++ b/src/libcec/CECTypeUtils.h @@ -185,6 +185,8 @@ namespace CEC return "1.3a"; case CEC_VERSION_1_4: return "1.4"; + case CEC_VERSION_2_0: + return "2.0"; default: return "unknown"; } diff --git a/src/libcec/LibCEC.cpp b/src/libcec/LibCEC.cpp index cf5de495..a814f389 100644 --- a/src/libcec/LibCEC.cpp +++ b/src/libcec/LibCEC.cpp @@ -53,7 +53,7 @@ using namespace P8PLATFORM; CLibCEC::CLibCEC(void) : m_iStartTime(GetTimeMs()), - m_client(NULL) + m_client(nullptr) { m_cec = new CCECProcessor(this); } @@ -110,7 +110,7 @@ void CLibCEC::Close(void) m_cec->Close(); } -int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */) +int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = nullptr */) { return CAdapterFactory(this).FindAdapters(deviceList, iBufSize, strDevicePath); } @@ -125,10 +125,27 @@ bool CLibCEC::PingAdapter(void) return m_client ? m_client->PingAdapter() : false; } +#if CEC_LIB_VERSION_MAJOR >= 5 +bool CLibCEC::SetCallbacks(ICECCallbacks *callbacks, void *cbParam) +{ + return !!m_client ? m_client->EnableCallbacks(cbParam, callbacks) : false; +} + +bool CLibCEC::DisableCallbacks(void) +{ + return !!m_client ? m_client->EnableCallbacks(nullptr, nullptr) : false; +} + bool CLibCEC::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks) { - return m_client ? m_client->EnableCallbacks(cbParam, callbacks) : false; + return SetCallbacks(callbacks, cbParam); } +#else +bool CLibCEC::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks) +{ + return !!m_client ? m_client->EnableCallbacks(cbParam, callbacks) : false; +} +#endif bool CLibCEC::GetCurrentConfiguration(libcec_configuration *configuration) { @@ -140,15 +157,21 @@ bool CLibCEC::SetConfiguration(const libcec_configuration *configuration) return m_client ? m_client->SetConfiguration(*configuration) : false; } +#if CEC_LIB_VERSION_MAJOR >= 5 +bool CLibCEC::CanSaveConfiguration(void) +#else bool CLibCEC::CanPersistConfiguration(void) +#endif { - return m_client ? m_client->CanPersistConfiguration() : false; + return m_client ? m_client->CanSaveConfiguration() : false; } +#if CEC_LIB_VERSION_MAJOR < 5 bool CLibCEC::PersistConfiguration(libcec_configuration *configuration) { - return m_client ? m_client->PersistConfiguration(*configuration) : false; + return SetConfiguration(configuration); } +#endif void CLibCEC::RescanActiveDevices(void) { @@ -285,6 +308,15 @@ uint8_t CLibCEC::VolumeDown(bool bSendRelease /* = true */) return m_client ? m_client->SendVolumeDown(bSendRelease) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; } +#if CEC_LIB_VERSION_MAJOR >= 5 +uint8_t CLibCEC::MuteAudio(void) +{ + return !!m_client ? + m_client->SendMuteAudio() : + (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; +} +#endif + bool CLibCEC::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = true */) { return m_client ? m_client->SendKeypress(iDestination, key, bWait) : false; @@ -422,6 +454,11 @@ CECClientPtr CLibCEC::RegisterClient(libcec_configuration &configuration) { if (!m_cec->RegisterClient(newClient)) newClient = CECClientPtr(); + else + { + // update the current configuration + newClient->GetCurrentConfiguration(configuration); + } } return newClient; @@ -430,48 +467,25 @@ CECClientPtr CLibCEC::RegisterClient(libcec_configuration &configuration) ICECAdapter* CECInitialise(libcec_configuration *configuration) { if (!configuration) - return NULL; + return nullptr; // create a new libCEC instance CLibCEC *lib = new CLibCEC; // register a new client CECClientPtr client; - if (lib && configuration) - client = lib->RegisterClient(*configuration); - - // update the current configuration - if (client) - client->GetCurrentConfiguration(*configuration); - - // ensure that the correct server version is set - configuration->serverVersion = LIBCEC_VERSION_CURRENT; - - return static_cast (lib); -} - -void * CECInit(const char *strDeviceName, CEC::cec_device_type_list types) -{ - libcec_configuration configuration; configuration.Clear(); - - // client version < 1.5.0 - snprintf(configuration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", strDeviceName); - configuration.deviceTypes = types; - configuration.iPhysicalAddress = CEC_INVALID_PHYSICAL_ADDRESS; - - if (configuration.deviceTypes.IsEmpty()) - configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE); - - return CECInitialise(&configuration); + return (!!lib && !!lib->RegisterClient(*configuration)) ? + static_cast (lib) : + nullptr; } bool CECStartBootloader(void) { bool bReturn(false); cec_adapter deviceList[1]; - if (CAdapterFactory(NULL).FindAdapters(deviceList, 1, 0) > 0) + if (CAdapterFactory(nullptr).FindAdapters(deviceList, 1, 0) > 0) { - CAdapterFactory factory(NULL); + CAdapterFactory factory(nullptr); IAdapterCommunication *comm = factory.GetInstance(deviceList[0].comm); if (comm) { @@ -560,7 +574,7 @@ uint8_t CLibCEC::AudioStatus(void) return m_client ? m_client->AudioStatus() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; } -int8_t CLibCEC::DetectAdapters(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */, bool bQuickScan /* = false */) +int8_t CLibCEC::DetectAdapters(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath /* = nullptr */, bool bQuickScan /* = false */) { int8_t iAdaptersFound = CAdapterFactory(this).DetectAdapters(deviceList, iBufSize, strDevicePath); if (!bQuickScan) @@ -604,7 +618,7 @@ cec_command CLibCEC::CommandFromString(const char* strCommand) for (std::vector::const_iterator it = splitCommand.begin(); it != splitCommand.end(); ++it) { - tmpVal = strtoul((*it).c_str(), NULL, 16); + tmpVal = strtoul((*it).c_str(), nullptr, 16); if (tmpVal <= 0xFF) retval.PushBack((uint8_t)tmpVal); } diff --git a/src/libcec/LibCEC.h b/src/libcec/LibCEC.h index 1fe3ced5..feaad337 100644 --- a/src/libcec/LibCEC.h +++ b/src/libcec/LibCEC.h @@ -63,6 +63,10 @@ namespace CEC bool Open(const char *strPort, uint32_t iTimeout = CEC_DEFAULT_CONNECT_TIMEOUT); void Close(void); +#if CEC_LIB_VERSION_MAJOR >= 5 + bool SetCallbacks(ICECCallbacks *callbacks, void *cbParam); + bool DisableCallbacks(void); +#endif bool EnableCallbacks(void *cbParam, ICECCallbacks *callbacks); int8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL); int8_t DetectAdapters(cec_adapter_descriptor *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL, bool bQuickScan = false); @@ -94,7 +98,9 @@ namespace CEC bool SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort = CEC_DEFAULT_HDMI_PORT); uint8_t VolumeUp(bool bSendRelease = true); uint8_t VolumeDown(bool bSendRelease = true); - uint8_t MuteAudio(bool bSendRelease = true); +#if CEC_LIB_VERSION_MAJOR >= 5 + uint8_t MuteAudio(void); +#endif bool SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait = true); bool SendKeyRelease(cec_logical_address iDestination, bool bWait = true); std::string GetDeviceOSDName(cec_logical_address iAddress); @@ -105,8 +111,12 @@ namespace CEC cec_logical_addresses GetLogicalAddresses(void); bool GetCurrentConfiguration(libcec_configuration *configuration); bool SetConfiguration(const libcec_configuration *configuration); +#if CEC_LIB_VERSION_MAJOR >= 5 + bool CanSaveConfiguration(void); +#else bool CanPersistConfiguration(void); bool PersistConfiguration(libcec_configuration *configuration); +#endif void RescanActiveDevices(void); bool IsLibCECActiveSource(void); diff --git a/src/libcec/LibCECC.cpp b/src/libcec/LibCECC.cpp index 7dcecdfb..549b871d 100644 --- a/src/libcec/LibCECC.cpp +++ b/src/libcec/LibCECC.cpp @@ -79,6 +79,23 @@ void libcec_clear_configuration(libcec_configuration* configuration) configuration->Clear(); } +#if CEC_LIB_VERSION_MAJOR >= 5 +int libcec_set_callbacks(libcec_connection_t connection, ICECCallbacks* callbacks, void* cbParam) +{ + ICECAdapter* adapter = static_cast(connection); + if (adapter) + return adapter->SetCallbacks(callbacks, cbParam) ? 1 : 0; + return -1; +} + +int libcec_disable_callbacks(libcec_connection_t connection) +{ + ICECAdapter* adapter = static_cast(connection); + if (adapter) + return adapter->DisableCallbacks() ? 1 : 0; + return -1; +} +#else int libcec_enable_callbacks(libcec_connection_t connection, void* cbParam, ICECCallbacks* callbacks) { ICECAdapter* adapter = static_cast(connection); @@ -86,6 +103,7 @@ int libcec_enable_callbacks(libcec_connection_t connection, void* cbParam, ICECC return adapter->EnableCallbacks(cbParam, callbacks) ? 1 : 0; return -1; } +#endif int8_t libcec_find_adapters(libcec_connection_t connection, cec_adapter* deviceList, uint8_t iBufSize, const char* strDevicePath) { @@ -324,6 +342,7 @@ int libcec_volume_down(libcec_connection_t connection, int bSendRelease) -1; } +#if CEC_LIB_VERSION_MAJOR >= 5 int libcec_mute_audio(libcec_connection_t connection, int UNUSED(bSendRelease)) { ICECAdapter* adapter = static_cast(connection); @@ -331,6 +350,7 @@ int libcec_mute_audio(libcec_connection_t connection, int UNUSED(bSendRelease)) adapter->AudioToggleMute() : -1; } +#endif int libcec_send_keypress(libcec_connection_t connection, cec_logical_address iDestination, cec_user_control_code key, int bWait) { @@ -397,6 +417,15 @@ int libcec_get_current_configuration(libcec_connection_t connection, libcec_conf -1; } +#if CEC_LIB_VERSION_MAJOR >= 5 +int libcec_can_save_configuration(libcec_connection_t connection) +{ + ICECAdapter* adapter = static_cast(connection); + return adapter ? + (adapter->CanSaveConfiguration() ? 1 : 0) : + -1; +} +#else int libcec_can_persist_configuration(libcec_connection_t connection) { ICECAdapter* adapter = static_cast(connection); @@ -404,7 +433,9 @@ int libcec_can_persist_configuration(libcec_connection_t connection) (adapter->CanPersistConfiguration() ? 1 : 0) : -1; } +#endif +#if CEC_LIB_VERSION_MAJOR < 5 int libcec_persist_configuration(libcec_connection_t connection, libcec_configuration* configuration) { ICECAdapter* adapter = static_cast(connection); @@ -412,6 +443,7 @@ int libcec_persist_configuration(libcec_connection_t connection, libcec_configur (adapter->PersistConfiguration(configuration) ? 1 : 0) : -1; } +#endif int libcec_set_configuration(libcec_connection_t connection, libcec_configuration* configuration) { diff --git a/src/libcec/SwigHelper.h b/src/libcec/SwigHelper.h index 464b7d9c..98559767 100644 --- a/src/libcec/SwigHelper.h +++ b/src/libcec/SwigHelper.h @@ -37,6 +37,7 @@ #define SWIG_PYTHON_USE_GIL #define LIBCEC_SWIG_EXPORTS +#include "env.h" #include "cectypes.h" #include "cec.h" #include "CECTypeUtils.h" @@ -56,6 +57,7 @@ namespace CEC PYTHON_CB_ALERT, PYTHON_CB_MENU_STATE, PYTHON_CB_SOURCE_ACTIVATED, + PYTHON_CB_CONFIGURATION, NB_PYTHON_CB, }; @@ -69,7 +71,8 @@ namespace CEC CCecPythonCallbacks(libcec_configuration* config) : m_configuration(config) { - assert(m_configuration); + assert(!!config); + assert(!!m_configuration); config->callbacks = new ICECCallbacks; if (!config->callbacks) @@ -78,11 +81,13 @@ namespace CEC for (size_t ptr = 0; ptr < NB_PYTHON_CB; ++ptr) m_callbacks[ptr] = NULL; - m_configuration->callbacks->logMessage = CBCecLogMessage; - m_configuration->callbacks->keyPress = CBCecKeyPress; - m_configuration->callbacks->commandReceived = CBCecCommand; - m_configuration->callbacks->menuStateChanged = CBCecMenuStateChanged; - m_configuration->callbacks->sourceActivated = CBCecSourceActivated; + m_configuration->callbacks->logMessage = CBCecLogMessage; + m_configuration->callbacks->keyPress = CBCecKeyPress; + m_configuration->callbacks->commandReceived = CBCecCommand; + m_configuration->callbacks->configurationChanged = CBCecConfigurationChanged; + m_configuration->callbacks->alert = CBCecAlert; + m_configuration->callbacks->menuStateChanged = CBCecMenuStateChanged; + m_configuration->callbacks->sourceActivated = CBCecSourceActivated; } /** @@ -110,8 +115,8 @@ namespace CEC if (callback >= NB_PYTHON_CB || !m_callbacks[callback]) return retval; - PyObject* result = NULL; - if (m_callbacks[callback]) + PyObject* result = nullptr; + if (!!m_callbacks[callback]) { /** call the callback */ result = PyEval_CallObject(m_callbacks[callback], arglist); @@ -141,7 +146,7 @@ namespace CEC assert(PyCallable_Check(pyfunc)); /** unref previous callback (if any) */ - if (m_callbacks[cb]) + if (!!m_callbacks[cb]) Py_XDECREF(m_callbacks[cb]); /** set the new callback */ @@ -153,7 +158,7 @@ namespace CEC static inline int CallPythonCallback(void* param, enum libcecSwigCallback callback, PyObject* arglist) { CCecPythonCallbacks* pCallbacks = static_cast(param); - return pCallbacks ? + return !!pCallbacks ? pCallbacks->CallPythonCallback(callback, arglist) : 0; } @@ -199,6 +204,22 @@ namespace CEC PyGILState_Release(gstate); } + static void CBCecAlert(void* param, const libcec_alert alert, const libcec_parameter cbparam) + { + PyGILState_STATE gstate = PyGILState_Ensure(); + CallPythonCallback(param, PYTHON_CB_ALERT, + Py_BuildValue("(I,I)", alert, cbparam)); + PyGILState_Release(gstate); + } + + static void CBCecConfigurationChanged(void* param, const libcec_configuration* configuration) + { + PyGILState_STATE gstate = PyGILState_Ensure(); + CallPythonCallback(param, PYTHON_CB_CONFIGURATION, + Py_BuildValue("(I)", configuration)); + PyGILState_Release(gstate); + } + PyObject* m_callbacks[NB_PYTHON_CB]; libcec_configuration* m_configuration; }; @@ -208,25 +229,27 @@ namespace CEC /** allocate callbacks struct and python callbacks if needed */ if (!self->callbackParam) self->callbackParam = new CCecPythonCallbacks(self); - + if (!self->callbackParam) + throw std::bad_alloc(); return static_cast(self->callbackParam); } } static void _SetCallback(CEC::libcec_configuration* self, size_t cb, PyObject* pyfunc) { - assert(self); + assert(!!self); CEC::CCecPythonCallbacks* pCallbacks = CEC::_GetCallbacks(self); - if (pCallbacks) + if (!!pCallbacks) pCallbacks->SetCallback(cb, pyfunc); else - printf("ERROR: cannot set callback to %p: out of memory\n", pyfunc); + throw std::bad_alloc(); } void _ClearCallbacks(CEC::libcec_configuration* self) { + assert(!!self); CEC::CCecPythonCallbacks* pCallbacks = static_cast(self->callbackParam); - if (pCallbacks) + if (!!pCallbacks) delete pCallbacks; self->callbackParam = NULL; } diff --git a/src/libcec/adapter/AOCEC/AOCECAdapterCommunication.h b/src/libcec/adapter/AOCEC/AOCECAdapterCommunication.h index 0843e381..e3d7aeb7 100644 --- a/src/libcec/adapter/AOCEC/AOCECAdapterCommunication.h +++ b/src/libcec/adapter/AOCEC/AOCECAdapterCommunication.h @@ -71,7 +71,7 @@ namespace CEC uint16_t GetFirmwareVersion(void); uint32_t GetFirmwareBuildDate(void) { return 0; } bool IsRunningLatestFirmware(void) { return true; } - bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } + bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } bool SetAutoMode(bool UNUSED(automode)) { return false; } bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } std::string GetPortName(void) { return std::string("AOCEC"); } diff --git a/src/libcec/adapter/AdapterCommunication.h b/src/libcec/adapter/AdapterCommunication.h index 8af9b227..f887d891 100644 --- a/src/libcec/adapter/AdapterCommunication.h +++ b/src/libcec/adapter/AdapterCommunication.h @@ -179,7 +179,7 @@ namespace CEC * @param configuration The configuration to store. * @return True when the configuration was persisted, false otherwise. */ - virtual bool PersistConfiguration(const libcec_configuration &configuration) = 0; + virtual bool SaveConfiguration(const libcec_configuration &configuration) = 0; /*! * @brief Enable or disable auto mode (only supported by P8 USB-CEC) diff --git a/src/libcec/adapter/Exynos/ExynosCECAdapterCommunication.h b/src/libcec/adapter/Exynos/ExynosCECAdapterCommunication.h index 8f00c7c0..990c0d11 100644 --- a/src/libcec/adapter/Exynos/ExynosCECAdapterCommunication.h +++ b/src/libcec/adapter/Exynos/ExynosCECAdapterCommunication.h @@ -69,7 +69,7 @@ namespace CEC uint16_t GetFirmwareVersion(void); uint32_t GetFirmwareBuildDate(void) { return 0; } bool IsRunningLatestFirmware(void) { return true; } - bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } + bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } bool SetAutoMode(bool UNUSED(automode)) { return false; } std::string GetPortName(void) { return std::string("EXYNOS"); } diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h index fdf21d4b..abc5cc64 100644 --- a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h +++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h @@ -73,7 +73,7 @@ namespace CEC uint16_t GetFirmwareVersion(void); uint32_t GetFirmwareBuildDate(void) { return 0; } bool IsRunningLatestFirmware(void) { return true; } - bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } + bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } bool SetAutoMode(bool UNUSED(automode)) { return false; } std::string GetPortName(void) { return std::string("IMX"); } diff --git a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h index f3519d40..57c5e26c 100644 --- a/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h +++ b/src/libcec/adapter/Linux/LinuxCECAdapterCommunication.h @@ -69,7 +69,7 @@ namespace CEC uint32_t GetFirmwareBuildDate(void) override { return 0; } bool IsRunningLatestFirmware(void) override { return true; } bool SetControlledMode(bool UNUSED(controlled)) override { return true; } - bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) override { return false; } + bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) override { return false; } bool SetAutoMode(bool UNUSED(automode)) override { return false; } bool GetConfiguration(libcec_configuration & UNUSED(configuration)) override { return false; } std::string GetPortName(void) override { return std::string("LINUX"); } diff --git a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.cpp b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.cpp index 67cc651e..b343cb87 100644 --- a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.cpp +++ b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.cpp @@ -52,14 +52,12 @@ CUSBCECAdapterCommands::CUSBCECAdapterCommands(CUSBCECAdapterCommunication *comm m_comm(comm), m_bSettingsRetrieved(false), m_bSettingAutoEnabled(false), - m_settingCecVersion(CEC_VERSION_UNKNOWN), m_iSettingLAMask(0), m_bNeedsWrite(false), - m_iBuildDate(CEC_FW_BUILD_UNKNOWN), m_bControlledMode(false), m_adapterType(P8_ADAPTERTYPE_UNKNOWN) { - m_persistedConfiguration.Clear(); + m_savedConfiguration.Clear(); } cec_datapacket CUSBCECAdapterCommands::RequestSetting(cec_adapter_messagecode msgCode) @@ -84,17 +82,17 @@ cec_datapacket CUSBCECAdapterCommands::RequestSetting(cec_adapter_messagecode ms uint16_t CUSBCECAdapterCommands::RequestFirmwareVersion(void) { - m_persistedConfiguration.iFirmwareVersion = CEC_FW_VERSION_UNKNOWN; + m_savedConfiguration.iFirmwareVersion = CEC_FW_VERSION_UNKNOWN; unsigned int iFwVersionTry(0); - while (m_persistedConfiguration.iFirmwareVersion == CEC_FW_VERSION_UNKNOWN && iFwVersionTry++ < 3) + while (m_savedConfiguration.iFirmwareVersion == CEC_FW_VERSION_UNKNOWN && iFwVersionTry++ < 3) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting the firmware version"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting the firmware version"); #endif cec_datapacket response = RequestSetting(MSGCODE_FIRMWARE_VERSION); if (response.size == 2) - m_persistedConfiguration.iFirmwareVersion = (response[0] << 8 | response[1]); + m_savedConfiguration.iFirmwareVersion = (response[0] << 8 | response[1]); else { LIB_CEC->AddLog(CEC_LOG_WARNING, "the adapter did not respond with a correct firmware version (try %d, size = %d)", iFwVersionTry, response.size); @@ -102,30 +100,30 @@ uint16_t CUSBCECAdapterCommands::RequestFirmwareVersion(void) } } - if (m_persistedConfiguration.iFirmwareVersion == CEC_FW_VERSION_UNKNOWN) + if (m_savedConfiguration.iFirmwareVersion == CEC_FW_VERSION_UNKNOWN) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "defaulting to firmware version 1"); - m_persistedConfiguration.iFirmwareVersion = 1; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: defaulting to firmware version 1"); + m_savedConfiguration.iFirmwareVersion = 1; } // firmware versions < 2 don't have an autonomous mode - if (m_persistedConfiguration.iFirmwareVersion < 2) + if (m_savedConfiguration.iFirmwareVersion < 2) m_bControlledMode = true; - return m_persistedConfiguration.iFirmwareVersion; + return m_savedConfiguration.iFirmwareVersion; } bool CUSBCECAdapterCommands::RequestSettingAutoEnabled(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting autonomous mode setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting autonomous mode setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_AUTO_ENABLED); if (response.size == 1) { m_bSettingAutoEnabled = response[0] == 1; - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted autonomous mode setting: '%s'", m_bSettingAutoEnabled ? "enabled" : "disabled"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: autonomous mode = %s", m_bSettingAutoEnabled ? "enabled" : "disabled"); return true; } return false; @@ -133,31 +131,33 @@ bool CUSBCECAdapterCommands::RequestSettingAutoEnabled(void) bool CUSBCECAdapterCommands::RequestSettingAutoPowerOn(void) { +#if CEC_LIB_VERSION_MAJOR >= 5 #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting auto power on setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting auto power on setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_AUTO_POWER_ON); if (response.size == 1) { - m_settingAutoOn = response[0]; - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using auto on setting: '%u'", m_settingAutoOn ? 1 : 0); + m_savedConfiguration.bAutoPowerOn = response[0]; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: auto power on = %s", m_savedConfiguration.bAutoPowerOn ? "enabled" : "disabled"); return true; } +#endif return false; } bool CUSBCECAdapterCommands::RequestSettingCECVersion(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting CEC version setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting CEC version setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_HDMI_VERSION); if (response.size == 1) { - m_settingCecVersion = (cec_version)response[0]; - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted CEC version setting: '%s'", ToString(m_settingCecVersion)); + m_savedConfiguration.cecVersion = (cec_version)response[0]; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: CEC version = %s", ToString(m_savedConfiguration.cecVersion)); return true; } return false; @@ -168,7 +168,7 @@ p8_cec_adapter_type CUSBCECAdapterCommands::RequestAdapterType(void) if (m_adapterType == P8_ADAPTERTYPE_UNKNOWN) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting adapter type"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting adapter type"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_ADAPTER_TYPE); @@ -180,30 +180,30 @@ p8_cec_adapter_type CUSBCECAdapterCommands::RequestAdapterType(void) uint32_t CUSBCECAdapterCommands::RequestBuildDate(void) { - if (m_iBuildDate == CEC_FW_BUILD_UNKNOWN) + if (m_savedConfiguration.iFirmwareBuildDate == CEC_FW_BUILD_UNKNOWN) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting firmware build date"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting firmware build date"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_BUILDDATE); if (response.size == 4) - m_iBuildDate = (uint32_t)response[0] << 24 | (uint32_t)response[1] << 16 | (uint32_t)response[2] << 8 | (uint32_t)response[3]; + m_savedConfiguration.iFirmwareBuildDate = (uint32_t)response[0] << 24 | (uint32_t)response[1] << 16 | (uint32_t)response[2] << 8 | (uint32_t)response[3]; } - return m_iBuildDate; + return m_savedConfiguration.iFirmwareBuildDate; } bool CUSBCECAdapterCommands::RequestSettingDefaultLogicalAddress(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting default logical address setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting default logical address setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS); if (response.size == 1) { - m_persistedConfiguration.logicalAddresses.primary = (cec_logical_address)response[0]; - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted logical address setting: '%s'", ToString(m_persistedConfiguration.logicalAddresses.primary)); + m_savedConfiguration.logicalAddresses.primary = (cec_logical_address)response[0]; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: logical address = %s", ToString(m_savedConfiguration.logicalAddresses.primary)); return true; } return false; @@ -212,32 +212,32 @@ bool CUSBCECAdapterCommands::RequestSettingDefaultLogicalAddress(void) bool CUSBCECAdapterCommands::RequestSettingDeviceType(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting device type setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting device type setting"); #endif - m_persistedConfiguration.deviceTypes.Clear(); + m_savedConfiguration.deviceTypes.Clear(); cec_datapacket response = RequestSetting(MSGCODE_GET_DEVICE_TYPE); if (response.size == 1) { - m_persistedConfiguration.deviceTypes.Add((cec_device_type)response[0]); - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted device type setting: '%s'", ToString((cec_device_type)response[0])); + m_savedConfiguration.deviceTypes.Add((cec_device_type)response[0]); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: device type = %s", ToString((cec_device_type)response[0])); return true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "no persisted device type setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: device type = (not set)"); return false; } bool CUSBCECAdapterCommands::RequestSettingLogicalAddressMask(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting logical address mask setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting logical address mask setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_LOGICAL_ADDRESS_MASK); if (response.size == 2) { m_iSettingLAMask = ((uint16_t)response[0] << 8) | ((uint16_t)response[1]); - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted logical address mask setting: '%x'", m_iSettingLAMask); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: logical address mask = %x", m_iSettingLAMask); return true; } return false; @@ -246,20 +246,20 @@ bool CUSBCECAdapterCommands::RequestSettingLogicalAddressMask(void) bool CUSBCECAdapterCommands::RequestSettingOSDName(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting OSD name setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting OSD name setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_OSD_NAME); if (response.size == 0) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "no persisted device name setting"); - m_persistedConfiguration.strDeviceName[0] = (char)0; + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: device name = (not set)"); + m_savedConfiguration.strDeviceName[0] = (char)0; return false; } - memcpy(m_persistedConfiguration.strDeviceName, response.data, response.size <= LIBCEC_OSD_NAME_SIZE ? response.size : LIBCEC_OSD_NAME_SIZE); + memcpy(m_savedConfiguration.strDeviceName, response.data, response.size <= LIBCEC_OSD_NAME_SIZE ? response.size : LIBCEC_OSD_NAME_SIZE); if (response.size < LIBCEC_OSD_NAME_SIZE) { - m_persistedConfiguration.strDeviceName[response.size] = (char)0; + m_savedConfiguration.strDeviceName[response.size] = (char)0; } return true; } @@ -267,17 +267,17 @@ bool CUSBCECAdapterCommands::RequestSettingOSDName(void) bool CUSBCECAdapterCommands::RequestSettingPhysicalAddress(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "requesting physical address setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: requesting physical address setting"); #endif cec_datapacket response = RequestSetting(MSGCODE_GET_PHYSICAL_ADDRESS); if (response.size == 2) { - m_persistedConfiguration.iPhysicalAddress = ((uint16_t)response[0] << 8) | ((uint16_t)response[1]); - LIB_CEC->AddLog(CEC_LOG_DEBUG, "using persisted physical address setting: '%4x'", m_persistedConfiguration.iPhysicalAddress); + m_savedConfiguration.iPhysicalAddress = ((uint16_t)response[0] << 8) | ((uint16_t)response[1]); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: physical address = %04x", m_savedConfiguration.iPhysicalAddress); return true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "no persisted physical address setting"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: physical address = (not set)"); return false; } @@ -293,8 +293,6 @@ bool CUSBCECAdapterCommands::SetSettingAutoEnabled(bool enabled) m_bNeedsWrite = true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "turning autonomous mode %s", enabled ? "on" : "off"); - CCECAdapterMessage params; params.PushEscaped(enabled ? 1 : 0); CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_AUTO_ENABLED, params); @@ -303,9 +301,14 @@ bool CUSBCECAdapterCommands::SetSettingAutoEnabled(bool enabled) if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updating autonomous mode: %s", enabled ? "enabled" : "disabled"); CLockObject lock(m_mutex); m_bSettingAutoEnabled = enabled; } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to %s autonomous mode", enabled ? "enable" : "disable"); + } return bReturn; } @@ -317,13 +320,11 @@ bool CUSBCECAdapterCommands::SetSettingDeviceType(cec_device_type type) /* check whether this value was changed */ { CLockObject lock(m_mutex); - if (m_persistedConfiguration.deviceTypes.types[0] == type) + if (m_savedConfiguration.deviceTypes.types[0] == type) return bReturn; m_bNeedsWrite = true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the device type to %X (previous: %X)", (uint8_t)type, (uint8_t)m_persistedConfiguration.deviceTypes.types[0]); - CCECAdapterMessage params; params.PushEscaped((uint8_t)type); CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_DEVICE_TYPE, params); @@ -332,8 +333,15 @@ bool CUSBCECAdapterCommands::SetSettingDeviceType(cec_device_type type) if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updated device type: %s -> %s", + ToString(m_savedConfiguration.deviceTypes.types[0]), + ToString(type)); CLockObject lock(m_mutex); - m_persistedConfiguration.deviceTypes.types[0] = type; + m_savedConfiguration.deviceTypes.types[0] = type; + } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to update device type to %s", ToString(type)); } return bReturn; @@ -346,13 +354,11 @@ bool CUSBCECAdapterCommands::SetSettingDefaultLogicalAddress(cec_logical_address /* check whether this value was changed */ { CLockObject lock(m_mutex); - if (m_persistedConfiguration.logicalAddresses.primary == address) + if (m_savedConfiguration.logicalAddresses.primary == address) return bReturn; m_bNeedsWrite = true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the default logical address to %X (previous: %X)", (uint8_t)address, (uint8_t)m_persistedConfiguration.logicalAddresses.primary); - CCECAdapterMessage params; params.PushEscaped((uint8_t)address); CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS, params); @@ -361,8 +367,15 @@ bool CUSBCECAdapterCommands::SetSettingDefaultLogicalAddress(cec_logical_address if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updated default logical address: %s -> %s", + ToString(m_savedConfiguration.logicalAddresses.primary), + ToString(address)); CLockObject lock(m_mutex); - m_persistedConfiguration.logicalAddresses.primary = address; + m_savedConfiguration.logicalAddresses.primary = address; + } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to update default logical address to %s", ToString(address)); } return bReturn; @@ -380,8 +393,6 @@ bool CUSBCECAdapterCommands::SetSettingLogicalAddressMask(uint16_t iMask) m_bNeedsWrite = true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the logical address mask to %2X (previous: %2X)", iMask, m_iSettingLAMask); - CCECAdapterMessage params; params.PushEscaped(iMask >> 8); params.PushEscaped((uint8_t)iMask); @@ -391,9 +402,16 @@ bool CUSBCECAdapterCommands::SetSettingLogicalAddressMask(uint16_t iMask) if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updated logical address mask: %02X -> %02X", + m_iSettingLAMask, + iMask); CLockObject lock(m_mutex); m_iSettingLAMask = iMask; } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to update logical address mask to %02X", iMask); + } return bReturn; } @@ -405,13 +423,11 @@ bool CUSBCECAdapterCommands::SetSettingPhysicalAddress(uint16_t iPhysicalAddress /* check whether this value was changed */ { CLockObject lock(m_mutex); - if (m_persistedConfiguration.iPhysicalAddress == iPhysicalAddress) + if (m_savedConfiguration.iPhysicalAddress == iPhysicalAddress) return bReturn; m_bNeedsWrite = true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the physical address to %04X (previous: %04X)", iPhysicalAddress, m_persistedConfiguration.iPhysicalAddress); - CCECAdapterMessage params; params.PushEscaped(iPhysicalAddress >> 8); params.PushEscaped((uint8_t)iPhysicalAddress); @@ -421,8 +437,15 @@ bool CUSBCECAdapterCommands::SetSettingPhysicalAddress(uint16_t iPhysicalAddress if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updated physical address: %04X -> %04X", + m_savedConfiguration.iPhysicalAddress, + iPhysicalAddress); CLockObject lock(m_mutex); - m_persistedConfiguration.iPhysicalAddress = iPhysicalAddress; + m_savedConfiguration.iPhysicalAddress = iPhysicalAddress; + } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to update physical address to %04X", iPhysicalAddress); } return bReturn; @@ -431,15 +454,15 @@ bool CUSBCECAdapterCommands::SetSettingPhysicalAddress(uint16_t iPhysicalAddress bool CUSBCECAdapterCommands::SetSettingAutoPowerOn(bool autoOn) { bool bReturn(false); - - if (m_persistedConfiguration.iFirmwareVersion < 10) +#if CEC_LIB_VERSION_MAJOR >= 5 + if (m_savedConfiguration.iFirmwareVersion < 10) // only supported by v10+ return bReturn; - /* check whether this value was changed */ + // check whether this value changed { CLockObject lock(m_mutex); - if (m_settingAutoOn == autoOn) + if ((m_savedConfiguration.bAutoPowerOn == 1) == autoOn) return bReturn; m_bNeedsWrite = true; } @@ -453,13 +476,14 @@ bool CUSBCECAdapterCommands::SetSettingAutoPowerOn(bool autoOn) if (bReturn) { CLockObject lock(m_mutex); - m_settingAutoOn = autoOn; - LIB_CEC->AddLog(CEC_LOG_WARNING, "auto power on %s", autoOn ? "enabled" : "disabled"); + m_savedConfiguration.bAutoPowerOn = (autoOn ? 1 : 0); + LIB_CEC->AddLog(CEC_LOG_NOTICE, "usbcec: auto power on %s", autoOn ? "enabled" : "disabled"); } else { - LIB_CEC->AddLog(CEC_LOG_WARNING, "failed to %s auto power on", autoOn ? "enable" : "disable"); + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to %s auto power on", autoOn ? "enable" : "disable"); } +#endif return bReturn; } @@ -471,13 +495,11 @@ bool CUSBCECAdapterCommands::SetSettingCECVersion(cec_version version) /* check whether this value was changed */ { CLockObject lock(m_mutex); - if (m_settingCecVersion == version) + if (m_savedConfiguration.cecVersion == version) return bReturn; m_bNeedsWrite = true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the CEC version to %s (previous: %s)", ToString(version), ToString(m_settingCecVersion)); - CCECAdapterMessage params; params.PushEscaped((uint8_t)version); CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_HDMI_VERSION, params); @@ -486,8 +508,15 @@ bool CUSBCECAdapterCommands::SetSettingCECVersion(cec_version version) if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updated CEC version: %s -> %s", + ToString(m_savedConfiguration.cecVersion), + ToString(version)); CLockObject lock(m_mutex); - m_settingCecVersion = version; + m_savedConfiguration.cecVersion = version; + } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to update CEC version to %s", ToString(version)); } return bReturn; @@ -498,11 +527,9 @@ bool CUSBCECAdapterCommands::SetSettingOSDName(const char *strOSDName) bool bReturn(false); /* check whether this value was changed */ - if (!strcmp(m_persistedConfiguration.strDeviceName, strOSDName)) + if (!strcmp(m_savedConfiguration.strDeviceName, strOSDName)) return bReturn; - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the OSD name to %s (previous: %s)", strOSDName, m_persistedConfiguration.strDeviceName); - CCECAdapterMessage params; for (size_t iPtr = 0; iPtr < strlen(strOSDName); iPtr++) params.PushEscaped(strOSDName[iPtr]); @@ -511,7 +538,17 @@ bool CUSBCECAdapterCommands::SetSettingOSDName(const char *strOSDName) SAFE_DELETE(message); if (bReturn) - snprintf(m_persistedConfiguration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", strOSDName); + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updated OSD name: %s -> %s", + m_savedConfiguration.strDeviceName, + strOSDName); + CLockObject lock(m_mutex); + snprintf(m_savedConfiguration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", strOSDName); + } + else + { + LIB_CEC->AddLog(CEC_LOG_WARNING, "usbcec: failed to update OSD name to %s", strOSDName); + } return bReturn; } @@ -524,8 +561,6 @@ bool CUSBCECAdapterCommands::WriteEEPROM(void) return true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "writing settings in the EEPROM"); - CCECAdapterMessage params; CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_WRITE_EEPROM, params); bool bReturn = message && message->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; @@ -533,45 +568,62 @@ bool CUSBCECAdapterCommands::WriteEEPROM(void) if (bReturn) { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: eeprom updated"); CLockObject lock(m_mutex); m_bNeedsWrite = false; } + else + { + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: failed to update eeprom"); + } return bReturn; } -bool CUSBCECAdapterCommands::PersistConfiguration(const libcec_configuration &configuration) +bool CUSBCECAdapterCommands::SaveConfiguration(const libcec_configuration &configuration) { bool bReturn(false); - if (m_persistedConfiguration.iFirmwareVersion < 2) + if (m_savedConfiguration.iFirmwareVersion < 2) return bReturn; if (!RequestSettings()) return bReturn; - bReturn |= SetSettingDeviceType(CLibCEC::GetType(configuration.logicalAddresses.primary)); - bReturn |= SetSettingDefaultLogicalAddress(configuration.logicalAddresses.primary); - bReturn |= SetSettingLogicalAddressMask(CLibCEC::GetMaskForType(configuration.logicalAddresses.primary)); + if (CLibCEC::GetType(configuration.logicalAddresses.primary) != CEC_DEVICE_TYPE_RESERVED) + { + bReturn |= SetSettingDeviceType(CLibCEC::GetType(configuration.logicalAddresses.primary)); + bReturn |= SetSettingDefaultLogicalAddress(configuration.logicalAddresses.primary); + bReturn |= SetSettingLogicalAddressMask(CLibCEC::GetMaskForType(configuration.logicalAddresses.primary)); + } + else + { + bReturn |= SetSettingDeviceType(configuration.deviceTypes[0]); + } bReturn |= SetSettingPhysicalAddress(configuration.iPhysicalAddress); bReturn |= SetSettingOSDName(configuration.strDeviceName); - if (m_persistedConfiguration.iFirmwareVersion >= 10) + if (m_savedConfiguration.iFirmwareVersion >= 10) + { #if CEC_LIB_VERSION_MAJOR >= 5 - bReturn |= SetSettingAutoPowerOn(configuration.bAutoPowerOn); + if ((configuration.bAutoPowerOn == 0) || (configuration.bAutoPowerOn == 1)) + bReturn |= SetSettingAutoPowerOn(configuration.bAutoPowerOn == 1); #else bReturn |= SetSettingAutoPowerOn(false); #endif + } else + { bReturn |= SetSettingCECVersion(configuration.cecVersion); + } return bReturn; } bool CUSBCECAdapterCommands::RequestSettings(void) { - if (m_persistedConfiguration.iFirmwareVersion < 2) + if (m_savedConfiguration.iFirmwareVersion < 2) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - firmware version %d does not have any eeprom settings", __FUNCTION__, m_persistedConfiguration.iFirmwareVersion); - // settings can only be persisted with firmware v2+ + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - firmware version %d does not have any eeprom settings", __FUNCTION__, m_savedConfiguration.iFirmwareVersion); + // settings can only be saved when using firmware v2+ return false; } @@ -585,7 +637,7 @@ bool CUSBCECAdapterCommands::RequestSettings(void) bReturn |= RequestSettingLogicalAddressMask(); bReturn |= RequestSettingOSDName(); bReturn |= RequestSettingPhysicalAddress(); - if (m_persistedConfiguration.iFirmwareVersion >= 10) + if (m_savedConfiguration.iFirmwareVersion >= 10) bReturn |= RequestSettingAutoPowerOn(); else bReturn |= RequestSettingCECVersion(); @@ -596,18 +648,6 @@ bool CUSBCECAdapterCommands::RequestSettings(void) // - logical address mask (autodetected) // - CEC version (1.3a) - // TODO to be added to the firmware: - // - base device (4 bits) - // - HDMI port number (4 bits) - // - TV vendor id (12 bits) - // - wake devices (8 bits) - // - standby devices (8 bits) - // - use TV menu language (1 bit) - // - activate source (1 bit) - // - power off screensaver (1 bit) - // - power off on standby (1 bit) - // - send inactive source (1 bit) - m_bSettingsRetrieved = true; return bReturn; @@ -620,10 +660,15 @@ bool CUSBCECAdapterCommands::GetConfiguration(libcec_configuration &configuratio return false; // copy the settings - configuration.iFirmwareVersion = m_persistedConfiguration.iFirmwareVersion; - configuration.deviceTypes = m_persistedConfiguration.deviceTypes; - configuration.iPhysicalAddress = m_persistedConfiguration.iPhysicalAddress; - snprintf(configuration.strDeviceName, LIBCEC_OSD_NAME_SIZE, "%s", m_persistedConfiguration.strDeviceName); + configuration.iFirmwareVersion = m_savedConfiguration.iFirmwareVersion; + configuration.iFirmwareBuildDate = m_savedConfiguration.iFirmwareBuildDate; + configuration.deviceTypes = m_savedConfiguration.deviceTypes; + configuration.iPhysicalAddress = m_savedConfiguration.iPhysicalAddress; + configuration.cecVersion = m_savedConfiguration.cecVersion; +#if CEC_LIB_VERSION_MAJOR >= 5 + configuration.bAutoPowerOn = m_savedConfiguration.bAutoPowerOn; +#endif + memcpy(configuration.strDeviceName, m_savedConfiguration.strDeviceName, LIBCEC_OSD_NAME_SIZE); return true; } @@ -631,7 +676,7 @@ bool CUSBCECAdapterCommands::GetConfiguration(libcec_configuration &configuratio bool CUSBCECAdapterCommands::PingAdapter(void) { #ifdef CEC_DEBUGGING - LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending ping"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: sending ping"); #endif CCECAdapterMessage params; @@ -643,7 +688,7 @@ bool CUSBCECAdapterCommands::PingAdapter(void) bool CUSBCECAdapterCommands::SetAckMask(uint16_t iMask) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting ackmask to %2x", iMask); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updating ackmask: %04X", iMask); CCECAdapterMessage params; params.PushEscaped(iMask >> 8); @@ -657,9 +702,9 @@ bool CUSBCECAdapterCommands::SetAckMask(uint16_t iMask) void CUSBCECAdapterCommands::SetActiveSource(bool bSetTo, bool bClientUnregistered) { if (bClientUnregistered) return; - if (m_persistedConfiguration.iFirmwareVersion >= 3) + if (m_savedConfiguration.iFirmwareVersion >= 3) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "marking the adapter as %s source", bSetTo ? "active" : "inactive"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updating active source status: %s", bSetTo ? "active" : "inactive"); CCECAdapterMessage params; params.PushEscaped(bSetTo ? 1 : 0); CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_SET_ACTIVE_SOURCE, params); @@ -669,7 +714,7 @@ void CUSBCECAdapterCommands::SetActiveSource(bool bSetTo, bool bClientUnregister bool CUSBCECAdapterCommands::StartBootloader(void) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "starting the bootloader"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: starting the bootloader"); CCECAdapterMessage params; CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_START_BOOTLOADER, params); @@ -680,7 +725,7 @@ bool CUSBCECAdapterCommands::StartBootloader(void) bool CUSBCECAdapterCommands::SetLineTimeout(uint8_t iTimeout) { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting the line timeout to %d", iTimeout); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: updating line timeout: %u", iTimeout); CCECAdapterMessage params; params.PushEscaped(iTimeout); CCECAdapterMessage *message = m_comm->SendCommand(MSGCODE_TRANSMIT_IDLETIME, params); @@ -697,7 +742,7 @@ bool CUSBCECAdapterCommands::SetControlledMode(bool controlled) return true; } - LIB_CEC->AddLog(CEC_LOG_DEBUG, "turning controlled mode %s", controlled ? "on" : "off"); + LIB_CEC->AddLog(CEC_LOG_DEBUG, "usbcec: %s controlled mode", controlled ? "enabling" : "disabling"); CCECAdapterMessage params; params.PushEscaped(controlled ? 1 : 0); diff --git a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.h b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.h index 552c5cf0..d89240b0 100644 --- a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.h +++ b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.h @@ -54,7 +54,7 @@ namespace CEC /*! * @return The firmware version of the adapter, retrieved when the connection is opened. */ - uint16_t GetFirmwareVersion(void) const { return m_persistedConfiguration.iFirmwareVersion; }; + uint16_t GetFirmwareVersion(void) const { return m_savedConfiguration.iFirmwareVersion; }; /*! * @brief Update the current configuration in the adapter. Does not do an eeprom update. @@ -62,7 +62,7 @@ namespace CEC * @param configuration The configuration to persist. * @return True when something changed, false otherwise. */ - bool PersistConfiguration(const libcec_configuration &configuration); + bool SaveConfiguration(const libcec_configuration &configuration); /*! * @brief Get the persisted configuration from the EEPROM. @@ -114,7 +114,7 @@ namespace CEC /*! * @return The persisted build date. */ - uint32_t GetPersistedBuildDate(void) const { return m_iBuildDate; }; + uint32_t GetPersistedBuildDate(void) const { return m_savedConfiguration.iFirmwareBuildDate; }; /*! * @brief Request the adapter type. @@ -246,12 +246,9 @@ namespace CEC CUSBCECAdapterCommunication *m_comm; /**< the communication handler */ bool m_bSettingsRetrieved; /**< true when the settings were read from the eeprom, false otherwise */ bool m_bSettingAutoEnabled; /**< the value of the auto-enabled setting */ - cec_version m_settingCecVersion; /**< the value of the cec version setting */ - bool m_settingAutoOn; /**< the value of the auto power on setting */ uint16_t m_iSettingLAMask; /**< the value of the LA mask setting */ bool m_bNeedsWrite; /**< true when we sent changed settings to the adapter that have not been persisted */ - libcec_configuration m_persistedConfiguration; /**< the configuration that is persisted in the eeprom */ - uint32_t m_iBuildDate; /**< the build date of the firmware */ + libcec_configuration m_savedConfiguration; /**< the configuration that is saved in the eeprom */ bool m_bControlledMode; /**< current value of the controlled mode feature */ p8_cec_adapter_type m_adapterType; /**< the type of the adapter that we're connected to */ P8PLATFORM::CMutex m_mutex; diff --git a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp index b048cb8b..d0e08550 100644 --- a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp +++ b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp @@ -517,7 +517,11 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = CEC_DEFA bool CUSBCECAdapterCommunication::IsOpen(void) { /* thread is not being stopped, the port is open and the thread is running */ - return !IsStopped() && m_port->IsOpen() && IsRunning(); + bool stopped, opened, running; + stopped = IsStopped(); + opened = m_port->IsOpen(); + running = IsRunning(); + return !stopped && opened && running; } std::string CUSBCECAdapterCommunication::GetError(void) const @@ -650,10 +654,10 @@ bool CUSBCECAdapterCommunication::IsRunningLatestFirmware(void) GetFirmwareVersion() >= CEC_LATEST_ADAPTER_FW_VERSION; } -bool CUSBCECAdapterCommunication::PersistConfiguration(const libcec_configuration &configuration) +bool CUSBCECAdapterCommunication::SaveConfiguration(const libcec_configuration &configuration) { return IsOpen() ? - m_commands->PersistConfiguration(configuration) && m_eepromWriteThread->Write() : + m_commands->SaveConfiguration(configuration) && m_eepromWriteThread->Write() : false; } diff --git a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.h b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.h index b8d2459e..46c5860c 100644 --- a/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.h +++ b/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.h @@ -82,7 +82,7 @@ namespace CEC uint16_t GetFirmwareVersion(void); uint32_t GetFirmwareBuildDate(void); bool IsRunningLatestFirmware(void); - bool PersistConfiguration(const libcec_configuration &configuration); + bool SaveConfiguration(const libcec_configuration &configuration); bool SetAutoMode(bool automode); bool GetConfiguration(libcec_configuration &configuration); std::string GetPortName(void); diff --git a/src/libcec/adapter/RPi/RPiCECAdapterCommunication.h b/src/libcec/adapter/RPi/RPiCECAdapterCommunication.h index 4c2a4eba..2bf9fba7 100644 --- a/src/libcec/adapter/RPi/RPiCECAdapterCommunication.h +++ b/src/libcec/adapter/RPi/RPiCECAdapterCommunication.h @@ -76,7 +76,7 @@ namespace CEC uint16_t GetFirmwareVersion(void); uint32_t GetFirmwareBuildDate(void) { return 0; }; bool IsRunningLatestFirmware(void) { return true; }; - bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; }; + bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; }; bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; }; bool SetAutoMode(bool UNUSED(automode)) { return false; } std::string GetPortName(void) { std::string strReturn("RPI"); return strReturn; }; diff --git a/src/libcec/adapter/TDA995x/TDA995xCECAdapterCommunication.h b/src/libcec/adapter/TDA995x/TDA995xCECAdapterCommunication.h index f3cfb760..fbd5bd85 100644 --- a/src/libcec/adapter/TDA995x/TDA995xCECAdapterCommunication.h +++ b/src/libcec/adapter/TDA995x/TDA995xCECAdapterCommunication.h @@ -80,7 +80,7 @@ namespace CEC uint16_t GetFirmwareVersion(void); uint32_t GetFirmwareBuildDate(void) { return 0; } bool IsRunningLatestFirmware(void) { return true; } - bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } + bool SaveConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } bool SetAutoMode(bool UNUSED(automode)) { return false; } std::string GetPortName(void) { return std::string("TDA995X"); } diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake index 1d99bd87..5d423df7 100644 --- a/src/libcec/cmake/CheckPlatformSupport.cmake +++ b/src/libcec/cmake/CheckPlatformSupport.cmake @@ -73,7 +73,7 @@ if(WIN32) libcec.rc) else() # not Windows - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-missing-field-initializers") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-missing-field-initializers -Wno-deprecated-copy") list(APPEND CEC_SOURCES_PLATFORM platform/posix/os-edid.cpp platform/posix/serialport.cpp) set(LIB_DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/src/libcec/libcec.i b/src/libcec/libcec.i index 57096775..88250be0 100644 --- a/src/libcec/libcec.i +++ b/src/libcec/libcec.i @@ -93,6 +93,16 @@ _SetCallback(self, CEC::PYTHON_CB_SOURCE_ACTIVATED, pyfunc); } + void SetAlertCallback(PyObject* pyfunc) + { + _SetCallback(self, CEC::PYTHON_CB_ALERT, pyfunc); + } + + void SetConfigurationChangedCallback(PyObject* pyfunc) + { + _SetCallback(self, CEC::PYTHON_CB_CONFIGURATION, pyfunc); + } + void ClearCallbacks(void) { _ClearCallbacks(self); @@ -117,14 +127,18 @@ namespace std { if (self->GetCurrentConfiguration(&config)) { _ClearCallbacks(&config); + %#if CEC_LIB_VERSION_MAJOR >= 5 + self->DisableCallbacks(); + %#else self->EnableCallbacks(NULL, NULL); + %#endif } } static CEC::ICECAdapter* Create(CEC::libcec_configuration* configuration) { CEC::ICECAdapter* lib = CECInitialise(configuration); - if (lib) + if (!!lib) { lib->InitVideoStandalone(); PyEval_InitThreads(); @@ -144,6 +158,10 @@ namespace std { } %ignore CEC::ICECAdapter::~ICECAdapter; +%ignore CEC::ICECAdapter::SetCallbacks; +%ignore CEC::ICECAdapter::EnableCallbacks; +%ignore CEC::ICECAdapter::CanPersistConfiguration; +%ignore CEC::ICECAdapter::PersistConfiguration; %ignore CEC::ICECCallbacks; %ignore CEC::DetectAdapters; %ignore CEC::GetDeviceMenuLanguage; diff --git a/src/platform b/src/platform index 1c9d14fa..1133cccd 160000 --- a/src/platform +++ b/src/platform @@ -1 +1 @@ -Subproject commit 1c9d14fa996af33760a2c700caebd2bd9ae527c9 +Subproject commit 1133cccd412fd5dba541bf735f3facc5b72321c3 diff --git a/support b/support index 7c412111..416da1d0 160000 --- a/support +++ b/support @@ -1 +1 @@ -Subproject commit 7c4121112af37d641ea02383d53b50a38087115a +Subproject commit 416da1d0e60ee2397f31d4eb8f85886a9ef3327a diff --git a/windows/build-all.cmd b/windows/build-all.cmd index 8e244fb5..e1a86c70 100644 --- a/windows/build-all.cmd +++ b/windows/build-all.cmd @@ -37,6 +37,13 @@ IF "%3" == "" ( SET VSVERSION=%3 ) +rem optional parameter: build .net applications +IF "%4" == "" ( + SET DOTNETAPPS=1 +) ELSE ( + SET DOTNETAPPS=0 +) + SET BUILDPATH=%MYDIR%..\build SET EXITCODE=1 @@ -93,38 +100,40 @@ IF EXIST "%MYDIR%..\build\%BUILDARCH%\netcore\LibCecSharpCore.dll" ( EXIT /b 1 ) -rem Compile cec-tray and CecSharpTester apps -ECHO. * compiling .Net applications for %BUILDARCH% -CD "%MYDIR%..\src\dotnet\project" -rem Restore nuget dependencies -msbuild -t:restore -"%DevEnvDir%devenv.com" cec-dotnet.sln /Build "%BUILDTYPE%|%BUILDARCHPROJECT%" - -rem Check and copy CecSharpTester -IF EXIST ..\build\%BUILDARCHPROJECT%\CecSharpTester.exe ( - COPY ..\build\%BUILDARCHPROJECT%\CecSharpTester.exe "%MYDIR%..\build\%BUILDARCH%\CecSharpTester.exe" >nul -) ELSE ( - ECHO. *** failed to build CecSharpTester for %BUILDARCH% *** - PAUSE - EXIT /b 1 -) - -rem Check and copy cec-tray -IF EXIST ..\build\%BUILDARCHPROJECT%\cec-tray.exe ( - COPY ..\build\%BUILDARCHPROJECT%\cec-tray.exe "%MYDIR%..\build\%BUILDARCH%\cec-tray.exe" >nul -) ELSE ( - ECHO. *** failed to build cec-tray for %BUILDARCH% *** - PAUSE - EXIT /b 1 -) - -rem Check and copy CecSharpCoreTester -IF EXIST ..\build\%BUILDARCHPROJECT%\netcoreapp3.1\CecSharpCoreTester.exe ( - COPY ..\build\%BUILDARCHPROJECT%\netcoreapp3.1\CecSharpCoreTester.* "%MYDIR%..\build\%BUILDARCH%\netcore\." >nul -) ELSE ( - ECHO. *** failed to build CecSharpCoreTester for %BUILDARCH% *** - PAUSE - EXIT /b 1 +IF %DOTNETAPPS% == 1 ( + rem Compile cec-tray and CecSharpTester apps + ECHO. * compiling .Net applications for %BUILDARCH% + CD "%MYDIR%..\src\dotnet\project" + rem Restore nuget dependencies + msbuild -t:restore + "%DevEnvDir%devenv.com" cec-dotnet.sln /Build "%BUILDTYPE%|%BUILDARCHPROJECT%" + + rem Check and copy CecSharpTester + IF EXIST "..\build\%BUILDARCHPROJECT%\CecSharpTester.exe" ( + COPY "..\build\%BUILDARCHPROJECT%\CecSharpTester.exe" "%MYDIR%..\build\%BUILDARCH%\CecSharpTester.exe" >nul + ) ELSE ( + ECHO. *** failed to build CecSharpTester for %BUILDARCH% *** + PAUSE + EXIT /b 1 + ) + + rem Check and copy cec-tray + IF EXIST "..\build\%BUILDARCHPROJECT%\cec-tray.exe" ( + COPY "..\build\%BUILDARCHPROJECT%\cec-tray.exe" "%MYDIR%..\build\%BUILDARCH%\cec-tray.exe" >nul + ) ELSE ( + ECHO. *** failed to build cec-tray for %BUILDARCH% *** + PAUSE + EXIT /b 1 + ) + + rem Check and copy CecSharpCoreTester + IF EXIST "..\build\%BUILDARCHPROJECT%\netcoreapp3.1\CecSharpCoreTester.exe" ( + COPY "..\build\%BUILDARCHPROJECT%\netcoreapp3.1\CecSharpCoreTester.*" "%MYDIR%..\build\%BUILDARCH%\netcore\." >nul + ) ELSE ( + ECHO. *** failed to build CecSharpCoreTester for %BUILDARCH% *** + PAUSE + EXIT /b 1 + ) ) RMDIR /s /q "%BUILDPATH%\cmake" >nul 2>&1 diff --git a/windows/build-lib.cmd b/windows/build-lib.cmd index 39122e16..4dc66e29 100644 --- a/windows/build-lib.cmd +++ b/windows/build-lib.cmd @@ -19,10 +19,16 @@ SET TARGET=%INSTALLPATH%\%BUILDARCH% rem Check support submodule IF NOT EXIST "%MYDIR%..\support\windows\cmake\build.cmd" ( - ECHO.*** support git submodule has not been checked out *** - ECHO. - ECHO.See docs\README.windows.md - EXIT /b 2 + rem Try to init the git submodules + cd "%MYDIR%.." + git submodule update --init -r >nul 2>&1 + + IF NOT EXIST "%MYDIR%..\support\windows\cmake\build.cmd" ( + ECHO.*** support git submodule has not been checked out *** + ECHO. + ECHO.See docs\README.windows.md + EXIT /b 2 + ) ) rem Check platform submodule @@ -36,6 +42,7 @@ IF NOT EXIST "%MYDIR%..\src\platform\windows\build.cmd" ( rem Compile platform library ECHO. * compiling platform library for %BUILDARCH% CALL "%MYDIR%..\src\platform\windows\build-lib.cmd" %BUILDARCH% %BUILDTYPE% %VSVERSION% "%INSTALLPATH%" +IF %errorlevel% neq 0 EXIT /b %errorlevel% RMDIR /s /q "%BUILDTARGET%" >nul 2>&1 rem Compile libCEC diff --git a/windows/create-installer.cmd b/windows/create-installer.cmd index 43a62656..a6802072 100644 --- a/windows/create-installer.cmd +++ b/windows/create-installer.cmd @@ -20,6 +20,7 @@ IF "%2" == "" ( SET BUILDTYPE=%2 ) +SET NSISDOTNET=/DNSISDOTNETAPPS SET BUILDPATH=%MYDIR%..\build SET EXITCODE=1 @@ -33,6 +34,7 @@ rem Skip to libCEC/x86 if we're running on win32 IF "%PROCESSOR_ARCHITECTURE%"=="x86" IF "%PROCESSOR_ARCHITEW6432%"=="" GOTO libcecx86 :libcecx64 +SET X86ONLY=0 CALL "%MYDIR%build-all.cmd" amd64 %BUILDTYPE% %VSVERSION% IF %errorlevel% neq 0 ( ECHO. *** failed to build libCEC for x64 *** @@ -41,6 +43,7 @@ IF %errorlevel% neq 0 ( ) :libcecx86 +SET X86ONLY=1 CALL "%MYDIR%build-all.cmd" x86 %BUILDTYPE% %VSVERSION% IF %errorlevel% neq 0 ( ECHO. *** failed to build libCEC for x86 *** @@ -48,23 +51,6 @@ IF %errorlevel% neq 0 ( GOTO EXIT ) -:CREATEEGPLUGIN -ECHO. * creating EventGhost plugin -SET EGSOURCES=%MYDIR%..\src\eventghost\egplugin_sources\ -COPY "%MYDIR%..\build\x86\python\cec\__init__.py" "%EGSOURCES%PulseEight\cec" >nul -COPY "%MYDIR%..\build\x86\python\cec\_cec.pyd" "%EGSOURCES%PulseEight" >nul -COPY "%MYDIR%..\build\x86\cec.dll" "%EGSOURCES%PulseEight" >nul -DEL /q /f "%EGSOURCES%..\pulse_eight.egplugin" >nul 2>&1 -PowerShell -ExecutionPolicy ByPass -Command "Add-Type -Assembly System.IO.Compression.FileSystem;[System.IO.Compression.ZipFile]::CreateFromDirectory('%EGSOURCES%', '%EGSOURCES%..\pulse_eight.egplugin', [System.IO.Compression.CompressionLevel]::Optimal, $false)" -DEL /q /f "%EGSOURCES%PulseEight\cec\__init__.py" >nul 2>&1 -DEL /q /f "%EGSOURCES%PulseEight\_cec.pyd" >nul 2>&1 -DEL /q /f "%EGSOURCES%PulseEight\cec.dll" >nul 2>&1 -IF NOT EXIST "%EGSOURCES%..\pulse_eight.egplugin" ( - ECHO. *** failed to create EventGhost plugin *** - SET EXITCODE=1 - GOTO EXIT -) - :SIGNBINARIES rem Check for sign-binary.cmd, only present on the Pulse-Eight production build system rem Calls signtool.exe and signs the DLLs with Pulse-Eight's code signing key @@ -72,36 +58,62 @@ IF NOT EXIST "..\support\private\sign-binary.cmd" GOTO CREATEINSTALLER ECHO. * signing all binaries CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\cec.dll" >nul CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\LibCecSharp.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\cec-tray.exe" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\CecSharpTester.exe" >nul CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\netcore\LibCecSharpCore.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\netcore\CecSharpCoreTester.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\netcore\CecSharpCoreTester.exe" >nul CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\cec-client.exe" >nul CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\cecc-client.exe" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cec.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\LibCecSharp.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cec-tray.exe" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\CecSharpTester.exe" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\netcore\LibCecSharpCore.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\netcore\CecSharpCoreTester.dll" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\netcore\CecSharpCoreTester.exe" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cec-client.exe" >nul -CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cecc-client.exe" >nul +IF EXIST "%MYDIR%..\build\x86\cec-tray.exe" ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\cec-tray.exe" >nul +) +IF EXIST "%MYDIR%..\build\x86\CecSharpTester.exe" ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\CecSharpTester.exe" >nul +) +IF EXIST "%MYDIR%..\build\x86\netcore\CecSharpCoreTester.exe" ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\netcore\CecSharpCoreTester.dll" >nul + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\x86\netcore\CecSharpCoreTester.exe" >nul +) + +IF %X86ONLY% == 0 ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cec.dll" >nul + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\LibCecSharp.dll" >nul + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\netcore\LibCecSharpCore.dll" >nul + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cec-client.exe" >nul + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cecc-client.exe" >nul + IF EXIST "%MYDIR%..\build\amd64\cec-tray.exe" ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\cec-tray.exe" >nul + ) + IF EXIST "%MYDIR%..\build\amd64\CecSharpTester.exe" ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\CecSharpTester.exe" >nul + ) + IF EXIST "%MYDIR%..\build\amd64\netcore\CecSharpCoreTester.exe" ( + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\netcore\CecSharpCoreTester.dll" >nul + CALL ..\support\private\sign-binary.cmd "%MYDIR%..\build\amd64\netcore\CecSharpCoreTester.exe" >nul + ) +) + +:CREATEEGPLUGIN +call "%MYDIR%eventghost.cmd" + +IF %errorlevel% neq 0 ( + ECHO. *** failed to create EventGhost plugin *** + SET EXITCODE=1 + GOTO EXIT +) :CREATEINSTALLER -rem Copy prebuilt driver +rem Copy prebuilt drivers COPY "%MYDIR%..\support\windows\p8-usbcec-driver-installer.exe" "%MYDIR%..\build\." >nul +COPY "%MYDIR%..\support\windows\p8-usbcec-bootloader-driver-installer.exe" "%MYDIR%..\build\." >nul +COPY "%MYDIR%..\support\windows\libusb0.dll" "%MYDIR%..\build\." >nul RMDIR /s /q "%MYDIR%..\build\ref" >nul 2>&1 -CALL "%MYDIR%nsis-helper.cmd" libcec.nsi "libcec-*.exe" +CALL "%MYDIR%nsis-helper.cmd" libcec.nsi "libcec-*.exe" "%NSISDOTNET%" IF %errorlevel% neq 0 ( ECHO. *** failed to build installer *** SET EXITCODE=%errorlevel% GOTO EXIT ) -CALL "%MYDIR%nsis-helper.cmd" libcec.nsi "libcec-dbg-*.exe" "/DNSISINCLUDEPDB" +CALL "%MYDIR%nsis-helper.cmd" libcec.nsi "libcec-dbg-*.exe" "/DNSISINCLUDEPDB %NSISDOTNET%" IF %errorlevel% neq 0 ( ECHO. *** failed to build installer *** SET EXITCODE=%errorlevel% diff --git a/windows/eventghost.cmd b/windows/eventghost.cmd new file mode 100644 index 00000000..a0a28e65 --- /dev/null +++ b/windows/eventghost.cmd @@ -0,0 +1,30 @@ +@ECHO OFF + +SETLOCAL + +SET MYDIR=%~dp0 +SET EXITCODE=0 + +ECHO. * creating EventGhost plugin +SET EGSOURCES=%MYDIR%..\build\EventGhost\egplugin_sources +RMDIR /s /q "%MYDIR%..\build\EventGhost" >nul 2>&1 +MKDIR "%MYDIR%..\build\EventGhost" + +XCOPY /E /I "%MYDIR%..\src\eventghost\egplugin_sources" "%EGSOURCES%" >nul + +COPY "%MYDIR%..\build\x86\python\cec\_cec.pyd" "%EGSOURCES%\PulseEight" >nul +COPY "%MYDIR%..\build\x86\cec.dll" "%EGSOURCES%\PulseEight" >nul + +COPY "%MYDIR%..\build\x86\python\cec\__init__.py" "%EGSOURCES%\PulseEight\cec" >nul + +PowerShell -ExecutionPolicy ByPass -Command "Add-Type -Assembly System.IO.Compression.FileSystem;[System.IO.Compression.ZipFile]::CreateFromDirectory('%EGSOURCES%\', '%EGSOURCES%\..\pulse_eight.egplugin', [System.IO.Compression.CompressionLevel]::Optimal, $false)" + +DEL /q /f "%EGSOURCES%" >nul 2>&1 + +IF NOT EXIST "%EGSOURCES%\..\pulse_eight.egplugin" ( + ECHO. *** failed to create EventGhost plugin *** + SET EXITCODE=1 + GOTO EXIT +) + +exit /b %EXITCODE%