From 5e49fdf3797d81c5c0640aa22187dacaf49d30ff Mon Sep 17 00:00:00 2001 From: Vishnu Karpuram Date: Tue, 5 Apr 2022 13:29:29 -0700 Subject: [PATCH] Version 2.9.1 alexa-smart-screen-sdk *** Bug Fixes *** * Fixed hold-to-talk event handling logic in the native layer to keep it in sync with GUI *** Enhancements *** * Upgraded dependency to APL Client Library 1.8.3 * Upgraded nanoid version to 3.2.0, minimist version to 1.2.6 and refreshed the package-lock.json with new dependencies. Note that users upgrading to this version will need to remove the existing node modules from modules/GUI/js/node_modules before the build. --- CHANGELOG.md | 16 ++-- CMakeLists.txt | 2 +- README.md | 8 +- .../Communication/src/WebSocketServer.cpp | 37 +++++---- .../SmartScreenClient/SmartScreenClient.h | 8 +- .../src/SmartScreenClient.cpp | 11 ++- .../include/SampleApp/AplClientBridge.h | 5 +- .../include/SampleApp/GUI/GUIClient.h | 11 ++- .../include/SampleApp/GUI/GUIManager.h | 8 +- .../Alexa/SampleApp/src/AplClientBridge.cpp | 14 +++- modules/Alexa/SampleApp/src/GUI/GUIClient.cpp | 20 +++-- .../Alexa/SampleApp/src/GUI/GUIManager.cpp | 29 ++++--- .../AlexaPresentation/AlexaPresentation.h | 14 ++-- .../AplCommandsExecutionEvent.h | 77 +++++++++++++++++++ .../src/AlexaPresentation.cpp | 51 ++++++------ .../test/AlexaPresentationTest.cpp | 5 +- .../GUIServerInterface.h | 12 ++- .../include/Utils/SmartScreenSDKVersion.h | 2 +- modules/GUI/SDK-GUI-API.md | 16 +++- modules/GUI/config/SmartScreenSDKConfig.md | 2 +- modules/GUI/js/package-lock.json | 17 ++-- modules/GUI/js/package.json | 2 +- modules/GUI/js/src/app.tsx | 6 +- .../js/src/components/APLRendererWindow.tsx | 2 +- .../src/components/LiveViewCameraWindow.tsx | 1 + modules/GUI/js/src/lib/messages/messages.ts | 3 +- 26 files changed, 264 insertions(+), 115 deletions(-) create mode 100644 modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AplCommandsExecutionEvent.h diff --git a/CHANGELOG.md b/CHANGELOG.md index aefd702..b6f2c3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ -### v2.9.0 released 12/16/2021: +### v2.9.1 released 04/05/2022: +#### Bug fixes +* Fixed hold-to-talk event handling logic in the native layer to keep it in sync with GUI + +#### Enhancements +* Upgraded dependency to APL Client Library 1.8.3 +* Upgraded nanoid version to 3.2.0, minimist version to 1.2.6 and refreshed the package-lock.json with new dependencies. Note that users upgrading to this version will need to remove the existing node modules from modules/GUI/js/node_modules before the build. +### v2.9.0 released 12/16/2021: #### Breaking Changes * Decoupled APL Client Library and APL Core Engine build from Smart Screen SDK. Please follow new build instructions here [https://developer.amazon.com/en-US/docs/alexa/alexa-smart-screen-sdk/overview.html] @@ -82,7 +89,6 @@ * Fixed a regression introduced in 2.4 wherein keyboard events no longer interrupted TTS and APL activity ### v2.4.0 released 11/09/2020: - #### Enhancements * Upgraded dependency to Device SDK 1.21.0 [https://github.com/alexa/avs-device-sdk/tree/v1.21.0] * Added DND Support @@ -92,7 +98,6 @@ * Fixed an issue where the sample app automatically goes into the listening mode when prompted by a skill ### v2.3.0 released 09/24/2020: - #### Enhancements * Upgraded dependency to Device SDK 1.20.1 [https://github.com/alexa/avs-device-sdk/tree/v1.20.1] * Support for APL 1.4 [https://developer.amazon.com/en-US/docs/alexa/alexa-presentation-language/apl-changes-1-4.html] @@ -107,7 +112,6 @@ * Fixed import content failure cache update ### v2.2.0 released 07/13/2020: - #### Enhancements * Upgraded dependency to Device SDK 1.20.0 * Optimization for APL package import latency @@ -131,7 +135,6 @@ * The AVS Device SDK must be built with an additional flag: `-DRAPIDJSON_MEM_OPTIMIZATION=OFF` ### v2.1.0 released 06/02/2020: - #### Enhancements * Upgraded dependency to Device SDK 1.19.1 * Provided a reference implementation for rendering of captions @@ -156,7 +159,6 @@ * Progress bar on Now Playing display card does not reflect the actual audio offset when such information is not provided in RenderPlayerInfo directive ### v2.0.2 released 04/14/2020: - #### Bug fixes * Added support for Raspbian Buster. * Upgrade dependency on Device SDK 1.19 @@ -174,7 +176,6 @@ * The build option ENABLE_CAPTIONS does not enable captions. Enabling it will cause undefined behaviour during a build. ### v2.0.1 released 11/26/2019: - #### Bug Fixes * Fixed segfault is situation when bad Misc DB path was provided in configuration. * Fixed situation where video playback controls were unresponsive on some skills. @@ -185,7 +186,6 @@ * In rare cases button presses could trigger repeat speech. ### v2.0 released 11/16/2019: - Initial public release #### Known Issues diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bb23f9..cceb9ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -project(AlexaSmartScreenSDK VERSION 2.9.0 LANGUAGES CXX) +project(AlexaSmartScreenSDK VERSION 2.9.1 LANGUAGES CXX) set(PROJECT_BRIEF "A cross-platform, modular SDK for multi modal interaction with the Alexa Voice Service") configure_file ( "${PROJECT_SOURCE_DIR}/modules/Alexa/Utils/include/Utils/SmartScreenSDKVersion.h.in" diff --git a/README.md b/README.md index 5349394..42767e0 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Alexa Smart Screen SDK

