From b9bda20d81ea44ed8265de8819eb95e2e31dabf9 Mon Sep 17 00:00:00 2001 From: asanoaozora Date: Tue, 26 Sep 2017 13:55:44 +0200 Subject: update speech POC and connect it to navigation (some improvements needed) --- api/franca/hmi/speechservice/SpeechOutput.fidl | 2 +- .../genivi-speechservice-speechoutput.xml | 10 +- src/navigation/build.sh | 28 ++- .../genivi_mapviewer_mapviewercontrol.cxx | 11 +- .../genivi_navigationcore_guidance.cxx | 24 +- src/navigation/run | 18 +- src/speech-service/CMakeLists.txt | 101 ++++++++ src/speech-service/build.sh | 78 ++++++ src/speech-service/kill-all | 4 + src/speech-service/log.h | 154 ++++++++++++ src/speech-service/main.cpp | 276 +++++++++++++++++++++ src/speech-service/run | 41 +++ src/speech-service/test-speech.py | 89 +++++++ src/speech/CMakeLists.txt | 12 +- src/speech/main.cpp | 2 +- src/speech/test-speech-capi.py | 12 +- test/navigation/script/genivi.py | 36 +++ test/navigation/script/lbs-api-test.e4p | 3 +- test/navigation/script/test-speech.py | 111 +++++++++ 19 files changed, 976 insertions(+), 36 deletions(-) create mode 100644 src/speech-service/CMakeLists.txt create mode 100755 src/speech-service/build.sh create mode 100755 src/speech-service/kill-all create mode 100644 src/speech-service/log.h create mode 100644 src/speech-service/main.cpp create mode 100755 src/speech-service/run create mode 100755 src/speech-service/test-speech.py create mode 100755 test/navigation/script/test-speech.py diff --git a/api/franca/hmi/speechservice/SpeechOutput.fidl b/api/franca/hmi/speechservice/SpeechOutput.fidl index 98e94e1..3f4768c 100644 --- a/api/franca/hmi/speechservice/SpeechOutput.fidl +++ b/api/franca/hmi/speechservice/SpeechOutput.fidl @@ -7,7 +7,7 @@ // Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with // this file, You can obtain one at http://mozilla.org/MPL/2.0/. -package org.genivi.hmi.speechoutputservice +package org.genivi.hmi.speechservice import org.genivi.CommonTypes.* from "../../CommonTypes.fidl" diff --git a/api/speech-service/genivi-speechservice-speechoutput.xml b/api/speech-service/genivi-speechservice-speechoutput.xml index 35838c3..6b162cc 100644 --- a/api/speech-service/genivi-speechservice-speechoutput.xml +++ b/api/speech-service/genivi-speechservice-speechoutput.xml @@ -24,13 +24,13 @@ openPrompter = Must be called to open a SpeechOutputService session and to get the audio connection. - + connectionType (of type ConnectionType) = Sets the Audio connection that should be used for the prompter application. enum[CT_NAVIGATION (null), CT_READER (null), CT_GEN_HIGH (null), CT_GEN_MEDIUM (null), CT_GEN_LOW (null), CT_MAX (null)] - + preProcessingType (of type PreProcessingType) = Sets the text normaization mode and which active prompt data base will be activated. enum[PPT_DIALOG (null), PPT_NAVIGATION (null), PPT_NONE (null), PPT_READER (null), PPT_MAX (null)] @@ -72,7 +72,7 @@ notifyConnectionStatus = Notifies the connection status - + connectionStatus (of type ConnectionStatus) = Client connection status. enum[CS_UNKNOWN (null), CS_ESTABLISHED (null), CS_REFUSED (null), CS_POSSIBLE (null), CS_PENDING (null), CS_PAUSED (null), CS_TERMINATED (null), CS_MAX (null)] @@ -100,7 +100,7 @@ notifyQueueStatus = Notifies the queue status. - + queueStatus (of type QueueStatus) = Fill status of the text buffer. enum[QS_UNKNOWN (null), QS_FULL (null), QS_HIGH_FILL (null), QS_LOW_FILL (null), QS_MAX (null)] @@ -111,7 +111,7 @@ notifyTTSStatus = Notifies the TTS engine status. - + ttsStatus (of type TtsStatus) = Current status of the TTS. enum[TS_UNKNOWN (null), TS_NOT_INITIALIZED (null), TS_ACTIVE (null), TS_ABORTED (null), TS_MARKER (null), TS_IDLE (null), TS_ENQUEUED (null), TS_FINISHED (null), TS_FAILED (null), TS_MAX (null)] diff --git a/src/navigation/build.sh b/src/navigation/build.sh index 4a7217e..f8daf55 100755 --- a/src/navigation/build.sh +++ b/src/navigation/build.sh @@ -34,6 +34,8 @@ navit=0 #no build of navit -> -n option poi=0 #no build of poi -> -p option dlt_option="OFF" #no DLT -> -l option debug="OFF" #no debug -> -d option +speech=0 #no build of speech -> -s option +speech_option="OFF" function check_path_for_capi { @@ -61,7 +63,7 @@ function check_path_for_capi commonapi_tools_option="-DWITH_PLUGIN_MIGRATION=ON -DWITH_DBUS_INTERFACE=OFF -DDBUS_LIB_PATH="$DBUS_LIB_PATH" -DCOMMONAPI_DBUS_TOOL_DIR="$COMMONAPI_DBUS_TOOL_DIR" -DCOMMONAPI_TOOL_DIR="$COMMONAPI_TOOL_DIR } -while getopts cdlmhnp opt +while getopts cdlmhnps opt do case $opt in c) @@ -84,9 +86,13 @@ do p) poi=1 ;; + s) + speech=1 + speech_option="ON" + ;; h) echo "Usage:" - echo "$0 [-cdhlmnp]" + echo "$0 [-cdhlmnps]" echo "-c: Rebuild with clean" echo "-d: Enable the debug messages" echo "-h: Help" @@ -94,6 +100,7 @@ do echo "-m: Build with commonAPI plugins (only with -c)" echo "-n: Build navit" echo "-p: Build poi" + echo "-s: Build with speech" exit 1 esac done @@ -143,7 +150,7 @@ cd .. echo 'build navigation' if [ "$clean" = 1 ] then - cmake -DWITH_DLT=$dlt_option $commonapi_tools_option -DWITH_DEBUG=$debug ../ + cmake -DWITH_DLT=$dlt_option $commonapi_tools_option -DWITH_SPEECH=$speech_option -DWITH_DEBUG=$debug ../ echo 'Allow to display Korean and Japanese by replacing a font in the configuration file of navit instances' sed -i -e 's/Liberation Sans/NanumGothic/' ./navit/navit/navit_genivi_mapviewer.xml sed -i -e 's/Liberation Sans/NanumGothic/' ./navit/navit/navit_genivi_navigationcore.xml @@ -166,3 +173,18 @@ then fi cd ../../navigation +#speech +cd ../speech-service +mkdir -p build +cd build +if [ "$speech" = 1 ] +then + echo 'build speech' + if [ "$clean" = 1 ] + then + cmake -DWITH_DLT=$dlt_option -DWITH_DEBUG=$debug ../ + fi + make +fi +cd ../../navigation + diff --git a/src/navigation/map-viewer/mapviewercontrol-plugin/genivi_mapviewer_mapviewercontrol.cxx b/src/navigation/map-viewer/mapviewercontrol-plugin/genivi_mapviewer_mapviewercontrol.cxx index 6082063..702c596 100644 --- a/src/navigation/map-viewer/mapviewercontrol-plugin/genivi_mapviewer_mapviewercontrol.cxx +++ b/src/navigation/map-viewer/mapviewercontrol-plugin/genivi_mapviewer_mapviewercontrol.cxx @@ -1622,12 +1622,19 @@ static void callbackFunction(ilmObjectType object, t_ilm_uint surfaceId, t_ilm_b struct ilmSurfaceProperties pSurfaceProperties; t_ilm_layer renderOrder[2]; + if(object == ILM_LAYER) { + if(created){ + //FIXIT: Need to add tempo + sleep(1); + } + } + if (object == ILM_SURFACE) { if (created) { if (surfaceId == FSA_SURFACE) { //FIXIT: Need to add tempo - sleep(1); + sleep(2); //Grab all the layers - HMI will be pLength-2 and FSA pLength-1 if (ilm_getLayerIDs(&pLength, &ppArray) != ILM_SUCCESS) { @@ -1635,7 +1642,7 @@ static void callbackFunction(ilmObjectType object, t_ilm_uint surfaceId, t_ilm_b } //FIXIT: Since we don't know thep id of hmi_launcher and order of start. - //Guess it is teh last one or the one before navit mapviewer PID. + //Guess it is the last one or the one before navit mapviewer PID. renderOrder[0] = FSA_SURFACE; if (ppArray[pLength - 2] != FSA_SURFACE) renderOrder[1] = SURFACE_OFFSET + ppArray[pLength - 2]; diff --git a/src/navigation/navigation-core/guidance-plugin/genivi_navigationcore_guidance.cxx b/src/navigation/navigation-core/guidance-plugin/genivi_navigationcore_guidance.cxx index a7b8419..782150e 100644 --- a/src/navigation/navigation-core/guidance-plugin/genivi_navigationcore_guidance.cxx +++ b/src/navigation/navigation-core/guidance-plugin/genivi_navigationcore_guidance.cxx @@ -49,7 +49,7 @@ #include #include #include - +#include #include "navigation-common-dbus.h" #include "log.h" @@ -73,11 +73,11 @@ class SpeechOutput SpeechOutput(DBus::Connection &connection) : DBus::ObjectProxy(connection, "/org/genivi/hmi/speechservice/SpeechOutput", - "org.genivi.navigation.hmi.speechservice.SpeechOutput") + "org.genivi.hmi.speechservice.SpeechOutput") { } - void notifyConnectionStatus(const uint32_t& connectionStatus) + void notifyConnectionStatus(const int32_t& connectionStatus) { } @@ -87,12 +87,12 @@ class SpeechOutput } - void notifyQueueStatus(const uint32_t& queueStatus) + void notifyQueueStatus(const int32_t& queueStatus) { } - void notifyTTSStatus(const uint32_t& ttsStatus) + void notifyTTSStatus(const int32_t& ttsStatus) { } @@ -690,12 +690,17 @@ void GuidanceObj::SetVoiceGuidance(const bool& activate, const std::string& voic void GuidanceObj::PlayVoiceManeuver() { +#if (SPEECH_ENABLED) message *messages; messages = navit_get_messages(get_navit()); -#if (SPEECH_ENABLED) - m_speechoutput->openPrompter(GENIVI_SPEECHSERVICE_CT_NAVIGATION,GENIVI_SPEECHSERVICE_PPT_NAVIGATION); - m_speechoutput->addTextChunk(messages); - m_speechoutput->closePrompter(); + if(messages){ + m_speechoutput->openPrompter(GENIVI_SPEECHSERVICE_CT_NAVIGATION,GENIVI_SPEECHSERVICE_PPT_NAVIGATION); + while(messages){ + m_speechoutput->addTextChunk(std::string(messages->text)); + messages=messages->next; + } + m_speechoutput->closePrompter(); + } #endif } @@ -754,6 +759,7 @@ GuidanceObj_Callback(GuidanceObj *obj) } obj->m_guidance->ManeuverChanged(maneuver); LOG_INFO(gCtx,"Maneuver: %d",maneuver); + obj->PlayVoiceManeuver(); } else { LOG_ERROR(gCtx,"Maneuver item not found: %p",item); } diff --git a/src/navigation/run b/src/navigation/run index 24efa16..1430da5 100755 --- a/src/navigation/run +++ b/src/navigation/run @@ -90,6 +90,7 @@ replayer=1 verbose=0 #no debug or log messages displayed center="4612 N 0608 E" poi=0 +speech=0 CUR_DIR=$PWD BIN_DIR=$CUR_DIR/bin @@ -104,7 +105,10 @@ POI_SERVER_RESOURCE_DIR=$CUR_DIR/../../src/poi-service/resource poidatabase=$POI_SERVER_RESOURCE_DIR/empty.db # empty poi database by default -while getopts c:ghnoprvx opt +SPEECH_SERVER=speech-server +SPEECH_OUTPUT_BIN_DIR=$CUR_DIR/../../src/speech-service/bin/ + +while getopts c:ghnoprsvx opt do case $opt in c) @@ -142,6 +146,9 @@ do r) replayer=0 ;; + s) + speech=1 + ;; v) #enable log messages verbose=1 ;; @@ -150,7 +157,7 @@ do ;; h) echo "Usage:" - echo "$0 [-c center][-gnoprvx]" + echo "$0 [-c center][-gnoprsvxh]" echo "-c: Set center (supported values: paris,tokyo,seoul,longitude,latitude). Default is geneve" echo "-g: Run subprocesses within gdb (only with -x)" echo "-h: This help" @@ -158,6 +165,7 @@ do echo "-r: Don't start replayer" echo "-o: Create log file of subprocess output" echo "-p: Launch the poi server" + echo "-s: Launch the speech server" echo "-v: Enable the output debug messages" echo "-x: Run subprocesses in own xterm to get separated log messages" exit 1 @@ -192,6 +200,12 @@ then run "POI service" $POI_SERVER_BIN_DIR/$POI_SERVER -f $poidatabase fi +if [ "$speech" = 1 ] +then + # start the speech server + run "Speech service" $SPEECH_OUTPUT_BIN_DIR/$SPEECH_SERVER +fi + cd $NAVIT_BIN_DIR >bookmark.txt diff --git a/src/speech-service/CMakeLists.txt b/src/speech-service/CMakeLists.txt new file mode 100644 index 0000000..96725e7 --- /dev/null +++ b/src/speech-service/CMakeLists.txt @@ -0,0 +1,101 @@ +########################################################################### +# @licence app begin@ +# SPDX-License-Identifier: MPL-2.0 +# +# Component Name: speech-server +# +# Author: Philippe Colliot +# +# Copyright (C) 2017, PSA GROUP +# +# License: +# This Source Code Form is subject to the terms of the +# Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with +# this file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# @licence end@ +########################################################################### +project(speech-server) +cmake_minimum_required(VERSION 2.8) +find_package(PkgConfig REQUIRED) + +message(STATUS ${PROJECT_NAME}) + +add_definitions("-std=gnu++11") + +option(WITH_DEBUG + "Enable the debug messages" OFF) +option(WITH_DLT + "Enable DLT logging" OFF) + +message(STATUS "WITH_DEBUG = ${WITH_DEBUG}") +message(STATUS "WITH_DLT = ${WITH_DLT}") + +set(API_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../api") +set(DBUS_GENERATED_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/dbus-include") + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin) + +if(${WITH_DLT}) + add_definitions("-DDLT_ENABLED=1") + pkg_check_modules(DLT REQUIRED automotive-dlt) + include_directories( ${DLT_INCLUDE_DIRS} ) + set(LIBRARIES ${LIBRARIES} ${DLT_LIBRARIES}) +endif() + +if(WITH_DEBUG) + add_definitions("-DDEBUG_ENABLED=1") +endif() + +pkg_check_modules(DBUS_CPP dbus-c++-1) +pkg_check_modules(GLIB REQUIRED glib-2.0) +pkg_check_modules(GOBJECT gobject-2.0) +pkg_check_modules(DBUS dbus-1) +pkg_check_modules(DBUS_CPP_GLIB dbus-c++-glib-1) + +#generates the GLib DBus proxies and adaptors +add_subdirectory(${API_DIR}/speech-service "${DBUS_GENERATED_INCLUDE_DIR}/speech-service") + +#add flite dependencies +set(FLITE_INCLUDE_DIRS /usr/include/flite) +set(FLITE_LIBDIR /usr/lib/x86_64-linux-gnu/) +set(FLITE_LIBRARIES /usr/lib/x86_64-linux-gnu/libflite.so /usr/lib/x86_64-linux-gnu/libflite_cmu_us_kal.so) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${COMMON_DIR} + ${DBUS_GENERATED_INCLUDE_DIR}/speech-service + ${DBUS_CPP_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${GOBJECT_INCLUDE_DIRS} + ${DBUS_INCLUDE_DIRS} + ${DBUS_CPP_GLIB_INCLUDE_DIRS} + ${FLITE_INCLUDE_DIRS} +) + +link_directories( + ${DBUS_CPP_LIBRARY_DIRS} + ${GLIB_LIBRARY_DIRS} + ${GOBJECT_LIBRARY_DIRS} + ${DBUS_LIBRARY_DIRS} + ${DBUS_CPP_GLIB_DIRS} + ${FLITE_LIBDIR} +) + +set(LIBRARIES + ${LIBRARIES} + ${DBUS_CPP_LIBRARIES} + ${GLIB_LIBRARIES} + ${GOBJECT_LIBRARIES} + ${DBUS_LIBRARIES} + ${DBUS_CPP_GLIB_LIBRARIES} + ${FLITE_LIBRARIES} +) + +add_executable(${PROJECT_NAME} + main.cpp +) + +target_link_libraries(${PROJECT_NAME} ${LIBRARIES}) + diff --git a/src/speech-service/build.sh b/src/speech-service/build.sh new file mode 100755 index 0000000..2dbb819 --- /dev/null +++ b/src/speech-service/build.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +########################################################################### +# @licence app begin@ +# SPDX-License-Identifier: MPL-2.0 +# +# \copyright Copyright (C) 2013-2017, PSA Group +# +# \file build.sh +# +# \brief This file is part of the Build System for speech. +# +# \author Philippe Colliot +# +# \version 1.0 +# +# This Source Code Form is subject to the terms of the +# Mozilla Public License (MPL), v. 2.0. +# If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# For further information see http://www.genivi.org/. +# +# List of changes: +# +# +# @licence end@ +########################################################################### + +clean=0 #no clean (means no cmake) -> -c option +dlt_option="OFF" #no DLT -> -l option +debug="OFF" #no debug -> -d option + +while getopts cdhl opt +do + case $opt in + c) + clean=1 + ;; + d) + debug="ON" + ;; + l) + dlt_option="ON" + ;; + h) + echo "Usage:" + echo "$0 [-cdhl]" + echo "-c: Rebuild with clean" + echo "-d: Enable the debug messages" + echo "-h: Help" + echo "-l: Build with dlt (only with -c)" + exit 1 + esac +done + +set -e + +if [ "$clean" = 1 ] +then + echo 'clean up the build folder' + if [ -d "./build" ] + then + find ./build ! -name '*.cbp' -type f -exec rm -f {} + + fi +fi + +mkdir -p build +cd build + +echo 'build speech output' +if [ "$clean" = 1 ] +then + cmake -DWITH_DLT=$dlt_option -DWITH_DEBUG=$debug ../ +fi +make + + diff --git a/src/speech-service/kill-all b/src/speech-service/kill-all new file mode 100755 index 0000000..9889cf6 --- /dev/null +++ b/src/speech-service/kill-all @@ -0,0 +1,4 @@ +#!/bin/sh +echo 'kill all remaining process' +kill -9 `ps -ef | grep speech-server | grep -v grep | awk '{print $2}'` + diff --git a/src/speech-service/log.h b/src/speech-service/log.h new file mode 100644 index 0000000..4d946fb --- /dev/null +++ b/src/speech-service/log.h @@ -0,0 +1,154 @@ +/************************************************************************** +* @licence app begin@ +* +* SPDX-License-Identifier: MPL-2.0 +* +* \ingroup GNSSService +* +* \copyright Copyright (C) BMW Car IT GmbH 2011 +* Copyright (C) 2013, XS Embedded GmbH +* +* \license +* This Source Code Form is subject to the terms of the +* Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with +* this file, You can obtain one at http://mozilla.org/MPL/2.0/. +* +* @licence end@ +**************************************************************************/ + +#ifndef INCLUDE_LOG +#define INCLUDE_LOG + +// turn-on via cmake define: +// $ cmake -DWITH_DLT=1 -DDEBUG_ENABLED=1 .. + +#if (!DLT_ENABLED) +/*****************************************************************************/ +// use printf +#include + +// some type-name used instead of DLT context +typedef const char* NoDltContext; + +#define DLT_DECLARE_CONTEXT(CONTEXT) \ + NoDltContext CONTEXT; + +#define DLT_IMPORT_CONTEXT(CONTEXT) \ + extern NoDltContext CONTEXT; + +#define DLT_REGISTER_CONTEXT(CONTEXT, CONTEXT_ID, DESC) \ + CONTEXT = CONTEXT_ID; + +#define DLT_REGISTER_APP(CONTEXT, DESC) ; + +#define DLT_UNREGISTER_CONTEXT(CONTEXT) ; +#define DLT_UNREGISTER_APP() ; +#define dlt_free() ; + +// log calls +#if (!DEBUG_ENABLED) + +#define LOG_VERBOSE_MSG(context, msg) ; +#define LOG_VERBOSE(context, fmt, ...) ; + +#define LOG_DEBUG_MSG(context, msg) ; +#define LOG_DEBUG(context, fmt, ...) ; + +#define LOG_INFO_MSG(context, msg) ; +#define LOG_INFO(context, fmt, ...) ; + +#define LOG_WARNING_MSG(context, msg) ; +#define LOG_WARNING(context, fmt, ...) ; + +#else + +#define LOG_VERBOSE_MSG(context, msg) \ + fprintf(stderr, "[VERBO][%4s] " msg "\n", context) +#define LOG_VERBOSE(context, fmt, ...) \ + fprintf(stderr, "[VERBO][%4s] " fmt "\n", context, __VA_ARGS__) + +#define LOG_DEBUG_MSG(context, msg) \ + fprintf(stderr, "[DEBUG][%4s] " msg "\n", context) +#define LOG_DEBUG(context, fmt, ...) \ + fprintf(stderr, "[DEBUG][%4s] " fmt "\n", context, __VA_ARGS__) + +#define LOG_INFO_MSG(context, msg) \ + fprintf(stderr, "[INFO ][%4s] " msg "\n", context) +#define LOG_INFO(context, fmt, ...) \ + fprintf(stderr, "[INFO ][%4s] " fmt "\n", context, __VA_ARGS__) + +#define LOG_WARNING_MSG(context, msg) \ + fprintf(stderr, "[WARN ][%4s] " msg "\n", context) +#define LOG_WARNING(context, fmt, ...) \ + fprintf(stderr, "[WARN ][%4s] " fmt "\n", context, __VA_ARGS__) +#endif + +#define LOG_ERROR_MSG(context, msg) \ + fprintf(stderr, "[ERROR][%4s] " msg "\n", context) +#define LOG_ERROR(context, fmt, ...) \ + fprintf(stderr, "[ERROR][%4s] " fmt "\n", context, __VA_ARGS__) + +#define LOG_FATAL_MSG(context, msg) \ + fprintf(stderr, "[FATAL][%4s] " msg "\n", context) +#define LOG_FATAL(context, fmt, ...) \ + fprintf(stderr, "[FATAL][%4s] " fmt "\n", context, __VA_ARGS__) + +#else /* DLT_ENABLED */ +/*****************************************************************************/ +// use DLT +#include "dlt.h" + +typedef const char* Context; + +#define LOG_VERBOSE_MSG(context, msg) \ + DLT_LOG(context, DLT_LOG_VERBOSE, DLT_STRING(msg)); +#define LOG_VERBOSE(context, fmt, ...) \ + { \ + char logBuffer[256]; \ + sprintf(logBuffer, fmt, __VA_ARGS__); \ + DLT_LOG(context, DLT_LOG_VERBOSE, DLT_STRING(logBuffer)); \ + } +#define LOG_DEBUG_MSG(context, msg) \ + DLT_LOG(context, DLT_LOG_DEBUG, DLT_STRING(msg)); +#define LOG_DEBUG(context, fmt, ...) \ + { \ + char logBuffer[256]; \ + sprintf(logBuffer, fmt, __VA_ARGS__); \ + DLT_LOG(context, DLT_LOG_DEBUG, DLT_STRING(logBuffer)); \ + } +#define LOG_INFO_MSG(context, msg) \ + DLT_LOG(context, DLT_LOG_INFO, DLT_STRING(msg)); +#define LOG_INFO(context, fmt, ...) \ + { \ + char logBuffer[256]; \ + sprintf(logBuffer, fmt, __VA_ARGS__); \ + DLT_LOG(context, DLT_LOG_INFO, DLT_STRING(logBuffer)); \ + } +#define LOG_WARNING_MSG(context, msg) \ + DLT_LOG(context, DLT_LOG_WARN, DLT_STRING(msg)); +#define LOG_WARNING(context, fmt, ...) \ + { \ + char logBuffer[256]; \ + sprintf(logBuffer, fmt, __VA_ARGS__); \ + DLT_LOG(context, DLT_LOG_WARN, DLT_STRING(logBuffer)); \ + } +#define LOG_ERROR_MSG(context, msg) \ + DLT_LOG(context, DLT_LOG_ERROR, DLT_STRING(msg)); +#define LOG_ERROR(context, fmt, ...) \ + { \ + char logBuffer[256]; \ + sprintf(logBuffer, fmt, __VA_ARGS__); \ + DLT_LOG(context, DLT_LOG_ERROR, DLT_STRING(logBuffer)); \ + } +#define LOG_FATAL_MSG(context, msg) \ + DLT_LOG(context, DLT_LOG_FATAL, DLT_STRING(msg)); +#define LOG_FATAL(context, fmt, ...) \ + { \ + char logBuffer[256]; \ + sprintf(logBuffer, fmt, __VA_ARGS__); \ + DLT_LOG(context, DLT_LOG_FATAL, DLT_STRING(logBuffer)); \ + } + +#endif /* DLT_ENABLED */ + +#endif /* INCLUDE_LOG */ diff --git a/src/speech-service/main.cpp b/src/speech-service/main.cpp new file mode 100644 index 0000000..df45857 --- /dev/null +++ b/src/speech-service/main.cpp @@ -0,0 +1,276 @@ +/** +* @licence app begin@ +* SPDX-License-Identifier: MPL-2.0 +* +* \copyright Copyright (C) 2013-2017, PSA GROUP +* +* \file main.cpp +* +* \brief This file is part of the speech service proof of concept. +* +* \author Philippe Colliot +* \brief Some parts of the code has been inspired by the following people: +* \brief Mario Thielert, David Kämpf, Dominique Massonie +* +* \version 1.0 +* +* This Source Code Form is subject to the terms of the +* Mozilla Public License (MPL), v. 2.0. +* If a copy of the MPL was not distributed with this file, +* You can obtain one at http://mozilla.org/MPL/2.0/. +* +* For further information see http://www.genivi.org/. +* +* List of changes: +* , , +* +* @licence end@ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "genivi-speechservice-constants.h" +#include "genivi-speechservice-speechoutput_adaptor.h" +#include "log.h" +#include +#include + +extern "C" { + cst_voice* register_cmu_us_kal(const char *voxdir); + void unregister_cmu_us_kal(cst_voice *vox); +} + +DLT_DECLARE_CONTEXT(gCtx) + +static const char* speech_SERVICE_NAME = "org.genivi.hmi.speechservice.SpeechOutput"; +static const char* speech_OBJECT_PATH = "/org/genivi/hmi/speechservice/SpeechOutput"; + +static DBus::Glib::BusDispatcher *dispatcher; +static DBus::Connection *dbusConnection; + +static int m_lenLastChunk; +static int m_slotCount; +static const uint32_t MAX_CHUNK_SIZE = 1024 + 1; /**< Maximum size of any chunk which can be stored within the queue. */ +static const uint32_t MAX_SLOT_COUNT = 16; /**< Maximum number of chunks which can be present in the queue at the same time. */ +static const uint32_t MAX_SLOT_COUNT_NO_WARN = (3 * MAX_SLOT_COUNT) / 4; /**< When pushing a chunk, TAQS_WARNING shall be reported if the new occupied slot count exceeds MAX_SLOT_COUNT_NO_WARN. */ +static const uint32_t MAX_CHUNK_LENGTH = 1024; /**< max length of a single prompt part */ +static const uint32_t MAX_MARKER_LENGTH = 32; /**< marker tag inside the prompt chunk */ +static const uint32_t PROCESS_CHUNKS_LOOP = 100; +static cst_voice* mp_voice; +static cst_audio_streaming_info* mp_asi; +static pthread_mutex_t mutex; + +static std::string m_chunkBuffer; /** max size = MAX_CHUNK_SIZE*MAX_SLOT_COUNT */ + +gboolean processChunks(gpointer data) { + //worker thread to process chunks in buffer + + pthread_mutex_lock(&mutex); + + if (m_chunkBuffer.length() > 0) + { + LOG_DEBUG_MSG(gCtx,"processChunks"); + std::string tempBuffer; + tempBuffer.assign(m_chunkBuffer); + m_chunkBuffer.clear(); //buffer empty + m_slotCount=0; //reset counter of slots + + pthread_mutex_unlock(&mutex); + + // pass string to TTS engine + flite_text_to_speech(tempBuffer.c_str(),mp_voice,"play"); + } + else + { + pthread_mutex_unlock(&mutex); + } + return(true); +} + +static int fliteCallback(const cst_wave *w, int start, int size, + int last, cst_audio_streaming_info_struct *asi) +{ + static cst_audiodev *ad = 0; + + if (start == 0) + ad = audio_open(w->sample_rate,w->num_channels,CST_AUDIO_LINEAR16); + + audio_write(ad,&w->samples[start],size*sizeof(short)); + + if (last == 1) + { + audio_drain(ad); + audio_close(ad); + ad = NULL; + LOG_DEBUG_MSG(gCtx,"end of processing chunks"); + } + + /* if you want to stop return CST_AUDIO_STREAM_STOP */ + return CST_AUDIO_STREAM_CONT; +} + +class SpeechOutput +: public org::genivi::hmi::speechservice::SpeechOutput_adaptor, + public DBus::IntrospectableAdaptor, + public DBus::ObjectAdaptor +{ +public: + + SpeechOutput(DBus::Connection &connection) : DBus::ObjectAdaptor(connection, speech_OBJECT_PATH){ + m_version._1=1; + m_version._2=0; + m_version._3=0; + m_version._4="12-10-2016"; + + m_lenLastChunk = 0; + m_slotCount = 0; + + flite_init(); + + mp_voice = register_cmu_us_kal(NULL); + mp_asi = new_audio_streaming_info(); + mp_asi->asc = fliteCallback; + + feat_set(mp_voice->features,"streaming_info",audio_streaming_info_val(mp_asi)); + } + + ~SpeechOutput(){ + unregister_cmu_us_kal(mp_voice); + } + + ::DBus::Struct< uint16_t, uint16_t, uint16_t, std::string > getVersion(){ + return m_version; + } + + void openPrompter(const int32_t& connectionType, const int32_t& preProcessingType){ + LOG_DEBUG(gCtx,"openPrompter: connection %d preprocessing %d",connectionType,preProcessingType); + } + + /** + * description: The prompter must be opened to trigger the playback of the provided prompt. + * + The prompt length must not exceed the length of a PromptChunk + * buffer. + Synthesizes the provided text or if using the escape sequence of the + * engine supplier a wave file in a supported sampling rate is provided, the + * system will back back also wave files. + The text will be normalized using the + * context identifier provided to openprompter. This applies to matching + * prerecorded files as well as the synthesis of number and words that are + * matched to a lexical dictionary. + The synthesize will start if the prompter is + * idle, if the prompter is already playing the playback will be delayed until + * all previously added text chunks are played back. For every text chunk + * provided a notification will be send. + */ + uint32_t addTextChunk(const std::string& chunk){ + LOG_DEBUG(gCtx,"addTextChunk: %s", chunk.c_str()); + + uint32_t _chunkID; + + // todo: manage _chunkID + + int32_t qStatus = GENIVI_SPEECHSERVICE_CS_UNKNOWN; + + if (chunk.size() > 0 && chunk.size() < MAX_CHUNK_LENGTH) + { + if (m_slotCount < (int) MAX_SLOT_COUNT) + { + if (m_slotCount <= (int) MAX_SLOT_COUNT_NO_WARN) + { + qStatus = GENIVI_SPEECHSERVICE_QS_LOW_FILL; + } + else + { + qStatus = GENIVI_SPEECHSERVICE_QS_HIGH_FILL; + } + m_chunkBuffer.append(chunk); + m_lenLastChunk = chunk.size(); + ++m_slotCount; + } + else + { + qStatus = GENIVI_SPEECHSERVICE_QS_FULL; + } + } + + notifyQueueStatus(qStatus); + + return(_chunkID); + } + + /** + * description: A prompt must be playing to perform an abort action. If no prompting operation + * in progress there will be no reaction of the system. + */ + void abortPrompter(){ + LOG_DEBUG_MSG(gCtx,"abortPrompter"); + } + + /** + * description: The prompter is closed after the last text chunk submitted has finished playing. + */ + void closePrompter(){ + LOG_DEBUG_MSG(gCtx,"closePrompter"); + } + +private: + ::DBus::Struct< uint16_t, uint16_t, uint16_t, std::string > m_version; +}; + +static SpeechOutput* serverSpeechOutput; + +int main(int argc , char** argv ) +{ + DLT_REGISTER_APP("SPCS","SPEECH SERVER"); + DLT_REGISTER_CONTEXT(gCtx,"SPCS","Global Context"); + + GMainLoop * mainloop ; + guint processChunksID; + + // Set the global C and C++ locale to the user-configured locale, + // so we can use std::cout with UTF-8, via Glib::ustring, without exceptions. + std::locale::global(std::locale("")); + + // creating the dispatcher + dispatcher = new DBus::Glib::BusDispatcher(); + DBus::default_dispatcher = dispatcher; + dispatcher->attach(NULL); + + // create a connection on the session bus + dbusConnection = new DBus::Connection(DBus::Connection::SessionBus()); + dbusConnection->setup(dispatcher); + + // create the server for SpeechOutput + dbusConnection->request_name(speech_SERVICE_NAME); + serverSpeechOutput=new SpeechOutput(*dbusConnection); + + processChunksID = g_timeout_add(PROCESS_CHUNKS_LOOP,processChunks,NULL); + + // Create a new GMainLoop with default context and initial state of "not running " + mainloop = g_main_loop_new (g_main_context_default() , FALSE ); + + // Send a feedback to the user + LOG_INFO_MSG(gCtx,"Speech output server started"); + + // loop listening + g_main_loop_run ( mainloop ); + + // clean memory + delete serverSpeechOutput; + delete dbusConnection; + delete dispatcher; + + LOG_INFO_MSG(gCtx,"Speech output server stopped"); + + return EXIT_SUCCESS; +} + diff --git a/src/speech-service/run b/src/speech-service/run new file mode 100755 index 0000000..f60767e --- /dev/null +++ b/src/speech-service/run @@ -0,0 +1,41 @@ +#!/bin/sh + +# @licence app begin@ +# SPDX-License-Identifier: MPL-2.0 +# +# \copyright Copyright (C) 2013-2014, PCA Peugeot Citroen +# +# \file run +# +# \brief This file is part of the Build System. +# +# \author Philippe Colliot +# +# \version 1.0 +# +# This Source Code Form is subject to the terms of the +# Mozilla Public License (MPL), v. 2.0. +# If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# For further information see http://www.genivi.org/. +# +# List of changes: +# +# , , +# +# @licence end@ + +CURDIR=$PWD + +BIN_DIR=$CURDIR/bin +SPEECH_OUPUT_SERVER_BIN_DIR=$BIN_DIR + +echo 'kill reminding orphan process if necessary' +./kill-all + +echo '------------------------start the server------------------------' +$SPEECH_OUPUT_SERVER_BIN_DIR/speech-server + + + diff --git a/src/speech-service/test-speech.py b/src/speech-service/test-speech.py new file mode 100755 index 0000000..0f99e13 --- /dev/null +++ b/src/speech-service/test-speech.py @@ -0,0 +1,89 @@ +#!/usr/bin/python + +""" +************************************************************************** +* @licence app begin@ +* SPDX-License-Identifier: MPL-2.0 +* +* \copyright Copyright (C) 2016, PSA GROUP +* +* \file test-speech.py +* +* \brief This simple test shows how the speech +* could be easily tested using a python script +* +* \author Philippe Colliot +* +* \version 1.0 +* +* This Source Code Form is subject to the terms of the +* Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with +# this file, You can obtain one at http://mozilla.org/MPL/2.0/. +* List of changes: +* +* @licence end@ +************************************************************************** +""" + +import dbus +import gobject +import dbus.mainloop.glib +import time + +import pdb; +#pdb.set_trace() +#constants as defined in the Navigation API +GENIVI_SPEECHSERVICE_QS_LOW_FILL=51 + +#constants used into the script +TIME_OUT = 10000 + +def catch_speech_notifyConnectionStatus_signal_handler(connectionStatus): + print("Connection status: " + str(int(connectionStatus))) + +def catch_speech_notifyMarkerReached_signal_handler(chunkID,marker): + print("Chunk ID: " + chunkID) + +def catch_speech_notifyQueueStatus_signal_handler(queueStatus): + print("Queue status: " + str(int(queueStatus))) + if queueStatus==GENIVI_SPEECHSERVICE_QS_LOW_FILL: + print ('\nTest OK') + loop.quit() + +def catch_speech_notifyTTSStatus_signal_handler(ttsStatus): + print("TTS status: " + str(int(ttsStatus))) + +#timeout +def timeout(): + print ('Timeout Expired') + print ('\nTest FAILED') + loop.quit() + +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +#connect to session bus +bus = dbus.SessionBus() + +bus.add_signal_receiver(catch_speech_notifyConnectionStatus_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyConnectionStatus") +bus.add_signal_receiver(catch_speech_notifyMarkerReached_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyMarkerReached") +bus.add_signal_receiver(catch_speech_notifyQueueStatus_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyQueueStatus") +bus.add_signal_receiver(catch_speech_notifyTTSStatus_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyTTSStatus") + +speech = bus.get_object('org.genivi.hmi.speechservice.SpeechOutput','/org/genivi/speechservice/SpeechOutput') +g_speech_interface = dbus.Interface(speech, dbus_interface='org.genivi.hmi.speechservice.SpeechOutput') + +g_speech_interface.addTextChunk(dbus.String("Hello")) + +#main loop +gobject.timeout_add(TIME_OUT, timeout) +loop = gobject.MainLoop() +loop.run() diff --git a/src/speech/CMakeLists.txt b/src/speech/CMakeLists.txt index ee62ba2..27f578b 100644 --- a/src/speech/CMakeLists.txt +++ b/src/speech/CMakeLists.txt @@ -56,20 +56,20 @@ add_subdirectory(${FRANCA_DIR}/hmi/speechservice "${CMAKE_CURRENT_BINARY_DIR}/fr # Path to the generated files set(API_VERSION_NAVIGATION_MAJOR 4) set(API_VERSION_NAVIGATION "v${API_VERSION_NAVIGATION_MAJOR}") -set(API_VERSION_SPEECHOUTPUTSERVICE_MAJOR 1) -set(API_VERSION_SPEECHOUTPUTSERVICE "v${API_VERSION_SPEECHOUTPUTSERVICE_MAJOR}") +set(API_VERSION_SPEECHSERVICE_MAJOR 1) +set(API_VERSION_SPEECHSERVICE "v${API_VERSION_SPEECHSERVICE_MAJOR}") set(PRJ_SRC_GEN_COMMON_PATH ${COMMONAPI_GEN_DIR}/${API_VERSION_NAVIGATION}/org/genivi) #files shared by all the APIs -set(PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH ${COMMONAPI_GEN_DIR}/${API_VERSION_SPEECHOUTPUTSERVICE}/org/genivi/hmi/speechoutputservice) #files shared by the speechservice APIs +set(PRJ_SRC_GEN_SPEECHSERVICE_PATH ${COMMONAPI_GEN_DIR}/${API_VERSION_SPEECHSERVICE}/org/genivi/hmi/speechservice) #files shared by the speechservice APIs # Source Files FILE(GLOB PRJ_LOCAL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) FILE(GLOB PRJ_STUB_GEN_SRCS ${PRJ_SRC_GEN_ROOT_PATH}/*DBusStub*.cpp ${PRJ_SRC_GEN_ROOT_PATH}/*Types.cpp ${PRJ_SRC_GEN_ROOT_PATH}/*DBusDeployment.cpp ${PRJ_SRC_GEN_ROOT_PATH}/*StubDefault.cpp - ${PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH}/*DBusStub*.cpp ${PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH}/*Types.cpp ${PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH}/*DBusDeployment.cpp ${PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH}/*StubDefault.cpp + ${PRJ_SRC_GEN_SPEECHSERVICE_PATH}/*DBusStub*.cpp ${PRJ_SRC_GEN_SPEECHSERVICE_PATH}/*Types.cpp ${PRJ_SRC_GEN_SPEECHSERVICE_PATH}/*DBusDeployment.cpp ${PRJ_SRC_GEN_SPEECHSERVICE_PATH}/*StubDefault.cpp ) FILE(GLOB PRJ_STUB_IMPL_SRCS ${PRJ_SRC_GEN_ROOT_PATH}/*Stub*.cpp - ${PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH}/*Stub*.cpp + ${PRJ_SRC_GEN_SPEECHSERVICE_PATH}/*Stub*.cpp ) set(PRJ_SRCS ${PRJ_LOCAL_SRCS} ${PRJ_STUB_GEN_SRCS} ${PRJ_STUB_IMPL_SRCS}) @@ -82,7 +82,7 @@ include_directories( ${COMMONAPI_GEN_DIR} ${PRJ_SRC_GEN_ROOT_PATH} ${PRJ_SRC_GEN_COMMON_PATH} - ${PRJ_SRC_GEN_SPEECHOUTPUTSERVICE_PATH} + ${PRJ_SRC_GEN_SPEECHSERVICE_PATH} ${DBUS_INCLUDE_DIRS} ${COMMONAPI_INCLUDE_DIRS} ${COMMONAPI_DBUS_INCLUDE_DIRS} diff --git a/src/speech/main.cpp b/src/speech/main.cpp index 4d3b1bc..f6b3ca4 100644 --- a/src/speech/main.cpp +++ b/src/speech/main.cpp @@ -50,7 +50,7 @@ extern "C" { #include #include -using namespace v1::org::genivi::hmi::speechoutputservice; +using namespace v1::org::genivi::hmi::speechservice; using namespace v4::org::genivi; static std::shared_ptr < CommonAPI::Runtime > runtime; diff --git a/src/speech/test-speech-capi.py b/src/speech/test-speech-capi.py index 1fc6eb3..f89c60b 100755 --- a/src/speech/test-speech-capi.py +++ b/src/speech/test-speech-capi.py @@ -62,20 +62,20 @@ if __name__ == '__main__': bus = dbus.SessionBus() bus.add_signal_receiver(catch_speech_notifyConnectionStatus_signal_handler, \ - dbus_interface = "org.genivi.hmi.speechoutputservice.SpeechOutput.v1_0", \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput.v1_0", \ signal_name = "notifyConnectionStatus") bus.add_signal_receiver(catch_speech_notifyMarkerReached_signal_handler, \ - dbus_interface = "org.genivi.hmi.speechoutputservice.SpeechOutput.v1_0", \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput.v1_0", \ signal_name = "notifyMarkerReached") bus.add_signal_receiver(catch_speech_notifyQueueStatus_signal_handler, \ - dbus_interface = "org.genivi.hmi.speechoutputservice.SpeechOutput.v1_0", \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput.v1_0", \ signal_name = "notifyQueueStatus") bus.add_signal_receiver(catch_speech_notifyTTSStatus_signal_handler, \ - dbus_interface = "org.genivi.hmi.speechoutputservice.SpeechOutput.v1_0", \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput.v1_0", \ signal_name = "notifyTTSStatus") -speech = bus.get_object('org.genivi.hmi.speechoutputservice.SpeechOutput.v1_0_SpeechOutput','/SpeechOutput') -g_speech_interface = dbus.Interface(speech, dbus_interface='org.genivi.hmi.speechoutputservice.SpeechOutput.v1_0') +speech = bus.get_object('org.genivi.hmi.speechservice.SpeechOutput.v1_0_SpeechOutput','/SpeechOutput') +g_speech_interface = dbus.Interface(speech, dbus_interface='org.genivi.hmi.speechservice.SpeechOutput.v1_0') g_speech_interface.addTextChunk(dbus.String("Hello")) diff --git a/test/navigation/script/genivi.py b/test/navigation/script/genivi.py index 7c0d301..0b2be2e 100644 --- a/test/navigation/script/genivi.py +++ b/test/navigation/script/genivi.py @@ -47,3 +47,39 @@ MANEUVER_APPEARED = 0x0051 PRE_ADVICE = 0x0052 ADVICE = 0x0053 PASSED = 0x0054 + +SPEECHSERVICE_MAX_CHUNK_LENGTH = 1024 +SPEECHSERVICE_CS_UNKNOWN = 0x0000 +SPEECHSERVICE_CS_ESTABLISHED = 0x0001 +SPEECHSERVICE_CS_REFUSED = 0x0002 +SPEECHSERVICE_CS_POSSIBLE = 0x0003 +SPEECHSERVICE_CS_PENDING = 0x0004 +SPEECHSERVICE_CS_PAUSED = 0x0005 +SPEECHSERVICE_CS_TERMINATED = 0x0006 +SPEECHSERVICE_CS_MAX = 0x0007 +SPEECHSERVICE_CT_NAVIGATION = 0x0010 +SPEECHSERVICE_CT_READER = 0x0011 +SPEECHSERVICE_CT_GEN_HIGH = 0x0012 +SPEECHSERVICE_CT_GEN_MEDIUM = 0x0013 +SPEECHSERVICE_CT_GEN_LOW = 0x0014 +SPEECHSERVICE_CT_MAX = 0x0015 +SPEECHSERVICE_PPT_DIALOG = 0x0020 +SPEECHSERVICE_PPT_NAVIGATION = 0x0021 +SPEECHSERVICE_PPT_NONE = 0x0022 +SPEECHSERVICE_PPT_READER = 0x0023 +SPEECHSERVICE_PPT_MAX = 0x0024 +SPEECHSERVICE_QS_UNKNOWN = 0x0030 +SPEECHSERVICE_QS_FULL = 0x0031 +SPEECHSERVICE_QS_HIGH_FILL = 0x0032 +SPEECHSERVICE_QS_LOW_FILL = 0x0033 +SPEECHSERVICE_QS_MAX = 0x0034 +SPEECHSERVICE_TS_UNKNOWN = 0x0040 +SPEECHSERVICE_TS_NOT_INITIALIZED = 0x0041 +SPEECHSERVICE_TS_ACTIVE = 0x0042 +SPEECHSERVICE_TS_ABORTED = 0x0043 +SPEECHSERVICE_TS_MARKER = 0x0044 +SPEECHSERVICE_TS_IDLE = 0x0045 +SPEECHSERVICE_TS_ENQUEUED = 0x0046 +SPEECHSERVICE_TS_FINISHED = 0x0047 +SPEECHSERVICE_TS_FAILED = 0x0048 +SPEECHSERVICE_TS_MAX = 0x0049 diff --git a/test/navigation/script/lbs-api-test.e4p b/test/navigation/script/lbs-api-test.e4p index b0f184b..6ef49c7 100644 --- a/test/navigation/script/lbs-api-test.e4p +++ b/test/navigation/script/lbs-api-test.e4p @@ -1,7 +1,7 @@ - + en_US @@ -24,6 +24,7 @@ test-route-calculation.py genivi.py test-poi-guidance.py + test-speech.py diff --git a/test/navigation/script/test-speech.py b/test/navigation/script/test-speech.py new file mode 100755 index 0000000..01e68bc --- /dev/null +++ b/test/navigation/script/test-speech.py @@ -0,0 +1,111 @@ +#!/usr/bin/python + +""" +************************************************************************** +* @licence app begin@ +* SPDX-License-Identifier: MPL-2.0 +* +* \copyright Copyright (C) 2016, PSA GROUP +* +* \file test-speech.py +* +* \brief This simple test shows how the speech +* could be easily tested using a python script +* +* \author Philippe Colliot +* +* \version 1.0 +* +* This Source Code Form is subject to the terms of the +* Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with +# this file, You can obtain one at http://mozilla.org/MPL/2.0/. +* List of changes: +* +* @licence end@ +************************************************************************** +""" + +import dbus +import gobject +import dbus.mainloop.glib + +import genivi +try: + from dltTrigger import * + dltTrigger=True + print('DLT signal sent') +except dltTriggerNotBuilt: + dltTrigger=False +#import pdb; pdb.set_trace() + +#name of the test +test_name = "speech output" + +#constants used into the script +TIME_OUT = 10000 + +def catch_speech_notifyConnectionStatus_signal_handler(connectionStatus): + print("Connection status: " + str(int(connectionStatus))) + +def catch_speech_notifyMarkerReached_signal_handler(chunkID,marker): + print("Chunk ID: " + chunkID) + +def catch_speech_notifyQueueStatus_signal_handler(queueStatus): + print("Queue status: " + str(int(queueStatus))) + if queueStatus==genivi.SPEECHSERVICE_QS_LOW_FILL: + g_speech_interface.closePrompter() + exit(0) + +def catch_speech_notifyTTSStatus_signal_handler(ttsStatus): + print("TTS status: " + str(int(ttsStatus))) + +#timeout +def timeout(): + print ('Timeout Expired\n') + exit(1) + +def exit(value): + global g_exit + g_exit=value + if dltTrigger==True: + stopTrigger(test_name) + loop.quit() + +print('\n--------------------------') +print('Speech Test') +print('--------------------------\n') + +g_exit=0 + +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +#connect to session bus +bus = dbus.SessionBus() + +bus.add_signal_receiver(catch_speech_notifyConnectionStatus_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyConnectionStatus") +bus.add_signal_receiver(catch_speech_notifyMarkerReached_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyMarkerReached") +bus.add_signal_receiver(catch_speech_notifyQueueStatus_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyQueueStatus") +bus.add_signal_receiver(catch_speech_notifyTTSStatus_signal_handler, \ + dbus_interface = "org.genivi.hmi.speechservice.SpeechOutput", \ + signal_name = "notifyTTSStatus") + +if dltTrigger==True: + startTrigger(test_name) + +speech = bus.get_object('org.genivi.hmi.speechservice.SpeechOutput','/org/genivi/hmi/speechservice/SpeechOutput') +g_speech_interface = dbus.Interface(speech, dbus_interface='org.genivi.hmi.speechservice.SpeechOutput') + +g_speech_interface.openPrompter(genivi.SPEECHSERVICE_CT_NAVIGATION, genivi.SPEECHSERVICE_PPT_NAVIGATION) +g_speech_interface.addTextChunk(dbus.String("Hello")) + +#main loop +gobject.timeout_add(TIME_OUT, timeout) +loop = gobject.MainLoop() +loop.run() -- cgit v1.2.1