- - + + - - + +

diff --git a/modules/Alexa/ApplicationUtilities/Communication/src/WebSocketServer.cpp b/modules/Alexa/ApplicationUtilities/Communication/src/WebSocketServer.cpp index 342acf1..eb674bd 100644 --- a/modules/Alexa/ApplicationUtilities/Communication/src/WebSocketServer.cpp +++ b/modules/Alexa/ApplicationUtilities/Communication/src/WebSocketServer.cpp @@ -99,25 +99,30 @@ bool WebSocketServer::start() { } #endif - websocketpp::lib::error_code errorCode; + try { + websocketpp::lib::error_code errorCode; - m_webSocketServer.start_accept(errorCode); - if (errorCode) { - ACSDK_ERROR(LX("server::start_accept") - .d("errorCode", errorCode.value()) - .d("errorCategory", errorCode.category().name())); - return false; - } + m_webSocketServer.start_accept(errorCode); + if (errorCode) { + ACSDK_ERROR(LX("server::start_accept") + .d("errorCode", errorCode.value()) + .d("errorCategory", errorCode.category().name())); + return false; + } - auto endpoint = m_webSocketServer.get_local_endpoint(errorCode); - if (errorCode) { - ACSDK_ERROR(LX("server::get_local_endpoint") - .d("errorCode", errorCode.value()) - .d("errorCategory", errorCode.category().name())); - return false; - } + auto endpoint = m_webSocketServer.get_local_endpoint(errorCode); + if (errorCode) { + ACSDK_ERROR(LX("server::get_local_endpoint") + .d("errorCode", errorCode.value()) + .d("errorCategory", errorCode.category().name())); + return false; + } - ACSDK_INFO(LX("Listening for websocket connections").d("interface", endpoint.address()).d("port", endpoint.port())); + ACSDK_INFO( + LX("Listening for websocket connections").d("interface", endpoint.address()).d("port", endpoint.port())); + } catch (const std::bad_weak_ptr& e) { + ACSDK_ERROR(LX("std::bad_weak_ptr").d("reason", e.what())); + } m_webSocketServer.run(); diff --git a/modules/Alexa/ApplicationUtilities/SmartScreenClient/include/SmartScreenClient/SmartScreenClient.h b/modules/Alexa/ApplicationUtilities/SmartScreenClient/include/SmartScreenClient/SmartScreenClient.h index 0d1082a..727df97 100644 --- a/modules/Alexa/ApplicationUtilities/SmartScreenClient/include/SmartScreenClient/SmartScreenClient.h +++ b/modules/Alexa/ApplicationUtilities/SmartScreenClient/include/SmartScreenClient/SmartScreenClient.h @@ -1137,11 +1137,11 @@ AudioInputProcessor. /** * Handle execute command result. - * @param token The token. - * @param result The execute command result. - * @param error The error. + * @param token the execute command result token. + * @param event the command execution event. + * @param message the execute command completion message. */ - void handleExecuteCommandsResult(const std::string& token, bool result, std::string error); + void handleExecuteCommandsResult(const std::string& token, const std::string& event, const std::string& message); /** * Handle activity event. diff --git a/modules/Alexa/ApplicationUtilities/SmartScreenClient/src/SmartScreenClient.cpp b/modules/Alexa/ApplicationUtilities/SmartScreenClient/src/SmartScreenClient.cpp index 7823b12..079e712 100644 --- a/modules/Alexa/ApplicationUtilities/SmartScreenClient/src/SmartScreenClient.cpp +++ b/modules/Alexa/ApplicationUtilities/SmartScreenClient/src/SmartScreenClient.cpp @@ -58,6 +58,7 @@ #include #endif +#include #include #include "SmartScreenClient/DefaultClientComponent.h" @@ -1942,8 +1943,14 @@ void SmartScreenClient::handleRenderDocumentResult(const std::string& token, boo m_alexaPresentation->processRenderDocumentResult(token, result, error); } -void SmartScreenClient::handleExecuteCommandsResult(const std::string& token, bool result, std::string error) { - m_alexaPresentation->processExecuteCommandsResult(token, result, error); +void SmartScreenClient::handleExecuteCommandsResult( + const std::string& token, + const std::string& event, + const std::string& message) { + m_alexaPresentation->processExecuteCommandsResult( + token, + alexaSmartScreenSDK::smartScreenCapabilityAgents::alexaPresentation::stringToCommandExecutionEvent(event), + message); } void SmartScreenClient::handleActivityEvent( diff --git a/modules/Alexa/SampleApp/include/SampleApp/AplClientBridge.h b/modules/Alexa/SampleApp/include/SampleApp/AplClientBridge.h index 6507d43..87bd1ba 100644 --- a/modules/Alexa/SampleApp/include/SampleApp/AplClientBridge.h +++ b/modules/Alexa/SampleApp/include/SampleApp/AplClientBridge.h @@ -82,7 +82,10 @@ class AplClientBridge void onSendEvent(const std::string& token, const std::string& event) override; - void onCommandExecutionComplete(const std::string& token, bool result) override; + void onCommandExecutionComplete( + const std::string& token, + APLClient::AplCommandExecutionEvent event, + const std::string& message) override; void onRenderDocumentComplete(const std::string& token, bool result, const std::string& error) override; diff --git a/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIClient.h b/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIClient.h index 4eda4a2..9ea8049 100644 --- a/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIClient.h +++ b/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIClient.h @@ -374,11 +374,18 @@ class GUIClient void executeHandleTapToTalk(rapidjson::Document& message); /** - * Handle HoldToTalk event. + * Handle HoldToTalkStart event. * * @param message A complete message object with header and payload. */ - void executeHandleHoldToTalk(rapidjson::Document& message); + void executeHandleHoldToTalkStart(rapidjson::Document& message); + + /** + * Handle HoldToTalkEnd event. + * + * @param message A complete message object with header and payload. + */ + void executeHandleHoldToTalkEnd(rapidjson::Document& message); /** * Handle focus acquire requests. diff --git a/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIManager.h b/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIManager.h index 1e5f57f..56de6c1 100644 --- a/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIManager.h +++ b/modules/Alexa/SampleApp/include/SampleApp/GUI/GUIManager.h @@ -178,7 +178,7 @@ class GUIManager /// @{ void handleTapToTalk() override; - void handleHoldToTalk() override; + void handleHoldToTalk(bool start) override; void handleMicrophoneToggle() override; @@ -219,7 +219,8 @@ class GUIManager void handleRenderDocumentResult(std::string token, bool result, std::string error) override; - void handleExecuteCommandsResult(std::string token, bool result, std::string error) override; + void handleExecuteCommandsResult(const std::string& token, const std::string& event, const std::string& message) + override; void handleActivityEvent( alexaSmartScreenSDK::smartScreenSDKInterfaces::ActivityEvent event, @@ -469,9 +470,6 @@ class GUIManager /// The wake word audio provider. alexaClientSDK::capabilityAgents::aip::AudioProvider m_wakeWordAudioProvider; - /// Whether a hold is currently occurring. - bool m_isHoldOccurring; - /// Whether a tap is currently occurring. bool m_isTapOccurring; diff --git a/modules/Alexa/SampleApp/src/AplClientBridge.cpp b/modules/Alexa/SampleApp/src/AplClientBridge.cpp index 5479775..050f27e 100644 --- a/modules/Alexa/SampleApp/src/AplClientBridge.cpp +++ b/modules/Alexa/SampleApp/src/AplClientBridge.cpp @@ -150,9 +150,14 @@ void AplClientBridge::onSendEvent(const std::string& token, const std::string& e m_executor.submit([this, token, event] { m_guiManager->handleUserEvent(token, event); }); } -void AplClientBridge::onCommandExecutionComplete(const std::string& token, bool result) { +void AplClientBridge::onCommandExecutionComplete( + const std::string& token, + APLClient::AplCommandExecutionEvent event, + const std::string& message) { ACSDK_DEBUG9(LX(__func__)); - m_executor.submit([this, token, result] { m_guiManager->handleExecuteCommandsResult(token, result, ""); }); + m_executor.submit([this, token, event, message] { + m_guiManager->handleExecuteCommandsResult(token, APLClient::commandExecutionEventToString(event), message); + }); } void AplClientBridge::onRenderDocumentComplete(const std::string& token, bool result, const std::string& error) { @@ -362,6 +367,11 @@ void AplClientBridge::executeCommands(const std::string& jsonPayload, const std: auto aplClientRenderer = getAplClientRendererFromAplToken(token); if (aplClientRenderer) { aplClientRenderer->executeCommands(jsonPayload, token); + } else { + m_guiManager->handleExecuteCommandsResult( + token, + APLClient::commandExecutionEventToString(APLClient::AplCommandExecutionEvent::FAILED), + "No document renderer instance for token."); } }); } diff --git a/modules/Alexa/SampleApp/src/GUI/GUIClient.cpp b/modules/Alexa/SampleApp/src/GUI/GUIClient.cpp index fcbda73..c9df923 100644 --- a/modules/Alexa/SampleApp/src/GUI/GUIClient.cpp +++ b/modules/Alexa/SampleApp/src/GUI/GUIClient.cpp @@ -35,8 +35,11 @@ static const std::string MESSAGE_TYPE_INIT_RESPONSE("initResponse"); /// The message type for Tap To Talk. static const std::string MESSAGE_TYPE_TAP_TO_TALK("tapToTalk"); -/// The message type for Hold To Talk. -static const std::string MESSAGE_TYPE_HOLD_TO_TALK("holdToTalk"); +/// The message type for Hold To Talk start. +static const std::string MESSAGE_TYPE_HOLD_TO_TALK_START("holdToTalkStart"); + +/// The message type for Hold To Talk end. +static const std::string MESSAGE_TYPE_HOLD_TO_TALK_END("holdToTalkEnd"); /// The message type for Focus acquire request. static const std::string MESSAGE_TYPE_FOCUS_ACQUIRE_REQUEST("focusAcquireRequest"); @@ -331,8 +334,11 @@ GUIClient::GUIClient( m_captionManager{SmartScreenCaptionStateManager(miscStorage)} { m_messageHandlers.emplace( MESSAGE_TYPE_TAP_TO_TALK, [this](rapidjson::Document& payload) { executeHandleTapToTalk(payload); }); + m_messageHandlers.emplace(MESSAGE_TYPE_HOLD_TO_TALK_START, [this](rapidjson::Document& payload) { + executeHandleHoldToTalkStart(payload); + }); m_messageHandlers.emplace( - MESSAGE_TYPE_HOLD_TO_TALK, [this](rapidjson::Document& payload) { executeHandleHoldToTalk(payload); }); + MESSAGE_TYPE_HOLD_TO_TALK_END, [this](rapidjson::Document& payload) { executeHandleHoldToTalkEnd(payload); }); m_messageHandlers.emplace(MESSAGE_TYPE_FOCUS_ACQUIRE_REQUEST, [this](rapidjson::Document& payload) { executeHandleFocusAcquireRequest(payload); }); @@ -608,8 +614,12 @@ void GUIClient::executeHandleTapToTalk(rapidjson::Document& message) { m_guiManager->handleTapToTalk(); } -void GUIClient::executeHandleHoldToTalk(rapidjson::Document& message) { - m_guiManager->handleHoldToTalk(); +void GUIClient::executeHandleHoldToTalkStart(rapidjson::Document& message) { + m_guiManager->handleHoldToTalk(true); +} + +void GUIClient::executeHandleHoldToTalkEnd(rapidjson::Document& message) { + m_guiManager->handleHoldToTalk(false); } void GUIClient::executeHandleAcceptCall(rapidjson::Document& message) { diff --git a/modules/Alexa/SampleApp/src/GUI/GUIManager.cpp b/modules/Alexa/SampleApp/src/GUI/GUIManager.cpp index fa937ec..3b269e1 100644 --- a/modules/Alexa/SampleApp/src/GUI/GUIManager.cpp +++ b/modules/Alexa/SampleApp/src/GUI/GUIManager.cpp @@ -127,7 +127,6 @@ GUIManager::GUIManager( m_playerActivityState{PlayerActivity::FINISHED} { m_guiClient = guiClient; m_isMicOn = true; - m_isHoldOccurring = false; m_isTapOccurring = false; m_isSpeakingOrListening = false; m_clearAlertChannelOnForegrounded = false; @@ -240,15 +239,20 @@ void GUIManager::handleTapToTalk() { ; } -void GUIManager::handleHoldToTalk() { - ACSDK_DEBUG9(LX("handleHoldToTalk")); - m_executor.submit([this]() { +void GUIManager::handleHoldToTalk(bool start) { + ACSDK_DEBUG9(LX(__func__).d("start", start)); + m_executor.submit([this, start]() { handleASRProfileChanged(m_holdToTalkAudioProvider.profile); if (!m_isMicOn) { return; } bool activeCameraWithMicrophone = false; + // Set the value of @c isHoldOccurring to what UI thinks it should be. + // There could be circumstances where the user applications might fall out + // of sync with SDK about the status of hold-to-talk. + bool isHoldOccurring = !start; + #ifdef ENABLE_RTCSC // Mic input is fully routed to active camera and not Alexa AIP when: // - ASR Profile is CLOSE_TALK (physical remote mic input) @@ -264,12 +268,12 @@ void GUIManager::handleHoldToTalk() { smartScreenSDKInterfaces::AudioState::UNKNOWN != m_cameraMicrophoneAudioState) && smartScreenSDKInterfaces::ConcurrentTwoWayTalk::UNKNOWN != m_cameraConcurrentTwoWayTalk); #endif - if (!m_isHoldOccurring) { + if (!isHoldOccurring) { // If we have no active 2-way talk camera, route mic input to Alexa AIP provider as usual. - m_isHoldOccurring = + isHoldOccurring = activeCameraWithMicrophone || m_ssClient->notifyOfHoldToTalkStart(m_holdToTalkAudioProvider).get(); } else { - m_isHoldOccurring = false; + isHoldOccurring = false; if (!activeCameraWithMicrophone) { m_ssClient->notifyOfHoldToTalkEnd(); } @@ -279,9 +283,9 @@ void GUIManager::handleHoldToTalk() { // If we have an active 2-way camera, enable/disable its microphone. if (activeCameraWithMicrophone) { // Set camera mic state - handleSetCameraMicrophoneState(m_isHoldOccurring); + handleSetCameraMicrophoneState(isHoldOccurring); // Inform GUI of camera mic state - m_guiClient->handleCameraMicrophoneStateChanged(m_isHoldOccurring); + m_guiClient->handleCameraMicrophoneStateChanged(isHoldOccurring); } #endif }); @@ -580,9 +584,12 @@ void GUIManager::handleRenderDocumentResult(std::string token, bool result, std: m_executor.submit([this, result, token, error]() { m_ssClient->handleRenderDocumentResult(token, result, error); }); } -void GUIManager::handleExecuteCommandsResult(std::string token, bool result, std::string error) { +void GUIManager::handleExecuteCommandsResult( + const std::string& token, + const std::string& event, + const std::string& message) { m_executor.submit( - [this, token, result, error]() { m_ssClient->handleExecuteCommandsResult(token, result, error); }); + [this, token, event, message]() { m_ssClient->handleExecuteCommandsResult(token, event, message); }); } void GUIManager::handleActivityEvent(smartScreenSDKInterfaces::ActivityEvent event, const std::string& source) { diff --git a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AlexaPresentation.h b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AlexaPresentation.h index cb9520e..d460731 100644 --- a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AlexaPresentation.h +++ b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AlexaPresentation.h @@ -51,6 +51,7 @@ #include #include +#include "AplCommandsExecutionEvent.h" #include "TimeoutType.h" namespace alexaSmartScreenSDK { @@ -248,11 +249,14 @@ class AlexaPresentation /** * Process result of ExecuteCommands directive. * - * @param token request token - * @param result rendering result (true on executed, false on exception). - * @param error error message provided in case if result is false - */ - void processExecuteCommandsResult(const std::string& token, const bool result, const std::string& error); + * @param token the execute command result token. + * @param event the @c AplCommandExecution event received from the runtime. + * @param message the execute command completion message. + */ + void processExecuteCommandsResult( + const std::string& token, + AplCommandExecutionEvent event, + const std::string& message); /** * Process activity change event from GUI Client. diff --git a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AplCommandsExecutionEvent.h b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AplCommandsExecutionEvent.h new file mode 100644 index 0000000..ec4ab19 --- /dev/null +++ b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/include/AlexaPresentation/AplCommandsExecutionEvent.h @@ -0,0 +1,77 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#ifndef ALEXA_SMART_SCREEN_SDK_CAPABILITYAGENTS_ALEXAPRESENTATION_INCLUDE_ALEXAPRESENTATION_APLCOMMANDEXECUTIONEVENT_H_ +#define ALEXA_SMART_SCREEN_SDK_CAPABILITYAGENTS_ALEXAPRESENTATION_INCLUDE_ALEXAPRESENTATION_APLCOMMANDEXECUTIONEVENT_H_ + +#include + +#include + +namespace alexaSmartScreenSDK { +namespace smartScreenCapabilityAgents { +namespace alexaPresentation { + +static const std::string RESOLVED_STR = "RESOLVED"; +static const std::string TERMINATED_STR = "TERMINATED"; +static const std::string FAILED_STR = "FAILED"; + +/// Enumeration of APL Command Execution Events that can be reported to the agent by the runtime. +enum class AplCommandExecutionEvent { + /// APL Runtime resolved the commands sequence. + RESOLVED, + + /// APL Runtime terminated the commands sequence. + TERMINATED, + + /// APL Runtime failed to parse/handle the commands sequence. + FAILED +}; + +/** + * This is a function to convert the @c AplCommandExecutionEvent to a string. + */ +inline std::string commandExecutionEventToString(const AplCommandExecutionEvent event) { + switch (event) { + case AplCommandExecutionEvent::RESOLVED: + return "RESOLVED"; + case AplCommandExecutionEvent::TERMINATED: + return "TERMINATED"; + case AplCommandExecutionEvent::FAILED: + return "FAILED"; + } + return "UNKNOWN"; +} + +/** + * This is a function to convert a string to a @c AplCommandExecutionEvent. + */ +inline AplCommandExecutionEvent stringToCommandExecutionEvent(const std::string& eventStr) { + if (RESOLVED_STR == eventStr) { + return AplCommandExecutionEvent::RESOLVED; + } else if (TERMINATED_STR == eventStr) { + return AplCommandExecutionEvent::TERMINATED; + } else if (FAILED_STR == eventStr) { + return AplCommandExecutionEvent::FAILED; + } + + return AplCommandExecutionEvent::FAILED; +} + +} // namespace alexaPresentation +} // namespace smartScreenCapabilityAgents +} // namespace alexaSmartScreenSDK + +#endif // ALEXA_SMART_SCREEN_SDK_CAPABILITYAGENTS_ALEXAPRESENTATION_INCLUDE_ALEXAPRESENTATION_APLCOMMANDEXECUTIONEVENT_H_ diff --git a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/src/AlexaPresentation.cpp b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/src/AlexaPresentation.cpp index 3b6a317..e12c2ea 100644 --- a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/src/AlexaPresentation.cpp +++ b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/src/AlexaPresentation.cpp @@ -1414,32 +1414,37 @@ void AlexaPresentation::processRenderDocumentResult( void AlexaPresentation::processExecuteCommandsResult( const std::string& token, - const bool result, - const std::string& error) { - m_executor->submit([this, token, result, error]() { - ACSDK_DEBUG3(LX("processExecuteCommandsResultExecutor").d("token", token).d("result", result)); - - bool isSuccess = result; - if (token.empty()) { - ACSDK_ERROR(LX("processExecuteCommandsResultExecutorFailed").d("reason", "token is empty")); - isSuccess = false; - } else if (token != m_lastExecuteCommandTokenAndDirective.first) { - ACSDK_ERROR(LX("processExecuteCommandsResultExecutorFailed") - .d("reason", "asked to process missing directive") - .d("messageId", token)); - isSuccess = false; - } else if (!m_lastExecuteCommandTokenAndDirective.second) { - ACSDK_ERROR(LX("processExecuteCommandsResultExecutorFailed") - .d("reason", "directive to handle is null") - .d("messageId", token)); - isSuccess = false; + AplCommandExecutionEvent event, + const std::string& message) { + m_executor->submit([this, token, event, message]() { + ACSDK_DEBUG3(LX("processExecuteCommandsResultExecutor") + .d("token", token) + .d("event", commandExecutionEventToString(event))); + + bool isFailed = AplCommandExecutionEvent::FAILED == event; + std::string failureMessage; + if (isFailed) { + failureMessage = message; + } else { + // If runtime had no failures, ensure that this was still a valid directive + if (token.empty()) { + isFailed = true; + failureMessage = "token is empty"; + } else if (token != m_lastExecuteCommandTokenAndDirective.first) { + isFailed = true; + failureMessage = "asked to process missing directive"; + } else if (!m_lastExecuteCommandTokenAndDirective.second) { + isFailed = true; + failureMessage = "directive to handle is null"; + } } - if (isSuccess) { - setHandlingCompleted(m_lastExecuteCommandTokenAndDirective.second); - } else { + if (isFailed) { + ACSDK_ERROR(LX("processExecuteCommandsResultExecutorFailed").d("token", token).d("reason", failureMessage)); sendExceptionEncounteredAndReportFailed( - m_lastExecuteCommandTokenAndDirective.second, "Commands execution failed: " + error); + m_lastExecuteCommandTokenAndDirective.second, "Commands execution failed: " + failureMessage); + } else { + setHandlingCompleted(m_lastExecuteCommandTokenAndDirective.second); } m_lastExecuteCommandTokenAndDirective.first.clear(); diff --git a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/test/AlexaPresentationTest.cpp b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/test/AlexaPresentationTest.cpp index 82db4dc..3455779 100644 --- a/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/test/AlexaPresentationTest.cpp +++ b/modules/Alexa/SmartScreenCapabilityAgents/AlexaPresentation/test/AlexaPresentationTest.cpp @@ -39,6 +39,7 @@ #include #include "AlexaPresentation/AlexaPresentation.h" +#include "AlexaPresentation/AplCommandsExecutionEvent.h" namespace alexaSmartScreenSDK { namespace smartScreenCapabilityAgents { @@ -869,7 +870,7 @@ TEST_F(AlexaPresentationTest, testExecuteCommandAfterMismatchedAPLCard) { m_AlexaPresentation->CapabilityAgent::preHandleDirective(directive1, std::move(m_mockDirectiveHandlerResult)); m_AlexaPresentation->CapabilityAgent::handleDirective(MESSAGE_ID); - m_AlexaPresentation->processExecuteCommandsResult(MESSAGE_ID, true, ""); + m_AlexaPresentation->processExecuteCommandsResult(MESSAGE_ID, AplCommandExecutionEvent::RESOLVED, ""); m_executor->waitForSubmittedTasks(); } @@ -911,7 +912,7 @@ TEST_F(AlexaPresentationTest, testExecuteCommandAfterRightAPL) { m_AlexaPresentation->CapabilityAgent::preHandleDirective(directive1, std::move(m_mockDirectiveHandlerResult)); m_AlexaPresentation->CapabilityAgent::handleDirective(MESSAGE_ID_2); - m_AlexaPresentation->processExecuteCommandsResult("APL_TOKEN", true, ""); + m_AlexaPresentation->processExecuteCommandsResult("APL_TOKEN", AplCommandExecutionEvent::RESOLVED, ""); m_executor->waitForSubmittedTasks(); } diff --git a/modules/Alexa/SmartScreenSDKInterfaces/include/SmartScreenSDKInterfaces/GUIServerInterface.h b/modules/Alexa/SmartScreenSDKInterfaces/include/SmartScreenSDKInterfaces/GUIServerInterface.h index e7830f5..eb1b9b3 100644 --- a/modules/Alexa/SmartScreenSDKInterfaces/include/SmartScreenSDKInterfaces/GUIServerInterface.h +++ b/modules/Alexa/SmartScreenSDKInterfaces/include/SmartScreenSDKInterfaces/GUIServerInterface.h @@ -38,8 +38,9 @@ class GUIServerInterface { /** * Handle HoldToTalk event. + * @param start @c true if holdToTalk is being started, @c false otherwise. */ - virtual void handleHoldToTalk() = 0; + virtual void handleHoldToTalk(bool start) = 0; /** * Toggles the microphone state if the Sample App was built with wake word. When the microphone is turned off, the @@ -156,10 +157,13 @@ class GUIServerInterface { * Handle ExecuteCommands result message. * * @param token the execute command result token. - * @param result the execute command result. - * @param error the execute command error message. + * @param event the command execution event. + * @param message the execute command completion message. */ - virtual void handleExecuteCommandsResult(std::string token, bool result, std::string error) = 0; + virtual void handleExecuteCommandsResult( + const std::string& token, + const std::string& event, + const std::string& message) = 0; /** * Handle activityEvent message. diff --git a/modules/Alexa/Utils/include/Utils/SmartScreenSDKVersion.h b/modules/Alexa/Utils/include/Utils/SmartScreenSDKVersion.h index 6730bb0..ccc572a 100644 --- a/modules/Alexa/Utils/include/Utils/SmartScreenSDKVersion.h +++ b/modules/Alexa/Utils/include/Utils/SmartScreenSDKVersion.h @@ -25,7 +25,7 @@ namespace utils { /// NOTE: To make changes to this file you *MUST* do so via SmartScreenSDKVersion.h.in. namespace smartScreenSDKVersion{ inline static std::string getCurrentVersion(){ - return "2.9.0"; + return "2.9.1"; } inline static int getMajorVersion(){ return 2; diff --git a/modules/GUI/SDK-GUI-API.md b/modules/GUI/SDK-GUI-API.md index 6da2412..4cc7840 100644 --- a/modules/GUI/SDK-GUI-API.md +++ b/modules/GUI/SDK-GUI-API.md @@ -387,7 +387,7 @@ See : https://developer.amazon.com/docs/alexa-voice-service/speechrecognizer.htm } ``` -## holdToTalk +## holdToTalkStart This message instructs the SDK to open up the microphone and listen for an utterance using the `PRESS_AND_HOLD` initiator. @@ -395,7 +395,19 @@ See : https://developer.amazon.com/docs/alexa-voice-service/speechrecognizer.htm ```javascript { - type: 'holdToTalk' + type: 'holdToTalkStart' +} +``` + +## holdToTalkEnd + +This message instructs the SDK to close the microphone that was opened previously with `PRESS_AND_HOLD` initiator. + +See : https://developer.amazon.com/docs/alexa-voice-service/speechrecognizer.html#initiator + +```javascript +{ + type: 'holdToTalkEnd' } ``` diff --git a/modules/GUI/config/SmartScreenSDKConfig.md b/modules/GUI/config/SmartScreenSDKConfig.md index 1a5d4b6..37e11b7 100644 --- a/modules/GUI/config/SmartScreenSDKConfig.md +++ b/modules/GUI/config/SmartScreenSDKConfig.md @@ -176,7 +176,7 @@ Config for device input keys. | Parameter | Type | Required | Description | ------------- |------- |:-----: | ----- | -| talkKey | [Device Key](#device-key-parameters) | Yes | Key used in the GUI App to send either a [tapToTalk](../SDK-GUI-API.md#taptotalk) or [holdToTalk](../SDK-GUI-API.md#holdtotalk) message to the SDK based on `AudioInputInitiator` parameter defined in the [AppConfig](#appconfig-parameters). +| talkKey | [Device Key](#device-key-parameters) | Yes | Key used in the GUI App to send either a [tapToTalk](../SDK-GUI-API.md#taptotalk), [holdToTalkStart](../SDK-GUI-API.md#holdtotalkstart) or [holdToTalkEnd](../SDK-GUI-API.md#holdtotalkend) message to the SDK based on `AudioInputInitiator` parameter defined in the [AppConfig](#appconfig-parameters). | backKey | [Device Key](#device-key-parameters) | Yes | Key used in the GUI App to send a [navigationEvent](../SDK-GUI-API.md#navigationevent) to the SDK with event type `BACK`. | exitKey | [Device Key](#device-key-parameters) | Yes | Key used in the GUI App to send a [navigationEvent](../SDK-GUI-API.md#navigationevent) to the SDK with event type `EXIT`. | toggleCaptionsKey | [Device Key](#device-key-parameters) | Yes | Key used in the GUI App to send a [toggleCaptionsEvent](../SDK-GUI-API.md#togglecaptionsevent) to the SDK. diff --git a/modules/GUI/js/package-lock.json b/modules/GUI/js/package-lock.json index 24dfbd6..b26b2db 100644 --- a/modules/GUI/js/package-lock.json +++ b/modules/GUI/js/package-lock.json @@ -348,9 +348,6 @@ "color-convert": "^2.0.1" } }, - "apl-client": { - "version": "file:../../Alexa/APLClientLibrary/apl-client-js" - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1160,9 +1157,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "mkdirp": { "version": "0.5.5", @@ -1173,9 +1170,9 @@ } }, "nanoid": { - "version": "3.1.30", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz", - "integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", "dev": true }, "neo-async": { @@ -1993,4 +1990,4 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } -} +} \ No newline at end of file diff --git a/modules/GUI/js/package.json b/modules/GUI/js/package.json index 91ac148..484e1c1 100644 --- a/modules/GUI/js/package.json +++ b/modules/GUI/js/package.json @@ -32,4 +32,4 @@ "html-webpack-plugin": "^5.3.2", "webpack-cli": "^4.5.0" } -} +} \ No newline at end of file diff --git a/modules/GUI/js/src/app.tsx b/modules/GUI/js/src/app.tsx index 670c962..ddddce3 100644 --- a/modules/GUI/js/src/app.tsx +++ b/modules/GUI/js/src/app.tsx @@ -78,7 +78,7 @@ const HOST = 'localhost'; const PORT = 8933; /// The minimum SmartScreenSDK version required for this runtime. -const SMART_SCREEN_SDK_MIN_VERSION = '2.9'; +const SMART_SCREEN_SDK_MIN_VERSION = '2.9.1'; /// Indicates whether the SDK has built with WebSocket SSL Disabled. declare const DISABLE_WEBSOCKET_SSL : boolean; @@ -341,8 +341,8 @@ export class App extends React.Component { switch (this.deviceAppConfig.audioInputInitiator) { case AudioInputInitiator.PRESS_AND_HOLD : { - this.talkButtonDownMessage = 'holdToTalk'; - this.talkButtonUpMessage = 'holdToTalk'; + this.talkButtonDownMessage = 'holdToTalkStart'; + this.talkButtonUpMessage = 'holdToTalkEnd'; break; } case AudioInputInitiator.TAP : { diff --git a/modules/GUI/js/src/components/APLRendererWindow.tsx b/modules/GUI/js/src/components/APLRendererWindow.tsx index 0bc1ac2..a09271b 100644 --- a/modules/GUI/js/src/components/APLRendererWindow.tsx +++ b/modules/GUI/js/src/components/APLRendererWindow.tsx @@ -291,7 +291,7 @@ export class APLRendererWindow extends React.Component