From 3ff35d1427f0dcf3dc1744c03ad4dd0f1adf16a2 Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Thu, 8 Nov 2018 08:17:41 -0800 Subject: [PATCH 1/5] All demos running on Linux, Mac, Windows, and Android builds. Tested using Appveyor, and Travis-CI. Removed audio_*_alsa.* files in favor of the PortAudio implementation. audio_input_file.cc - Windows requires streams opened with binary flag. base64_encode.cc - u_char is not defined on some systems (Mac), using uint8_t instead. There is a pending PR for my CMake implementation to "build" googleapis tree. Once this is accepted, cmake/build_googleapis.cmake will be removed. When Cross compiling, a host implementation of grpc is required. --- .gitignore | 5 +- .travis.yml | 55 +++++++ CMakeLists.txt | 109 ++++++++++++++ appveyor.yml | 103 ++++++++++++++ cmake/build_dependencies.cmake | 190 +++++++++++++++++++++++++ cmake/build_googleapis.cmake | 96 +++++++++++++ cmake/make_uninstall.cmake | 16 +++ cmake/target_arch.cmake | 36 +++++ src/audio_input_alsa.cc | 116 --------------- src/audio_input_file.cc | 3 +- src/audio_output_alsa.cc | 140 ------------------ src/audio_output_alsa.h | 40 ------ src/audio_pa.cc | 142 ++++++++++++++++++ src/{audio_input_alsa.h => audio_pa.h} | 24 +++- src/base64_encode.cc | 2 +- src/run_assistant_audio.cc | 40 ++---- src/run_assistant_file.cc | 5 +- 17 files changed, 787 insertions(+), 335 deletions(-) create mode 100644 .travis.yml create mode 100644 CMakeLists.txt create mode 100644 appveyor.yml create mode 100644 cmake/build_dependencies.cmake create mode 100644 cmake/build_googleapis.cmake create mode 100644 cmake/make_uninstall.cmake create mode 100644 cmake/target_arch.cmake delete mode 100644 src/audio_input_alsa.cc delete mode 100644 src/audio_output_alsa.cc delete mode 100644 src/audio_output_alsa.h create mode 100644 src/audio_pa.cc rename src/{audio_input_alsa.h => audio_pa.h} (60%) diff --git a/.gitignore b/.gitignore index d33f720..61c0cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,7 @@ run_assistant_audio run_assistant_file run_assistant_text # Generated files -src/embedded_assistant* \ No newline at end of file +src/embedded_assistant* +build +.DS_Store + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4a69d37 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,55 @@ +language: cpp + +os: + - linux + - osx + +compiler: + - gcc + - clang + +env: + - BUILD_TYPE=Debug CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=Debug CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=Debug CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + + - BUILD_TYPE=Release CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=Release CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=Release CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + + - BUILD_TYPE=MinSizeRel CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=MinSizeRel CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=MinSizeRel CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + +addons: + apt: + packages: + - libasound2-dev + +install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mkdir ${DEPS_DIR} && cd ${DEPS_DIR} && pwd; fi + + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry wget --no-check-certificate https://cmake.org/files/v3.11/cmake-3.11.0-Linux-x86_64.tar.gz; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "96d67e21f0983ebf0fffc5b106ec338c *cmake-3.11.0-Linux-x86_64.tar.gz" > cmake_md5.txt; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then md5sum -c cmake_md5.txt; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xvf cmake-3.11.0-Linux-x86_64.tar.gz > /dev/null; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mv cmake-3.11.0-Linux-x86_64 cmake-install; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then PATH=${DEPS_DIR}/cmake-install:${DEPS_DIR}/cmake-install/bin:$PATH; fi + + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry wget --no-check-certificate https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "a6103c8157246dd1ac70528878994f31 *go1.11.1.linux-amd64.tar.gz" > go_md5.txt; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then md5sum -c go_md5.txt; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xzf go1.11.1.linux-amd64.tar.gz > /dev/null; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export GOROOT=${DEPS_DIR}/go; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then PATH=${DEPS_DIR}/go/bin:$PATH; fi + + +before_script: + - cd ${TRAVIS_BUILD_DIR} + - mkdir build && cd build + - cmake -DCMAKE_VERBOSE_MAKEFILE=FALSE -DCMAKE_BUILD_TYPE=${BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=${TRAVIS_BUILD_DIR}/build/dist ${CMAKE_ARGS} + .. +script: + - cmake --build . --config ${BUILD_TYPE} --target install diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..904b343 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,109 @@ +cmake_minimum_required(VERSION 3.11) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "MinSizeRel" CACHE STRING "Choose the type of build, options are: Debug, Release, or MinSizeRel." FORCE) + message(STATUS "CMAKE_BUILD_TYPE not set, defaulting to MinSizeRel.") +endif() + +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake") + +if(NOT BUILD_NUMBER) + set(BUILD_NUMBER 0) +endif() +set(ASSISTANT_SDK_CPP_VERSION 0.1.${BUILD_NUMBER}) + +set(PACKAGE_NAME assistant-sdk-cpp) +project(${PACKAGE_NAME} VERSION "${ASSISTANT_SDK_CPP_VERSION}" LANGUAGES CXX C) + +message(STATUS "Generator .............. ${CMAKE_GENERATOR}") +message(STATUS "Build Type ............. ${CMAKE_BUILD_TYPE}") +include (target_arch) +get_target_arch(TARGET_ARCH) +message(STATUS "Target ................. ${TARGET_ARCH}") + +include(build_dependencies) + +set(CMAKE_CXX_STANDARD_REQUIRED 11) +set(CMAKE_CXX_STANDARD 11) + +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +include(FindThreads) + + +set(GOOGLEAPIS_API_CCS + ${GOOGLEAPIS_GENS_PATH}/google/api/http.grpc.pb.cc + ${GOOGLEAPIS_GENS_PATH}/google/api/http.pb.cc + ${GOOGLEAPIS_GENS_PATH}/google/api/annotations.grpc.pb.cc + ${GOOGLEAPIS_GENS_PATH}/google/api/annotations.pb.cc +) +set(GOOGLEAPIS_TYPE_CCS + ${GOOGLEAPIS_GENS_PATH}/google/type/latlng.pb.cc + ${GOOGLEAPIS_GENS_PATH}/google/type/latlng.grpc.pb.cc +) +set(GOOGLEAPIS_RPC_CCS +) +set(GOOGLEAPIS_ASSISTANT_PATH google/assistant/embedded/v1alpha2) +set(GOOGLEAPIS_ASSISTANT_CCS + ${GOOGLEAPIS_GENS_PATH}/${GOOGLEAPIS_ASSISTANT_PATH}/embedded_assistant.pb.cc + ${GOOGLEAPIS_GENS_PATH}/${GOOGLEAPIS_ASSISTANT_PATH}/embedded_assistant.grpc.pb.cc +) +set(GOOGLEAPIS_CCS + ${GOOGLEAPIS_ASSISTANT_CCS} ${GOOGLEAPIS_API_CCS} + ${GOOGLEAPIS_RPC_CCS} ${GOOGLEAPIS_TYPE_CCS} +) +set_source_files_properties(${GOOGLEAPIS_CCS} PROPERTIES GENERATED TRUE) + +set(CORE_SRCS src/base64_encode.cc src/json_util.cc) +set(AUDIO_INPUT_FILE_SRCS src/audio_input_file.cc) +set(ASSISTANT_AUDIO_SRCS src/run_assistant_audio.cc src/audio_pa.cc) +set(ASSISTANT_FILE_SRCS src/run_assistant_file.cc) +set(ASSISTANT_TEXT_SRCS src/run_assistant_text.cc) + + +include_directories(src) + + +set(EXE_DEPS googleapis_ccs portaudio_ext) + +if(WIN32 AND MSVC) + add_definitions(-D_WIN32_WINNT=0x600) + set(_ALLTARGETS_LIBRARIES ${_GPERF_LIBRARY}) + list(APPEND EXE_DEPS gperf_ext portaudio_ext) +elseif(APPLE) + set(_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} m ${CMAKE_THREAD_LIBS_INIT}) +elseif(ANDROID) + set(_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} m log) +else() + set(_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} rt m ${CMAKE_THREAD_LIBS_INIT}) +endif() + + +set(LDFLAGS + grpc++ grpc gpr grpc_cronet address_sorting + ${_PROTOBUF_LIBRARIES} ${_CARES_LIBRARIES} + ${_ZLIB_LIBRARIES} ${_SSL_LIBRARIES} + ${_ALLTARGETS_LIBRARIES} +) + + +add_library(googleapis_ccs STATIC ${GOOGLEAPIS_CCS}) +add_dependencies(googleapis_ccs googleapis) + +add_executable(run_assistant_text ${CORE_SRCS} ${ASSISTANT_TEXT_SRCS}) +target_link_libraries(run_assistant_text googleapis_ccs ${LDFLAGS}) +add_dependencies(run_assistant_text ${EXE_DEPS}) + +add_executable(run_assistant_file ${CORE_SRCS} ${AUDIO_INPUT_FILE_SRCS} ${ASSISTANT_FILE_SRCS}) +target_link_libraries(run_assistant_file googleapis_ccs ${LDFLAGS}) +add_dependencies(run_assistant_file ${EXE_DEPS}) + +add_executable(run_assistant_audio ${CORE_SRCS} ${AUDIO_SRCS} ${ASSISTANT_AUDIO_SRCS}) +target_link_libraries(run_assistant_audio googleapis_ccs ${LDFLAGS} ${_PORTAUDIO_LIB}) +add_dependencies(run_assistant_audio ${EXE_DEPS}) + + +install (TARGETS run_assistant_audio run_assistant_text run_assistant_file + RUNTIME DESTINATION bin +) + +add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/make_uninstall.cmake") diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..fc8ed2e --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,103 @@ +version: 0.1.0.{build} + +shallow_clone: true +clone_depth: 1 + +configuration: +- MinSizeRel +- Release +- Debug + +environment: + DIST_DIR: '%APPVEYOR_BUILD_FOLDER%\dist' + GOPATH: c:\go + + matrix: + + - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' + VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat' + ARCHITECTURE: amd64_x86 + ARCHIVE: VS2015_%CONFIGURATION%_x86_%APPVEYOR_BUILD_NUMBER% + GENERATOR: 'NMake Makefiles' + CMAKE_ARGS: + + - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' + VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat' + ARCHITECTURE: amd64 + ARCHIVE: VS2015_%CONFIGURATION%_x64_%APPVEYOR_BUILD_NUMBER% + GENERATOR: 'NMake Makefiles' + CMAKE_ARGS: + +# - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' +# VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat' +# ARCHITECTURE: amd64_arm +# ARCHIVE: VS2015_%CONFIGURATION%_ARM_%APPVEYOR_BUILD_NUMBER% +# GENERATOR: 'NMake Makefiles' +# CMAKE_ARGS: + + +# - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' +# VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat' +# ARCHITECTURE: amd64_arm +# ARCHIVE: VS2017_%CONFIGURATION%_ARM_%APPVEYOR_BUILD_NUMBER% +# GENERATOR: 'NMake Makefiles' +# CMAKE_ARGS: + +# - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' +# VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat' +# ARCHITECTURE: amd64_arm64 +# ARCHIVE: VS2017_%CONFIGURATION%_ARM64_%APPVEYOR_BUILD_NUMBER% +# GENERATOR: 'NMake Makefiles' +# CMAKE_ARGS: + + - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' + VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat' + ARCHITECTURE: amd64_x86 + ARCHIVE: VS2017_%CONFIGURATION%_x86_%APPVEYOR_BUILD_NUMBER% + GENERATOR: 'NMake Makefiles' + CMAKE_ARGS: + + - APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' + VCVARSALL: '%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat' + ARCHITECTURE: amd64 + ARCHIVE: VS2017_%CONFIGURATION%_x86_%APPVEYOR_BUILD_NUMBER% + GENERATOR: 'NMake Makefiles' + CMAKE_ARGS: + +init: + - echo BUILD_NUMBER=%APPVEYOR_BUILD_NUMBER% + +stack: + - go 1.11 + +install: + - cmake --version + - go version + +build: + parallel: true + +build_script: + + - if exist "%VCVARSALL%" ( call "%VCVARSALL%" %ARCHITECTURE% ) + + - cd %APPVEYOR_BUILD_FOLDER% + - mkdir build + - cd build + + - cmake %CMAKE_TOOLCHAIN_ARGS% -G"%GENERATOR%" -DCMAKE_VERBOSE_MAKEFILE=TRUE + -DCMAKE_BUILD_TYPE=%CONFIGURATION% + "-DCMAKE_INSTALL_PREFIX=%DIST_DIR%\%APPVEYOR_BUILD_WORKER_IMAGE%" + -DBUILD_NUMBER=%APPVEYOR_BUILD_NUMBER% %CMAKE_ARGS% + .. + + - cmake --build . --config %CONFIGURATION% --target all + +after_build: + - cd %DIST_DIR% + - 7z a -tzip %ARCHIVE%.zip "%APPVEYOR_BUILD_WORKER_IMAGE%" + - certutil -hashfile %ARCHIVE%.zip MD5 > %ARCHIVE%.md5 + +artifacts: + - path: dist\$(ARCHIVE).zip + - path: dist\$(ARCHIVE).md5 diff --git a/cmake/build_dependencies.cmake b/cmake/build_dependencies.cmake new file mode 100644 index 0000000..beccdb0 --- /dev/null +++ b/cmake/build_dependencies.cmake @@ -0,0 +1,190 @@ +include (ExternalProject) +include(CheckFunctionExists) + +if(NOT GRPC_VERSION) + set(GRPC_VERSION v1.16.0) +endif() + +if(ANDROID) + set(GRPC_ANDROID_ARGS + -DRUN_HAVE_STD_REGEX=0 + -DRUN_HAVE_POSIX_REGEX=0 + -DRUN_HAVE_STEADY_CLOCK=0 + -DCMAKE_EXE_LINKER_FLAGS=-llog + -DgRPC_BUILD_CODEGEN=OFF + -DgRPC_BUILD_CSHARP_EXT=OFF + ) +endif() + +ExternalProject_Add(grpc_ext + GIT_REPOSITORY "https://github.com/grpc/grpc" + GIT_TAG ${GRPC_VERSION} + GIT_SHALLOW 1 + UPDATE_COMMAND "" + BUILD_IN_SOURCE 0 + CMAKE_ARGS + -DANDROID_PLATFORM=${ANDROID_PLATFORM} + -DANDROID_ABI=${ANDROID_ABI} + -DANDROID_STL=${ANDROID_STL} + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + ${GRPC_ANDROID_ARGS} +) +set(_GRPC_SRC_PATH ${CMAKE_BINARY_DIR}/grpc_ext-prefix/src/grpc_ext) + +set(_GRPC_LIBRARIES_DIR ${_GRPC_SRC_PATH}-build) + +set(_SSL_LIBRARIES_DIRS + ${_GRPC_SRC_PATH}-build/third_party/boringssl/crypto + ${_GRPC_SRC_PATH}-build/third_party/boringssl/ssl + ${_GRPC_SRC_PATH}-build/third_party/boringssl/decrepit +) +set(_SSL_LIBRARIES ssl decrepit crypto) + + +if(NOT MSVC) + set(_ZLIB_LIBRARIES z) +else() + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(_ZLIB_LIBRARIES zlibstaticd) + else() + set(_ZLIB_LIBRARIES zlibstatic) + endif() +endif() + +set(_CARES_LIBRARIES cares) + +if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(PROTOBUF_LIB protobufd) +else() + set(PROTOBUF_LIB protobuf) +endif() +if(MSVC) + set(PROTOBUF_LIB lib${PROTOBUF_LIB}) +endif() +set(_PROTOBUF_LIBRARIES ${PROTOBUF_LIB}) + + +set(GOOGLEAPIS_GENS_PATH ${CMAKE_INSTALL_PREFIX}/gens) + +if(NOT CMAKE_CROSSCOMPILING) + set(PROTOBUF_ROOT_FOLDER ${_GRPC_SRC_PATH}-build) + set(GRPC_PLUGINPATH ${_GRPC_SRC_PATH}-build) +endif() + +ExternalProject_Add(googleapis + GIT_REPOSITORY https://github.com/googleapis/googleapis.git + GIT_TAG master + GIT_SHALLOW 1 + PATCH_COMMAND + cmake -E copy + ${CMAKE_SOURCE_DIR}/cmake/build_googleapis.cmake + ${CMAKE_BINARY_DIR}/googleapis-prefix/src/googleapis/CMakeLists.txt + UPDATE_COMMAND "" + BUILD_IN_SOURCE 0 + CMAKE_ARGS + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DProtobuf_DEBUG=OFF + -DProtobuf_SRC_ROOT_FOLDER=${PROTOBUF_ROOT_FOLDER} + -DGRPCPLUGIN_PATH=${GRPC_PLUGINPATH} + -DOUTPUT=${GOOGLEAPIS_GENS_PATH} + INSTALL_COMMAND "" +) +add_dependencies(googleapis grpc_ext) + + +if(MSVC) + if(${TARGET_ARCH} STREQUAL "x86_64") + set(_PORTAUDIO_LIB portaudio_x64) + else() + set(_PORTAUDIO_LIB portaudio_${TARGET_ARCH}) + endif() +else() + set(_PORTAUDIO_LIB portaudio) +endif() + +if(NOT ANDROID) + ExternalProject_Add(portaudio_ext + GIT_REPOSITORY https://git.assembla.com/portaudio.git + GIT_TAG master + GIT_SHALLOW 1 + UPDATE_COMMAND "" + BUILD_IN_SOURCE 0 + CMAKE_ARGS + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -DPA_ENABLE_DEBUG_OUTPUT=OFF + -DPA_BUILD_EXAMPLES=ON + -DPA_BUILD_TESTS=ON + -DPA_DISABLE_INSTALL=OFF + ) +else() + ExternalProject_Add(portaudio_ext + GIT_REPOSITORY https://github.com/Gundersanne/portaudio_opensles.git + GIT_TAG master + GIT_SHALLOW 1 + UPDATE_COMMAND "" + BUILD_IN_SOURCE 0 + CMAKE_ARGS + -DANDROID_PLATFORM=${ANDROID_PLATFORM} + -DANDROID_ABI=${ANDROID_ABI} + -DANDROID_STL=${ANDROID_STL} + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -DPA_ENABLE_DEBUG_OUTPUT=OFF + -DPA_BUILD_EXAMPLES=OFF + -DPA_BUILD_TESTS=OFF + -DPA_DISABLE_INSTALL=OFF + ) +endif() + + +check_function_exists(getopt HAVE_GETOPT_C) +if(NOT HAVE_GETOPT_C) + + SET(GPERF_RELEASE 3.1) + ExternalProject_Add(gperf_ext + URL https://github.com/jwinarske/gperf/archive/cmake.zip + URL_HASH "SHA256=2c3ff3ce41f4a97b6bbc432372d3cb738afcf7535705e7c2977c4f6af1c7ff19" + UPDATE_COMMAND "" + BUILD_IN_SOURCE 0 + CMAKE_ARGS + -DANDROID_PLATFORM=${ANDROID_PLATFORM} + -DANDROID_ABI=${ANDROID_ABI} + -DANDROID_STL=${ANDROID_STL} + -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + ) + if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") + set(_GPERF_LIBRARY gpd) + else() + set(_GPERF_LIBRARY gp) + endif() +endif() + + +include_directories( + ${CMAKE_INSTALL_PREFIX}/include + ${_GRPC_SRC_PATH} + ${GOOGLEAPIS_GENS_PATH} +) + +link_directories( + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib/static + ${_GRPC_LIBRARIES_DIR} + ${_SSL_LIBRARIES_DIRS} +) diff --git a/cmake/build_googleapis.cmake b/cmake/build_googleapis.cmake new file mode 100644 index 0000000..f0844f4 --- /dev/null +++ b/cmake/build_googleapis.cmake @@ -0,0 +1,96 @@ +cmake_minimum_required(VERSION 3.11) + +set(Protobuf_USE_STATIC_LIBS OFF) + +if(NOT Protobuf_SRC_ROOT_FOLDER) + set(Protobuf_SRC_ROOT_FOLDER ${CMAKE_INSTALL_PREFIX}) +endif() + +set(Protobuf_IMPORT_DIRS + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_INSTALL_PREFIX}/include +) + +if(NOT WIN32) + set(BIN_SUFFIX "") + set(PATH_SEPERATOR ":") +else() + set(PATH_SEPERATOR ";") + set(BIN_SUFFIX ".exe") +endif() + +find_package(Protobuf REQUIRED) + +include_directories(${CMAKE_BINARY_DIR}) + +if(NOT Protobuf_FOUND) + message(FATAL_ERROR "Set Protobuf_SRC_ROOT_FOLDER to the desired sysroot...") +endif() +message(STATUS "Protobuf_VERSION=${Protobuf_VERSION}") + +# Choose the output directory +if(NOT OUTPUT) + set(OUTPUT ./gens) +endif() +file(MAKE_DIRECTORY ${OUTPUT}) + + +# Choose the target language. +if(NOT LANGUAGE) + set(LANGUAGE cpp) +endif() +if(${LANGUAGE} STREQUAL "go") + MESSAGE(FATAL_ERROR "Go source files are not generated from this repository. See: https://github.com/google/go-genproto") +endif() + + +# Choose grpc plugin +if(NOT GRPCPLUGIN_PATH) + set(GRPCPLUGIN_PATH /usr/local/bin/grpc_${LANGUAGE}_plugin) +endif() +set(GRPCPLUGIN "${GRPCPLUGIN_PATH}/grpc_${LANGUAGE}_plugin${BIN_SUFFIX}") + +# Choose the proto include directory. +#include_directories(${Protobuf_INCLUDE_DIRS}) + +get_filename_component(protoc_path ${Protobuf_PROTOC_EXECUTABLE} DIRECTORY) +file(TO_NATIVE_PATH ${protoc_path} protoc_path) + +set(ENV{PATH} "${protoc_path}${PATH_SEPERATOR}$ENV{PATH}") + +# Compile the entire repository +# +file(TO_NATIVE_PATH ${OUTPUT} NATIVE_OUTPUT) +file(TO_NATIVE_PATH ${GRPCPLUGIN} NATIVE_GRPCPLUGIN) +file(TO_NATIVE_PATH ${Protobuf_INCLUDE_DIRS} NATIVE_Protobuf_INCLUDE_DIRS) +MESSAGE(STATUS "Protobuf_INCLUDE_DIRS=${NATIVE_Protobuf_INCLUDE_DIRS}") +MESSAGE(STATUS "OUTPUT=${NATIVE_OUTPUT}") +MESSAGE(STATUS "LANGUAGE=${LANGUAGE}") +MESSAGE(STATUS "GRPCPLUGIN=${NATIVE_GRPCPLUGIN}") +message(STATUS "WORKING_DIRECTORY=${CMAKE_SOURCE_DIR}") + +file(MAKE_DIRECTORY ${OUTPUT}) + +file(GLOB_RECURSE src_list ${CMAKE_SOURCE_DIR} google/*.proto) + +foreach(src ${src_list}) + string (REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" rel_src ${src}) + file(TO_NATIVE_PATH ${rel_src} NATIVE_rel_src) + + if(Protobuf_DEBUG) + MESSAGE(STATUS "protoc${BIN_SUFFIX} --proto_path=.${PATH_SEPERATOR}${NATIVE_Protobuf_INCLUDE_DIRS} --${LANGUAGE}_out=${NATIVE_OUTPUT} --grpc_out=${NATIVE_OUTPUT} --plugin=protoc-gen-grpc=${NATIVE_GRPCPLUGIN} ${NATIVE_rel_src}") + else() + MESSAGE(STATUS ${NATIVE_rel_src}) + endif() + + execute_process( + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND "protoc${BIN_SUFFIX}" + "--proto_path=.${PATH_SEPERATOR}${NATIVE_Protobuf_INCLUDE_DIRS}" + "--${LANGUAGE}_out=${NATIVE_OUTPUT}" + "--grpc_out=${NATIVE_OUTPUT}" + "--plugin=protoc-gen-grpc=${NATIVE_GRPCPLUGIN}" + ${NATIVE_rel_src} + ) +endforeach(src) diff --git a/cmake/make_uninstall.cmake b/cmake/make_uninstall.cmake new file mode 100644 index 0000000..bd8504e --- /dev/null +++ b/cmake/make_uninstall.cmake @@ -0,0 +1,16 @@ +if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") + + file(READ "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt" install_manifest) + string(REGEX REPLACE "[\r\n]" ";" install_manifest "${install_manifest}") + + foreach(file ${install_manifest}) + if(EXISTS "${file}") + message(STATUS "Uninstalling ${file}") + file(REMOVE ${file}) + if (EXISTS "${file}") + message(FATAL_ERROR "Problem removing ${file}, check your permissions") + endif() + endif() + endforeach() + +endif() \ No newline at end of file diff --git a/cmake/target_arch.cmake b/cmake/target_arch.cmake new file mode 100644 index 0000000..38397c6 --- /dev/null +++ b/cmake/target_arch.cmake @@ -0,0 +1,36 @@ + +set(TARGET_ARCH_DETECT_CODE " + + #if defined(_M_ARM) || defined(__arm__) + #error cmake_arch ARM + #elif defined(_M_ARM64) || defined(__aarch64__) + #error cmake_arch ARM64 + #elif defined(_M_AMD64) || defined(__x86_64__) + #error cmake_arch x86_64 + #elif defined(_M_X64) + #error cmake_arch x64 + #elif defined(_M_IX86) || defined(__i386__) + #error cmake_arch x86 + #else + #error cmake_arch unknown + #endif +") + +function(get_target_arch out) + + file(WRITE + "${CMAKE_BINARY_DIR}/target_arch_detect.c" + "${TARGET_ARCH_DETECT_CODE}") + + try_run( + run_result_unused compile_result_unused + "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/target_arch_detect.c" + COMPILE_OUTPUT_VARIABLE TARGET_ARCH) + + # parse compiler output + string(REGEX MATCH "cmake_arch ([a-zA-Z0-9_]+)" TARGET_ARCH "${TARGET_ARCH}") + string(REPLACE "cmake_arch " "" TARGET_ARCH "${TARGET_ARCH}") + + set(${out} "${TARGET_ARCH}" PARENT_SCOPE) + +endfunction() diff --git a/src/audio_input_alsa.cc b/src/audio_input_alsa.cc deleted file mode 100644 index 8636132..0000000 --- a/src/audio_input_alsa.cc +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2017 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License 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. -*/ - -#include "audio_input_alsa.h" - -#include - -#include - -std::unique_ptr AudioInputALSA::GetBackgroundThread() { - return std::unique_ptr(new std::thread([this]() { - // Initialize. - snd_pcm_t* pcm_handle; - int pcm_open_ret = - snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_CAPTURE, 0); - if (pcm_open_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_open returned " << pcm_open_ret - << std::endl; - return; - } - - int pcm_nonblock_ret = snd_pcm_nonblock(pcm_handle, SND_PCM_NONBLOCK); - if (pcm_nonblock_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_nonblock returned " - << pcm_nonblock_ret << std::endl; - return; - } - - snd_pcm_hw_params_t* pcm_params; - int malloc_param_ret = snd_pcm_hw_params_malloc(&pcm_params); - if (malloc_param_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_hw_params_malloc returned " - << malloc_param_ret << std::endl; - return; - } - - snd_pcm_hw_params_any(pcm_handle, pcm_params); - int set_param_ret = snd_pcm_hw_params_set_access( - pcm_handle, pcm_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (set_param_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_hw_params_set_access returned " - << set_param_ret << std::endl; - return; - } - - set_param_ret = snd_pcm_hw_params_set_format(pcm_handle, pcm_params, - SND_PCM_FORMAT_S16_LE); - if (set_param_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_hw_params_set_format returned " - << set_param_ret << std::endl; - return; - } - - set_param_ret = snd_pcm_hw_params_set_channels(pcm_handle, pcm_params, 1); - if (set_param_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_hw_params_set_channels returned " - << set_param_ret << std::endl; - return; - } - - unsigned int rate = 16000; - set_param_ret = - snd_pcm_hw_params_set_rate_near(pcm_handle, pcm_params, &rate, nullptr); - if (set_param_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_hw_params_set_rate_near returned " - << set_param_ret << std::endl; - return; - } - - set_param_ret = snd_pcm_hw_params(pcm_handle, pcm_params); - if (set_param_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_hw_params returned " << set_param_ret - << std::endl; - return; - } - snd_pcm_hw_params_free(pcm_params); - - while (is_running_) { - std::shared_ptr> audio_data( - new std::vector(kFramesPerPacket * kBytesPerFrame)); - int pcm_read_ret = - snd_pcm_readi(pcm_handle, &(*audio_data.get())[0], kFramesPerPacket); - if (pcm_read_ret == -EAGAIN) { - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } else if (pcm_read_ret < 0) { - std::cerr << "AudioInputALSA snd_pcm_readi returned " << pcm_read_ret - << std::endl; - break; - } else if (pcm_read_ret > 0) { - audio_data->resize(kBytesPerFrame * pcm_read_ret); - for (auto& listener : data_listeners_) { - listener(audio_data); - } - } - } - - // Finalize. - snd_pcm_close(pcm_handle); - - // Call |OnStop|. - OnStop(); - })); -} diff --git a/src/audio_input_file.cc b/src/audio_input_file.cc index a4cc0f0..7ad7b80 100644 --- a/src/audio_input_file.cc +++ b/src/audio_input_file.cc @@ -18,11 +18,12 @@ limitations under the License. #include #include +#include std::unique_ptr AudioInputFile::GetBackgroundThread() { return std::unique_ptr(new std::thread([this]() { // Initialize. - std::ifstream file_stream(file_path_); + std::ifstream file_stream(file_path_, std::ifstream::binary); if (!file_stream) { std::cerr << "AudioInputFile cannot open file " << file_path_ << std::endl; diff --git a/src/audio_output_alsa.cc b/src/audio_output_alsa.cc deleted file mode 100644 index 009d163..0000000 --- a/src/audio_output_alsa.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2017 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License 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. -*/ - -#include "audio_output_alsa.h" - -#include - -#include - -bool AudioOutputALSA::Start() { - std::unique_lock lock(isRunningMutex); - - if (isRunning) { - return true; - } - - snd_pcm_t* pcm_handle; - int pcm_open_ret = - snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); - if (pcm_open_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_open returned " << pcm_open_ret - << std::endl; - return false; - } - - snd_pcm_hw_params_t* pcm_params; - int malloc_param_ret = snd_pcm_hw_params_malloc(&pcm_params); - if (malloc_param_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_hw_params_malloc returned " - << malloc_param_ret << std::endl; - return false; - } - - snd_pcm_hw_params_any(pcm_handle, pcm_params); - int set_param_ret = snd_pcm_hw_params_set_access( - pcm_handle, pcm_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (set_param_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_hw_params_set_access returned " - << set_param_ret << std::endl; - return false; - } - - set_param_ret = snd_pcm_hw_params_set_format(pcm_handle, pcm_params, - SND_PCM_FORMAT_S16_LE); - if (set_param_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_hw_params_set_format returned " - << set_param_ret << std::endl; - return false; - } - - set_param_ret = snd_pcm_hw_params_set_channels(pcm_handle, pcm_params, 1); - if (set_param_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_hw_params_set_channels returned " - << set_param_ret << std::endl; - return false; - } - - unsigned int rate = 16000; - set_param_ret = - snd_pcm_hw_params_set_rate_near(pcm_handle, pcm_params, &rate, nullptr); - if (set_param_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_hw_params_set_rate_near returned " - << set_param_ret << std::endl; - return false; - } - - set_param_ret = snd_pcm_hw_params(pcm_handle, pcm_params); - if (set_param_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_hw_params returned " << set_param_ret - << std::endl; - return false; - } - - snd_pcm_hw_params_free(pcm_params); - - isRunning = true; - alsaThread.reset(new std::thread([this, pcm_handle]() { - while (isRunning) { - std::unique_lock lock(audioDataMutex); - - while (audioData.size() == 0 && isRunning) { - audioDataCv.wait_for(lock, std::chrono::milliseconds(100)); - } - - if (!isRunning) { - break; - } - - std::shared_ptr> data = audioData[0]; - audioData.erase(audioData.begin()); - // 1 channel, S16LE, so 2 bytes each frame. - int frames = data->size() / 2; - int pcm_write_ret = snd_pcm_writei(pcm_handle, &(*data.get())[0], frames); - if (pcm_write_ret < 0) { - int pcm_recover_ret = snd_pcm_recover(pcm_handle, pcm_write_ret, 0); - if (pcm_recover_ret < 0) { - std::cerr << "AudioOutputALSA snd_pcm_recover returns " - << pcm_recover_ret << std::endl; - break; - } - } - } - - // Wait for all data to be consumed. - snd_pcm_drain(pcm_handle); - snd_pcm_close(pcm_handle); - })); - return true; -} - -void AudioOutputALSA::Stop() { - std::unique_lock lick(isRunningMutex); - - if (!isRunning) { - return; - } - - isRunning = false; - alsaThread->join(); - alsaThread.reset(nullptr); -} - -void AudioOutputALSA::Send(std::shared_ptr> data) { - std::unique_lock lock(audioDataMutex); - audioData.push_back(data); - audioDataCv.notify_one(); -} diff --git a/src/audio_output_alsa.h b/src/audio_output_alsa.h deleted file mode 100644 index 4bacc98..0000000 --- a/src/audio_output_alsa.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2017 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License 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. -*/ - -#include -#include -#include -#include - -// Audio output using ALSA. -class AudioOutputALSA { - public: - bool Start(); - - void Stop(); - - void Send(std::shared_ptr> data); - - friend void fill_audio(void* userdata, unsigned char* stream, int len); - - private: - std::vector>> audioData; - std::mutex audioDataMutex; - std::condition_variable audioDataCv; - std::unique_ptr alsaThread; - bool isRunning = false; - std::mutex isRunningMutex; -}; diff --git a/src/audio_pa.cc b/src/audio_pa.cc new file mode 100644 index 0000000..900f576 --- /dev/null +++ b/src/audio_pa.cc @@ -0,0 +1,142 @@ +/* +Copyright 2017 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License 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. +*/ + +#include "audio_pa.h" + +#include +#include + +std::unique_ptr AudioPA::GetBackgroundThread() { + return std::unique_ptr(new std::thread([this]() { + + PaError err; + + std::shared_ptr> audio_data( + new std::vector); + + const size_t chunk_size = kFramesPerBuffer * kInputNumChannels * sizeof(short); + + audio_data->resize(chunk_size); + + err = Pa_StartStream( stream ); + if (err != paNoError) goto error; + + while (is_running_) { + + err = Pa_ReadStream(stream, &(*audio_data.get())[0], kFramesPerBuffer); + if(err == paNoError) { + for (auto& listener : data_listeners_) { + listener(audio_data); + } + } + else if(err != paInputOverflowed) { + std::cerr << "Pa_ReadStream error: "; + goto error; + } + } + + // Call |OnStop|. + OnStop(); + return; + +error: + std::cerr << Pa_GetErrorText(err) << std::endl; + + // Call |OnStop|. + OnStop(); + })); +} + + +int AudioPA::Open() { + + PaError err; + PaDeviceIndex devInput, devOutput; + const PaDeviceInfo* inputInfo; + const PaDeviceInfo* outputInfo; + PaStreamParameters inputParameters; + PaStreamParameters outputParameters; + + err = Pa_Initialize(); + if(err != paNoError) goto error; + + devInput = Pa_GetDefaultInputDevice(); + inputInfo = Pa_GetDeviceInfo( devInput ); + std::cout << "Input device # " << devInput << std::endl; + std::cout << " Name: " << inputInfo->name << std::endl; + + inputParameters.device = devInput; + inputParameters.channelCount = kInputNumChannels; + inputParameters.sampleFormat = kSampleFormat; + inputParameters.suggestedLatency = inputInfo->defaultLowInputLatency; + inputParameters.hostApiSpecificStreamInfo = NULL; + + devOutput = Pa_GetDefaultOutputDevice(); + outputInfo = Pa_GetDeviceInfo( devOutput ); + std::cout << "Output device # " << devOutput << std::endl; + std::cout << " Name: " << outputInfo->name << std::endl; + + outputParameters.device = devOutput; + outputParameters.channelCount = kOutputNumChannels; + outputParameters.sampleFormat = kSampleFormat; + outputParameters.suggestedLatency = outputInfo->defaultLowOutputLatency; + outputParameters.hostApiSpecificStreamInfo = NULL; + + err = Pa_IsFormatSupported( &inputParameters, &outputParameters, kSampleRate); + if( err != paNoError ) goto error; + + err = Pa_OpenStream( + &stream, + &inputParameters, + &outputParameters, + kSampleRate, + kFramesPerBuffer, + paClipOff, + NULL, + NULL ); + if( err != paNoError ) goto error; + + return err; + +error: + if( stream ) { + Pa_AbortStream( stream ); + Pa_CloseStream( stream ); + } + Pa_Terminate(); + std::cerr << Pa_GetErrorText(err) << std::endl; + return (int)err; +} + +int AudioPA::Write( const void *buffer, unsigned long frames ) { + return (int)Pa_WriteStream( stream, buffer, frames ); +} + +void AudioPA::Stop() { + + if( stream ) { + Pa_StopStream( stream ); + } +} + +void AudioPA::Close() { + + if( stream ) { + Pa_AbortStream( stream ); + Pa_CloseStream( stream ); + } + Pa_Terminate(); +} diff --git a/src/audio_input_alsa.h b/src/audio_pa.h similarity index 60% rename from src/audio_input_alsa.h rename to src/audio_pa.h index 68f9180..409267b 100644 --- a/src/audio_input_alsa.h +++ b/src/audio_pa.h @@ -16,15 +16,29 @@ limitations under the License. #include "audio_input.h" -class AudioInputALSA : public AudioInput { +#include + +class AudioPA : public AudioInput { public: - ~AudioInputALSA() override {} + ~AudioPA() override {} virtual std::unique_ptr GetBackgroundThread() override; + int Open(); + int Write(const void *buffer, unsigned long frames); + void Stop(); + void Close(); + private: + + static constexpr int kInputNumChannels = 1; + static constexpr int kOutputNumChannels = 1; + // For 16000Hz, it's about 0.1 second. - static constexpr int kFramesPerPacket = 1600; - // 1 channel, S16LE, so 2 bytes each frame. - static constexpr int kBytesPerFrame = 2; + static constexpr double kSampleRate = 16000; + static constexpr PaSampleFormat kSampleFormat = paInt16; + static constexpr unsigned long kFramesPerBuffer = 512; + + PaStream* stream; + }; diff --git a/src/base64_encode.cc b/src/base64_encode.cc index 888578d..f3819a5 100644 --- a/src/base64_encode.cc +++ b/src/base64_encode.cc @@ -22,7 +22,7 @@ std::string base64_encode(const std::string &in) { std::string out; int val = 0, valb = -6; - for (u_char c : in) { + for (uint8_t c : in) { val = (val << 8) + c; valb += 8; while (valb >= 0) { diff --git a/src/run_assistant_audio.cc b/src/run_assistant_audio.cc index aee16b9..47b74bf 100644 --- a/src/run_assistant_audio.cc +++ b/src/run_assistant_audio.cc @@ -26,14 +26,7 @@ limitations under the License. #include #include -#ifdef __linux__ -#define ENABLE_ALSA -#endif - -#ifdef ENABLE_ALSA -#include "audio_input_alsa.h" -#include "audio_output_alsa.h" -#endif +#include "audio_pa.h" #include "google/assistant/embedded/v1alpha2/embedded_assistant.grpc.pb.h" #include "google/assistant/embedded/v1alpha2/embedded_assistant.pb.h" @@ -59,7 +52,6 @@ using grpc::Channel; using grpc::ClientReaderWriter; static const std::string kCredentialsTypeUserAccount = "USER_ACCOUNT"; -static const std::string kALSAAudioInput = "ALSA_INPUT"; static const std::string kLanguageCode = "en-US"; static const std::string kDeviceModelId = "default"; static const std::string kDeviceInstanceId = "default"; @@ -141,11 +133,6 @@ bool GetCommandLineFlags(int argc, char** argv, int main(int argc, char** argv) { std::string credentials_file_path, api_endpoint, locale, html_out_command; -#ifndef ENABLE_ALSA - std::cerr << "ALSA audio input is not supported on this platform." - << std::endl; - return -1; -#endif // Initialize gRPC and DNS resolvers // https://github.com/grpc/grpc/issues/11366#issuecomment-328595941 @@ -155,6 +142,9 @@ int main(int argc, char** argv) { return -1; } + AudioPA audio_sys; + audio_sys.Open(); /* Opens default input and output */ + while (true) { // Create an AssistRequest AssistRequest request; @@ -225,9 +215,8 @@ int main(int argc, char** argv) { << request.ShortDebugString() << std::endl; } stream->Write(request); - - audio_input.reset(new AudioInputALSA()); - + + audio_input.reset(&audio_sys); audio_input->AddDataListener( [stream, &request](std::shared_ptr> data) { request.set_audio_in(&((*data)[0]), data->size()); @@ -236,9 +225,6 @@ int main(int argc, char** argv) { audio_input->AddStopListener([stream]() { stream->WritesDone(); }); audio_input->Start(); - AudioOutputALSA audio_output; - audio_output.Start(); - // Read responses. if (verbose) { std::clog << "assistant_sdk waiting for response ... " << std::endl; @@ -254,13 +240,8 @@ int main(int argc, char** argv) { } if (response.has_audio_out()) { // CUSTOMIZE: play back audio_out here. - - std::shared_ptr> data( - new std::vector); - data->resize(response.audio_out().audio_data().length()); - memcpy(&((*data)[0]), response.audio_out().audio_data().c_str(), - response.audio_out().audio_data().length()); - audio_output.Send(data); + audio_sys.Write(response.audio_out().audio_data().c_str(), + response.audio_out().audio_data().size() / 2); } // CUSTOMIZE: render spoken request on screen for (int i = 0; i < response.speech_results_size(); i++) { @@ -289,8 +270,7 @@ int main(int argc, char** argv) { } } - audio_output.Stop(); - + audio_sys.Stop(); grpc::Status status = stream->Finish(); if (!status.ok()) { // Report the RPC failure. @@ -300,5 +280,7 @@ int main(int argc, char** argv) { } } + audio_sys.Close(); + return 0; } diff --git a/src/run_assistant_file.cc b/src/run_assistant_file.cc index c67c303..8f51437 100644 --- a/src/run_assistant_file.cc +++ b/src/run_assistant_file.cc @@ -172,7 +172,7 @@ int main(int argc, char** argv) { return -2; } // Make sure the input file exists - std::ifstream audio_input_file(audio_input_source); + std::ifstream audio_input_file(audio_input_source, std::ifstream::binary); if (!audio_input_file) { std::cerr << "Audio input file \"" << audio_input_source << "\" does not exist." << std::endl; @@ -246,7 +246,8 @@ int main(int argc, char** argv) { std::ofstream audio_output_file; // Make sure to rewrite contents of file audio_output_file.open(audio_output_source, - std::ofstream::out | std::ofstream::trunc); + std::ofstream::out | std::ofstream::trunc | + std::ofstream::binary); // Check whether file was opened correctly if (audio_output_file.fail()) { std::cerr << "error opening file " << audio_output_source << std::endl; From e0251a35645a6baaa8fc9115e18f95ca1bf1843e Mon Sep 17 00:00:00 2001 From: joel Date: Mon, 12 Nov 2018 09:27:02 -0800 Subject: [PATCH 2/5] grpc bin default path when cross compiling --- cmake/build_dependencies.cmake | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cmake/build_dependencies.cmake b/cmake/build_dependencies.cmake index beccdb0..310663c 100644 --- a/cmake/build_dependencies.cmake +++ b/cmake/build_dependencies.cmake @@ -70,9 +70,16 @@ set(_PROTOBUF_LIBRARIES ${PROTOBUF_LIB}) set(GOOGLEAPIS_GENS_PATH ${CMAKE_INSTALL_PREFIX}/gens) -if(NOT CMAKE_CROSSCOMPILING) - set(PROTOBUF_ROOT_FOLDER ${_GRPC_SRC_PATH}-build) - set(GRPC_PLUGINPATH ${_GRPC_SRC_PATH}-build) +if(CMAKE_CROSSCOMPILING) + if(NOT PROTOBUF_ROOT_FOLDER) + set(PROTOBUF_ROOT_FOLDER /usr/local/bin) + endif() + if(NOT GRPC_PLUGINPATH) + set(GRPC_PLUGINPATH /usr/local/bin) + endif() +else() + set(PROTOBUF_ROOT_FOLDER ${_GRPC_SRC_PATH}-build) + set(GRPC_PLUGINPATH ${_GRPC_SRC_PATH}-build) endif() ExternalProject_Add(googleapis From 3b4214210371fb197920498eedbb14e9721432cb Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Mon, 24 Feb 2020 21:25:43 -0800 Subject: [PATCH 3/5] Move gRPC to v1.27.2 --- CMakeLists.txt | 1 + cmake/build_dependencies.cmake | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 904b343..9bca9b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ endif() set(LDFLAGS grpc++ grpc gpr grpc_cronet address_sorting + upb absl_base absl_strings absl_throw_delegate ${_PROTOBUF_LIBRARIES} ${_CARES_LIBRARIES} ${_ZLIB_LIBRARIES} ${_SSL_LIBRARIES} ${_ALLTARGETS_LIBRARIES} diff --git a/cmake/build_dependencies.cmake b/cmake/build_dependencies.cmake index 310663c..788f17f 100644 --- a/cmake/build_dependencies.cmake +++ b/cmake/build_dependencies.cmake @@ -2,7 +2,7 @@ include (ExternalProject) include(CheckFunctionExists) if(NOT GRPC_VERSION) - set(GRPC_VERSION v1.16.0) + set(GRPC_VERSION v1.27.2) endif() if(ANDROID) From 4f58aeaa45fbca2c13aa4bc984792e4909467ac1 Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Thu, 21 May 2020 09:07:37 -0700 Subject: [PATCH 4/5] Create FUNDING.yml --- .github/FUNDING.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..5bbac4f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [jwinarske] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] From e2dfceb7beda0ac49a3e1fbd2421b735b113c081 Mon Sep 17 00:00:00 2001 From: Joel Winarske Date: Thu, 9 Jul 2020 15:19:12 +0000 Subject: [PATCH 5/5] move to v1.30.1 --- .travis.yml | 37 ++++++------- CMakeLists.txt | 87 +++++++++++++++--------------- README.md | 64 ++++++++--------------- appveyor.yml | 14 +++-- cmake/build_dependencies.cmake | 93 ++++++++++++++++---------------- cmake/build_googleapis.cmake | 96 ---------------------------------- cmake/googleapis.cmake | 72 +++++++++++++++++++++++++ src/json_util.cc | 53 ------------------- src/json_util.h | 23 -------- src/json_util_test.cc | 45 ---------------- src/run_assistant_audio.cc | 1 - src/run_assistant_file.cc | 1 - src/run_assistant_text.cc | 1 - 13 files changed, 208 insertions(+), 379 deletions(-) delete mode 100644 cmake/build_googleapis.cmake create mode 100644 cmake/googleapis.cmake delete mode 100644 src/json_util.cc delete mode 100644 src/json_util.h delete mode 100644 src/json_util_test.cc diff --git a/.travis.yml b/.travis.yml index 4a69d37..5ed9732 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,17 +9,9 @@ compiler: - clang env: - - BUILD_TYPE=Debug CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - BUILD_TYPE=Debug CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - BUILD_TYPE=Debug CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - - BUILD_TYPE=Release CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - BUILD_TYPE=Release CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - BUILD_TYPE=Release CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - - BUILD_TYPE=MinSizeRel CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - BUILD_TYPE=MinSizeRel CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" - - BUILD_TYPE=MinSizeRel CMAKE_ARGS="-DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE" + - BUILD_TYPE=Debug + - BUILD_TYPE=Release + - BUILD_TYPE=MinSizeRel addons: apt: @@ -30,26 +22,27 @@ install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mkdir ${DEPS_DIR} && cd ${DEPS_DIR} && pwd; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry wget --no-check-certificate https://cmake.org/files/v3.11/cmake-3.11.0-Linux-x86_64.tar.gz; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "96d67e21f0983ebf0fffc5b106ec338c *cmake-3.11.0-Linux-x86_64.tar.gz" > cmake_md5.txt; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry wget --no-check-certificate https://github.com/Kitware/CMake/releases/download/v3.17.3/cmake-3.17.3-Linux-x86_64.tar.gz; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "06bb006122e8e094f942bc9b2d999c92 *cmake-3.17.3-Linux-x86_64.tar.gz" > cmake_md5.txt; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then md5sum -c cmake_md5.txt; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xvf cmake-3.11.0-Linux-x86_64.tar.gz > /dev/null; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mv cmake-3.11.0-Linux-x86_64 cmake-install; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xvf cmake-3.17.3-Linux-x86_64.tar.gz > /dev/null; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mv cmake-3.17.3-Linux-x86_64 cmake-install; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then PATH=${DEPS_DIR}/cmake-install:${DEPS_DIR}/cmake-install/bin:$PATH; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry wget --no-check-certificate https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "a6103c8157246dd1ac70528878994f31 *go1.11.1.linux-amd64.tar.gz" > go_md5.txt; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then travis_retry wget --no-check-certificate https://golang.org/dl/go1.14.4.linux-amd64.tar.gz; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "0ea61d0d7e05bbe454b8b19569ad86c8 *go1.14.4.linux-amd64.tar.gz" > go_md5.txt; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then md5sum -c go_md5.txt; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xzf go1.11.1.linux-amd64.tar.gz > /dev/null; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then tar -xzf go1.14.4.linux-amd64.tar.gz > /dev/null; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export GOROOT=${DEPS_DIR}/go; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then PATH=${DEPS_DIR}/go/bin:$PATH; fi - before_script: - cd ${TRAVIS_BUILD_DIR} - mkdir build && cd build - - cmake -DCMAKE_VERBOSE_MAKEFILE=FALSE -DCMAKE_BUILD_TYPE=${BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX=${TRAVIS_BUILD_DIR}/build/dist ${CMAKE_ARGS} - .. + - cmake .. + -DCMAKE_BUILD_TYPE=${BUILD_TYPE} + -DCMAKE_VERBOSE_MAKEFILE=TRUE + -DCMAKE_STAGING_PREFIX=${TRAVIS_BUILD_DIR}/dist/usr/local + script: - cmake --build . --config ${BUILD_TYPE} --target install diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bca9b9..7b2d852 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.10.2) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "MinSizeRel" CACHE STRING "Choose the type of build, options are: Debug, Release, or MinSizeRel." FORCE) @@ -10,7 +10,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/cmake") if(NOT BUILD_NUMBER) set(BUILD_NUMBER 0) endif() -set(ASSISTANT_SDK_CPP_VERSION 0.1.${BUILD_NUMBER}) +set(ASSISTANT_SDK_CPP_VERSION 0.0.1.${BUILD_NUMBER}) set(PACKAGE_NAME assistant-sdk-cpp) project(${PACKAGE_NAME} VERSION "${ASSISTANT_SDK_CPP_VERSION}" LANGUAGES CXX C) @@ -25,45 +25,42 @@ include(build_dependencies) set(CMAKE_CXX_STANDARD_REQUIRED 11) set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) include(FindThreads) +include(googleapis) -set(GOOGLEAPIS_API_CCS - ${GOOGLEAPIS_GENS_PATH}/google/api/http.grpc.pb.cc - ${GOOGLEAPIS_GENS_PATH}/google/api/http.pb.cc - ${GOOGLEAPIS_GENS_PATH}/google/api/annotations.grpc.pb.cc - ${GOOGLEAPIS_GENS_PATH}/google/api/annotations.pb.cc -) -set(GOOGLEAPIS_TYPE_CCS - ${GOOGLEAPIS_GENS_PATH}/google/type/latlng.pb.cc - ${GOOGLEAPIS_GENS_PATH}/google/type/latlng.grpc.pb.cc -) -set(GOOGLEAPIS_RPC_CCS -) -set(GOOGLEAPIS_ASSISTANT_PATH google/assistant/embedded/v1alpha2) -set(GOOGLEAPIS_ASSISTANT_CCS - ${GOOGLEAPIS_GENS_PATH}/${GOOGLEAPIS_ASSISTANT_PATH}/embedded_assistant.pb.cc - ${GOOGLEAPIS_GENS_PATH}/${GOOGLEAPIS_ASSISTANT_PATH}/embedded_assistant.grpc.pb.cc +protobuf_generate_grpc_cpp( + ${PROTO_BASE_PATH}/google/api/http.proto + ${PROTO_BASE_PATH}/google/api/annotations.proto + ${PROTO_BASE_PATH}/google/type/latlng.proto + ${PROTO_BASE_PATH}/google/assistant/embedded/v1alpha2/embedded_assistant.proto ) set(GOOGLEAPIS_CCS - ${GOOGLEAPIS_ASSISTANT_CCS} ${GOOGLEAPIS_API_CCS} - ${GOOGLEAPIS_RPC_CCS} ${GOOGLEAPIS_TYPE_CCS} + ${_gRPC_PROTO_GENS_DIR}/google/api/http.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/api/http.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/api/annotations.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/api/annotations.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/type/latlng.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/type/latlng.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/assistant/embedded/v1alpha2/embedded_assistant.pb.cc + ${_gRPC_PROTO_GENS_DIR}/google/assistant/embedded/v1alpha2/embedded_assistant.grpc.pb.cc ) set_source_files_properties(${GOOGLEAPIS_CCS} PROPERTIES GENERATED TRUE) +include_directories(${_gRPC_PROTO_GENS_DIR}) -set(CORE_SRCS src/base64_encode.cc src/json_util.cc) +set(CORE_SRCS src/base64_encode.cc) set(AUDIO_INPUT_FILE_SRCS src/audio_input_file.cc) set(ASSISTANT_AUDIO_SRCS src/run_assistant_audio.cc src/audio_pa.cc) set(ASSISTANT_FILE_SRCS src/run_assistant_file.cc) set(ASSISTANT_TEXT_SRCS src/run_assistant_text.cc) - -include_directories(src) - - -set(EXE_DEPS googleapis_ccs portaudio_ext) +include_directories( + src + ${CMAKE_CURRENT_BINARY_DIR}/grpc_ext-prefix/src/grpc_ext/third_party/abseil-cpp +) if(WIN32 AND MSVC) add_definitions(-D_WIN32_WINNT=0x600) @@ -77,34 +74,38 @@ else() set(_ALLTARGETS_LIBRARIES ${CMAKE_DL_LIBS} rt m ${CMAKE_THREAD_LIBS_INIT}) endif() - set(LDFLAGS - grpc++ grpc gpr grpc_cronet address_sorting - upb absl_base absl_strings absl_throw_delegate - ${_PROTOBUF_LIBRARIES} ${_CARES_LIBRARIES} + grpc++ grpc address_sorting upb cares gpr + ${_ABSL_LIBRARIES} ${_PROTOBUF_LIBRARIES} ${_ZLIB_LIBRARIES} ${_SSL_LIBRARIES} ${_ALLTARGETS_LIBRARIES} ) +if(NOT HAVE_GETOPT_C) + set(EXT_DEPS gperf_ext) +endif() +set(EXT_DEPS ${EXT_DEPS} portaudio_ext) -add_library(googleapis_ccs STATIC ${GOOGLEAPIS_CCS}) -add_dependencies(googleapis_ccs googleapis) - -add_executable(run_assistant_text ${CORE_SRCS} ${ASSISTANT_TEXT_SRCS}) -target_link_libraries(run_assistant_text googleapis_ccs ${LDFLAGS}) -add_dependencies(run_assistant_text ${EXE_DEPS}) +add_executable(run_assistant_text ${GOOGLEAPIS_CCS} ${CORE_SRCS} ${ASSISTANT_TEXT_SRCS}) +target_link_libraries(run_assistant_text ${LDFLAGS}) +add_dependencies(run_assistant_text ${EXT_DEPS}) -add_executable(run_assistant_file ${CORE_SRCS} ${AUDIO_INPUT_FILE_SRCS} ${ASSISTANT_FILE_SRCS}) -target_link_libraries(run_assistant_file googleapis_ccs ${LDFLAGS}) -add_dependencies(run_assistant_file ${EXE_DEPS}) +add_executable(run_assistant_file ${GOOGLEAPIS_CCS} ${CORE_SRCS} ${AUDIO_INPUT_FILE_SRCS} ${ASSISTANT_FILE_SRCS}) +target_link_libraries(run_assistant_file ${LDFLAGS}) +add_dependencies(run_assistant_file ${EXT_DEPS}) -add_executable(run_assistant_audio ${CORE_SRCS} ${AUDIO_SRCS} ${ASSISTANT_AUDIO_SRCS}) -target_link_libraries(run_assistant_audio googleapis_ccs ${LDFLAGS} ${_PORTAUDIO_LIB}) -add_dependencies(run_assistant_audio ${EXE_DEPS}) +add_executable(run_assistant_audio ${GOOGLEAPIS_CCS} ${CORE_SRCS} ${AUDIO_SRCS} ${ASSISTANT_AUDIO_SRCS}) +target_link_libraries(run_assistant_audio ${LDFLAGS} ${_PORTAUDIO_LIB}) +add_dependencies(run_assistant_audio ${EXT_DEPS}) +if(APPLE) + target_link_libraries(run_assistant_text "-framework CoreFoundation") + target_link_libraries(run_assistant_file "-framework CoreFoundation") + target_link_libraries(run_assistant_audio "-framework CoreFoundation") +endif() install (TARGETS run_assistant_audio run_assistant_text run_assistant_file - RUNTIME DESTINATION bin + RUNTIME DESTINATION bin ) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/make_uninstall.cmake") diff --git a/README.md b/README.md index 942ae1a..b451f12 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Google Assistant SDK for devices - C++ +### Linux / OSX build status +[![Build Status](https://travis-ci.com/jwinarske/assistant-sdk-cpp.svg?branch=cmake)](https://travis-ci.com/jwinarske/assistant-sdk-cpp) + +### Windows build status +[![Build status](https://ci.appveyor.com/api/projects/status/op7vmksh3p0jkln4/branch/cmake?svg=true)](https://ci.appveyor.com/project/jwinarske/assistant-sdk-cpp/branch/cmake) + ## Requirements This project is officially supported on Ubuntu 14.04. Other Linux distributions may be able to run @@ -29,7 +35,6 @@ sudo rm -rf /usr/local/bin/grpc_* /usr/local/bin/protoc \ ``` git clone https://github.com/googlesamples/assistant-sdk-cpp.git cd assistant-sdk-cpp -export PROJECT_PATH=$(pwd) ``` 2. Install dependencies @@ -39,78 +44,51 @@ sudo apt-get install libasound2-dev # For ALSA sound output sudo apt-get install libcurl4-openssl-dev # CURL development library ``` -3. Build Protocol Buffer, gRPC, and Google APIs -``` -git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc -GRPC_PATH=${PROJECT_PATH}/grpc -cd ${GRPC_PATH} - -git submodule update --init - -cd third_party/protobuf -./autogen.sh && ./configure && make -sudo make install -sudo ldconfig - -export LDFLAGS="$LDFLAGS -lm" -cd ${GRPC_PATH} -make clean -make -sudo make install -sudo ldconfig - -cd ${PROJECT_PATH} -git clone https://github.com/googleapis/googleapis.git -cd googleapis/ -make LANGUAGE=cpp -``` - -4. Make sure you setup environment variable `$GOOGLEAPIS_GENS_PATH` -``` -export GOOGLEAPIS_GENS_PATH=${PROJECT_PATH}/googleapis/gens -``` - -5. Build this project +3. Build this project ``` -cd ${PROJECT_PATH} -make run_assistant +mkdir build && cd build +cmake .. -DCMAKE_STAGING_PREFIX=`pwd`/dist/usr/local +make install -j ``` -6. Get credentials file. It must be an end-user's credentials. +4. Get credentials file. It must be an end-user's credentials. * Go to the [Actions Console](https://console.actions.google.com/) and register your device model, following [these instructions](https://developers.google.com/assistant/sdk/guides/library/python/embed/register-device) * Move it in this folder and rename it to `client_secret.json` * run `get_credentials.sh` in this folder. It will create the file `credentials.json`. -7. Start one of the `run_assistant` samples: +5. Start one of the `run_assistant` samples: ```bash -./run_assistant_file --input ./resources/weather_in_mountain_view.raw --output ./response.wav --credentials ./credentials.json +export LD_LIBRARY_PATH=`pwd`/dist/usr/local/lib +./dist/usr/local/bin/run_assistant_file --input ../resources/weather_in_mountain_view.raw --output ./response.wav --credentials ../credentials.json aplay ./response.wav --rate=16000 --format=S16_LE ``` On a Linux workstation, you can alternatively use ALSA for audio input: ```bash -./run_assistant_audio --credentials ./credentials.json +export LD_LIBRARY_PATH=`pwd`/dist/usr/local/lib +./dist/usr/local/bin/run_assistant_audio --credentials ../credentials.json ``` You can use a text-based query instead of audio. This allows you to continually enter text queries to the Assistant. ```bash -./run_assistant_text --credentials ./credentials.json +export LD_LIBRARY_PATH=`pwd`/dist/usr/local/lib +./dist/usr/local/bin/run_assistant_text --credentials ../credentials.json ``` This takes input from `cin`, so you can send data to the program when it starts. ```bash -echo "what time is it" | ./run_assistant_text --credentials ./credentials.json +echo "what time is it" | ./dist/usr/local/bin/run_assistant_text --credentials ../credentials.json ``` To change the locale, include a `locale` parameter: ```bash -echo "Bonjour" | ./run_assistant_text --credentials ./credentials.json --locale "fr-FR" +echo "Bonjour" | ./dist/usr/local/bin/run_assistant_text --credentials ../credentials.json --locale "fr-FR" ``` Default Assistant gRPC API endpoint is `embeddedassistant.googleapis.com`. If you want to test with a custom Assistant gRPC API endpoint, you can pass `--api_endpoint CUSTOM_API_ENDPOINT`. @@ -120,7 +98,7 @@ Default Assistant gRPC API endpoint is `embeddedassistant.googleapis.com`. If yo To get a visual output from the Assistant, provide a command to be run alongside every step of the conversation. It will execute that command along along with a provided argument of a temporary HTML file. ```bash -echo "what time is it" | ./run_assistant_text --credentials ./credentials.json --html_out google-chrome +echo "what time is it" | ./dist/usr/local/bin/run_assistant_text --credentials ../credentials.json --html_out google-chrome ``` After you enter text, it will run `google-chrome /tmp/google-assistant-cpp-screen-out.html`. diff --git a/appveyor.yml b/appveyor.yml index fc8ed2e..073f264 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -68,11 +68,16 @@ init: - echo BUILD_NUMBER=%APPVEYOR_BUILD_NUMBER% stack: - - go 1.11 + - go 1.14.4 install: + - echo Downloading Yasm... + - mkdir windows_build_tools + - powershell -Command "(New-Object Net.WebClient).DownloadFile('https://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe', 'windows_build_tools\yasm.exe')" + - set PATH=%cd%\windows_build_tools;%PATH% - cmake --version - go version + - yasm --version build: parallel: true @@ -85,12 +90,15 @@ build_script: - mkdir build - cd build - - cmake %CMAKE_TOOLCHAIN_ARGS% -G"%GENERATOR%" -DCMAKE_VERBOSE_MAKEFILE=TRUE + - cmake %CMAKE_TOOLCHAIN_ARGS% -G"%GENERATOR%" + -DCMAKE_VERBOSE_MAKEFILE=TRUE -DCMAKE_BUILD_TYPE=%CONFIGURATION% - "-DCMAKE_INSTALL_PREFIX=%DIST_DIR%\%APPVEYOR_BUILD_WORKER_IMAGE%" + -DCMAKE_ASM_NASM_COMPILER="yasm.exe" + -DCMAKE_STAGING_PREFIX="%DIST_DIR%\%APPVEYOR_BUILD_WORKER_IMAGE%\${CMAKE_INSTALL_PREFIX}" -DBUILD_NUMBER=%APPVEYOR_BUILD_NUMBER% %CMAKE_ARGS% .. + - set CL=/MP - cmake --build . --config %CONFIGURATION% --target all after_build: diff --git a/cmake/build_dependencies.cmake b/cmake/build_dependencies.cmake index 788f17f..4494e02 100644 --- a/cmake/build_dependencies.cmake +++ b/cmake/build_dependencies.cmake @@ -2,7 +2,7 @@ include (ExternalProject) include(CheckFunctionExists) if(NOT GRPC_VERSION) - set(GRPC_VERSION v1.27.2) + set(GRPC_VERSION v1.30.1) endif() if(ANDROID) @@ -11,15 +11,23 @@ if(ANDROID) -DRUN_HAVE_POSIX_REGEX=0 -DRUN_HAVE_STEADY_CLOCK=0 -DCMAKE_EXE_LINKER_FLAGS=-llog - -DgRPC_BUILD_CODEGEN=OFF - -DgRPC_BUILD_CSHARP_EXT=OFF ) endif() + +set(GRPC_SRC_PATH ${CMAKE_CURRENT_BINARY_DIR}/grpc_ext-prefix/src/grpc_ext) + +if(NOT MSVC) + set(gRPC_ZLIB_PROVIDER package) +else() + set(gRPC_ZLIB_PROVIDER module) +endif() + ExternalProject_Add(grpc_ext GIT_REPOSITORY "https://github.com/grpc/grpc" GIT_TAG ${GRPC_VERSION} GIT_SHALLOW 1 + PATCH_COMMAND "" UPDATE_COMMAND "" BUILD_IN_SOURCE 0 CMAKE_ARGS @@ -28,22 +36,43 @@ ExternalProject_Add(grpc_ext -DANDROID_STL=${ANDROID_STL} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_STAGING_PREFIX=${CMAKE_STAGING_PREFIX} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -DCMAKE_ASM_NASM_COMPILER=${CMAKE_ASM_NASM_COMPILER} + -DgRPC_INSTALL=ON + -DgRPC_BUILD_CODEGEN=ON + -DgRPC_BUILD_CSHARP_EXT=ON + -DgRPC_ZLIB_PROVIDER=${gRPC_ZLIB_PROVIDER} ${GRPC_ANDROID_ARGS} ) set(_GRPC_SRC_PATH ${CMAKE_BINARY_DIR}/grpc_ext-prefix/src/grpc_ext) set(_GRPC_LIBRARIES_DIR ${_GRPC_SRC_PATH}-build) +set(_ABSL_LIBRARIES + absl_bad_optional_access + absl_str_format_internal + absl_time + absl_time_zone + absl_civil_time + absl_strings + absl_strings_internal + absl_throw_delegate + absl_int128 + absl_base + absl_spinlock_wait + absl_raw_logging_internal + absl_log_severity + absl_dynamic_annotations +) + set(_SSL_LIBRARIES_DIRS ${_GRPC_SRC_PATH}-build/third_party/boringssl/crypto ${_GRPC_SRC_PATH}-build/third_party/boringssl/ssl - ${_GRPC_SRC_PATH}-build/third_party/boringssl/decrepit ) -set(_SSL_LIBRARIES ssl decrepit crypto) - +set(_SSL_LIBRARIES ssl crypto) if(NOT MSVC) set(_ZLIB_LIBRARIES z) @@ -55,8 +84,6 @@ else() endif() endif() -set(_CARES_LIBRARIES cares) - if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(PROTOBUF_LIB protobufd) else() @@ -68,42 +95,6 @@ endif() set(_PROTOBUF_LIBRARIES ${PROTOBUF_LIB}) -set(GOOGLEAPIS_GENS_PATH ${CMAKE_INSTALL_PREFIX}/gens) - -if(CMAKE_CROSSCOMPILING) - if(NOT PROTOBUF_ROOT_FOLDER) - set(PROTOBUF_ROOT_FOLDER /usr/local/bin) - endif() - if(NOT GRPC_PLUGINPATH) - set(GRPC_PLUGINPATH /usr/local/bin) - endif() -else() - set(PROTOBUF_ROOT_FOLDER ${_GRPC_SRC_PATH}-build) - set(GRPC_PLUGINPATH ${_GRPC_SRC_PATH}-build) -endif() - -ExternalProject_Add(googleapis - GIT_REPOSITORY https://github.com/googleapis/googleapis.git - GIT_TAG master - GIT_SHALLOW 1 - PATCH_COMMAND - cmake -E copy - ${CMAKE_SOURCE_DIR}/cmake/build_googleapis.cmake - ${CMAKE_BINARY_DIR}/googleapis-prefix/src/googleapis/CMakeLists.txt - UPDATE_COMMAND "" - BUILD_IN_SOURCE 0 - CMAKE_ARGS - -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} - -DProtobuf_DEBUG=OFF - -DProtobuf_SRC_ROOT_FOLDER=${PROTOBUF_ROOT_FOLDER} - -DGRPCPLUGIN_PATH=${GRPC_PLUGINPATH} - -DOUTPUT=${GOOGLEAPIS_GENS_PATH} - INSTALL_COMMAND "" -) -add_dependencies(googleapis grpc_ext) - - if(MSVC) if(${TARGET_ARCH} STREQUAL "x86_64") set(_PORTAUDIO_LIB portaudio_x64) @@ -124,6 +115,7 @@ if(NOT ANDROID) CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_STAGING_PREFIX=${CMAKE_STAGING_PREFIX} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} @@ -145,6 +137,7 @@ else() -DANDROID_STL=${ANDROID_STL} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_STAGING_PREFIX=${CMAKE_STAGING_PREFIX} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} @@ -171,6 +164,7 @@ if(NOT HAVE_GETOPT_C) -DANDROID_STL=${ANDROID_STL} -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + -DCMAKE_STAGING_PREFIX=${CMAKE_STAGING_PREFIX} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} @@ -184,14 +178,17 @@ endif() include_directories( - ${CMAKE_INSTALL_PREFIX}/include + ${CMAKE_STAGING_PREFIX}/include ${_GRPC_SRC_PATH} - ${GOOGLEAPIS_GENS_PATH} ) link_directories( - ${CMAKE_INSTALL_PREFIX}/lib - ${CMAKE_INSTALL_PREFIX}/lib/static + ${CMAKE_STAGING_PREFIX}/lib + ${CMAKE_STAGING_PREFIX}/lib/static ${_GRPC_LIBRARIES_DIR} ${_SSL_LIBRARIES_DIRS} ) + +set(Protobuf_PROTOC_EXECUTABLE ${CMAKE_STAGING_PREFIX}/bin/protoc${CMAKE_EXECUTABLE_SUFFIX}) + +set(PROTO_BASE_PATH ${CMAKE_CURRENT_BINARY_DIR}/grpc_ext-prefix/src/grpc_ext/third_party/googleapis) diff --git a/cmake/build_googleapis.cmake b/cmake/build_googleapis.cmake deleted file mode 100644 index f0844f4..0000000 --- a/cmake/build_googleapis.cmake +++ /dev/null @@ -1,96 +0,0 @@ -cmake_minimum_required(VERSION 3.11) - -set(Protobuf_USE_STATIC_LIBS OFF) - -if(NOT Protobuf_SRC_ROOT_FOLDER) - set(Protobuf_SRC_ROOT_FOLDER ${CMAKE_INSTALL_PREFIX}) -endif() - -set(Protobuf_IMPORT_DIRS - ${CMAKE_SOURCE_DIR} - ${CMAKE_BINARY_DIR} - ${CMAKE_INSTALL_PREFIX}/include -) - -if(NOT WIN32) - set(BIN_SUFFIX "") - set(PATH_SEPERATOR ":") -else() - set(PATH_SEPERATOR ";") - set(BIN_SUFFIX ".exe") -endif() - -find_package(Protobuf REQUIRED) - -include_directories(${CMAKE_BINARY_DIR}) - -if(NOT Protobuf_FOUND) - message(FATAL_ERROR "Set Protobuf_SRC_ROOT_FOLDER to the desired sysroot...") -endif() -message(STATUS "Protobuf_VERSION=${Protobuf_VERSION}") - -# Choose the output directory -if(NOT OUTPUT) - set(OUTPUT ./gens) -endif() -file(MAKE_DIRECTORY ${OUTPUT}) - - -# Choose the target language. -if(NOT LANGUAGE) - set(LANGUAGE cpp) -endif() -if(${LANGUAGE} STREQUAL "go") - MESSAGE(FATAL_ERROR "Go source files are not generated from this repository. See: https://github.com/google/go-genproto") -endif() - - -# Choose grpc plugin -if(NOT GRPCPLUGIN_PATH) - set(GRPCPLUGIN_PATH /usr/local/bin/grpc_${LANGUAGE}_plugin) -endif() -set(GRPCPLUGIN "${GRPCPLUGIN_PATH}/grpc_${LANGUAGE}_plugin${BIN_SUFFIX}") - -# Choose the proto include directory. -#include_directories(${Protobuf_INCLUDE_DIRS}) - -get_filename_component(protoc_path ${Protobuf_PROTOC_EXECUTABLE} DIRECTORY) -file(TO_NATIVE_PATH ${protoc_path} protoc_path) - -set(ENV{PATH} "${protoc_path}${PATH_SEPERATOR}$ENV{PATH}") - -# Compile the entire repository -# -file(TO_NATIVE_PATH ${OUTPUT} NATIVE_OUTPUT) -file(TO_NATIVE_PATH ${GRPCPLUGIN} NATIVE_GRPCPLUGIN) -file(TO_NATIVE_PATH ${Protobuf_INCLUDE_DIRS} NATIVE_Protobuf_INCLUDE_DIRS) -MESSAGE(STATUS "Protobuf_INCLUDE_DIRS=${NATIVE_Protobuf_INCLUDE_DIRS}") -MESSAGE(STATUS "OUTPUT=${NATIVE_OUTPUT}") -MESSAGE(STATUS "LANGUAGE=${LANGUAGE}") -MESSAGE(STATUS "GRPCPLUGIN=${NATIVE_GRPCPLUGIN}") -message(STATUS "WORKING_DIRECTORY=${CMAKE_SOURCE_DIR}") - -file(MAKE_DIRECTORY ${OUTPUT}) - -file(GLOB_RECURSE src_list ${CMAKE_SOURCE_DIR} google/*.proto) - -foreach(src ${src_list}) - string (REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" rel_src ${src}) - file(TO_NATIVE_PATH ${rel_src} NATIVE_rel_src) - - if(Protobuf_DEBUG) - MESSAGE(STATUS "protoc${BIN_SUFFIX} --proto_path=.${PATH_SEPERATOR}${NATIVE_Protobuf_INCLUDE_DIRS} --${LANGUAGE}_out=${NATIVE_OUTPUT} --grpc_out=${NATIVE_OUTPUT} --plugin=protoc-gen-grpc=${NATIVE_GRPCPLUGIN} ${NATIVE_rel_src}") - else() - MESSAGE(STATUS ${NATIVE_rel_src}) - endif() - - execute_process( - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMAND "protoc${BIN_SUFFIX}" - "--proto_path=.${PATH_SEPERATOR}${NATIVE_Protobuf_INCLUDE_DIRS}" - "--${LANGUAGE}_out=${NATIVE_OUTPUT}" - "--grpc_out=${NATIVE_OUTPUT}" - "--plugin=protoc-gen-grpc=${NATIVE_GRPCPLUGIN}" - ${NATIVE_rel_src} - ) -endforeach(src) diff --git a/cmake/googleapis.cmake b/cmake/googleapis.cmake new file mode 100644 index 0000000..9edcaca --- /dev/null +++ b/cmake/googleapis.cmake @@ -0,0 +1,72 @@ +# Set grpc plugin +if(NOT _gRPC_CPP_PLUGIN) + set(_gRPC_CPP_PLUGIN ${CMAKE_STAGING_PREFIX}/bin/grpc_cpp_plugin${CMAKE_EXECUTABLE_SUFFIX}) +endif() + +if(NOT _gRPC_PROTO_GENS_DIR) + set(_gRPC_PROTO_GENS_DIR ${CMAKE_CURRENT_BINARY_DIR}/gens) +endif() + +if(NOT _gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR) + set(_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR ${CMAKE_STAGING_PREFIX}/include) +endif() + +# Normalize all paths +file(TO_NATIVE_PATH ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR} NATIVE_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR) +file(TO_NATIVE_PATH ${_gRPC_CPP_PLUGIN} NATIVE_gRPC_CPP_PLUGIN) +file(TO_NATIVE_PATH ${_gRPC_PROTO_GENS_DIR} NATIVE_gRPC_PROTO_GENS_DIR) +file(TO_NATIVE_PATH ${PROTO_BASE_PATH} NATIVE_PROTO_BASE_PATH) + +# Create directory for generated .proto files +file(MAKE_DIRECTORY ${NATIVE_gRPC_PROTO_GENS_DIR}) + +# protobuf_generate_grpc_cpp +# -------------------------- +# +# Add custom commands to process ``.proto`` files to C++ using protoc and +# GRPC plugin:: +# +# protobuf_generate_grpc_cpp [...] +# +# ``ARGN`` +# ``.proto`` files +# +function(protobuf_generate_grpc_cpp) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files") + return() + endif() + + set(_protobuf_include_path -I . -I ${NATIVE_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR}) + + foreach(FIL ${ARGN}) + + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + file(RELATIVE_PATH REL_FIL ${PROTO_BASE_PATH} ${ABS_FIL}) + get_filename_component(REL_DIR ${REL_FIL} DIRECTORY) + + set(RELFIL_WE ${_gRPC_PROTO_GENS_DIR}/${REL_DIR}/${FIL_WE}) + + # Normalize paths + file(TO_NATIVE_PATH ${RELFIL_WE} NATIVE_RELFIL_WE) + file(TO_NATIVE_PATH ${REL_FIL} NATIVE_REL_FIL) + + add_custom_command( + OUTPUT ${NATIVE_RELFIL_WE}.grpc.pb.cc + ${NATIVE_RELFIL_WE}.grpc.pb.h + ${NATIVE_RELFIL_WE}_mock.grpc.pb.h + ${NATIVE_RELFIL_WE}.pb.cc + ${NATIVE_RELFIL_WE}.pb.h + COMMAND ${Protobuf_PROTOC_EXECUTABLE} + ARGS --grpc_out=generate_mock_code=true:${NATIVE_gRPC_PROTO_GENS_DIR} + --plugin=protoc-gen-grpc=${NATIVE_gRPC_CPP_PLUGIN} + --cpp_out=${NATIVE_gRPC_PROTO_GENS_DIR} + ${_protobuf_include_path} + ${NATIVE_REL_FIL} + DEPENDS ${ABS_FIL} grpc_ext + WORKING_DIRECTORY ${PROTO_BASE_PATH} + COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}" + VERBATIM) + endforeach() +endfunction() diff --git a/src/json_util.cc b/src/json_util.cc deleted file mode 100644 index 1911c92..0000000 --- a/src/json_util.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2017 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License 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. -*/ - -#include "json_util.h" -#include "scope_exit.h" - -extern "C" { -#include -} - -#include -#include - -grpc_json* GetJsonValueOrNullFromDict(grpc_json* dict_node, const char* key) { - if (dict_node->type != GRPC_JSON_OBJECT) { - return nullptr; - } - - grpc_json* child = dict_node->child; - while (child != nullptr) { - if (child->key != nullptr && strcmp(child->key, key) == 0) { - return child; - } - child = child->next; - } - return nullptr; -} - -grpc_json* GetJsonValueOrNullFromArray(grpc_json* array_node, int index) { - if (array_node->type != GRPC_JSON_ARRAY) { - return nullptr; - } - - grpc_json* child = array_node->child; - while (child != nullptr && index != 0) { - child = child->next; - index--; - } - return child; -} diff --git a/src/json_util.h b/src/json_util.h deleted file mode 100644 index 3b6ba78..0000000 --- a/src/json_util.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2017 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License 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 JSON_UTIL_H -#define JSON_UTIL_H - -#include -#include - -#endif diff --git a/src/json_util_test.cc b/src/json_util_test.cc deleted file mode 100644 index f50f0bf..0000000 --- a/src/json_util_test.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2017 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License 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. -*/ - -#include "json_util.h" - -#include - -bool check_result(const std::string& input_json, - std::unique_ptr intended_result) { - std::unique_ptr result = GetCustomResponseOrNull(input_json); - return (intended_result == nullptr && result == nullptr) || - (intended_result != nullptr && result != nullptr && - *intended_result == *result); -} - -int main() { - std::string invalid_json = ""; - std::unique_ptr intended_result(nullptr); - if (!check_result(invalid_json, std::move(intended_result))) { - std::cerr << "Test failed for invalid JSON" << std::endl; - return 1; - } - - std::string incomplete_json = "{}"; - intended_result.reset(nullptr); - if (!check_result(incomplete_json, std::move(intended_result))) { - std::cerr << "Test failed for incomplete JSON" << std::endl; - return 1; - } - - std::cerr << "Test passed" << std::endl; -} diff --git a/src/run_assistant_audio.cc b/src/run_assistant_audio.cc index 47b74bf..b33b88f 100644 --- a/src/run_assistant_audio.cc +++ b/src/run_assistant_audio.cc @@ -35,7 +35,6 @@ limitations under the License. #include "audio_input.h" #include "audio_input_file.h" #include "base64_encode.h" -#include "json_util.h" namespace assistant = google::assistant::embedded::v1alpha2; diff --git a/src/run_assistant_file.cc b/src/run_assistant_file.cc index 8f51437..c827910 100644 --- a/src/run_assistant_file.cc +++ b/src/run_assistant_file.cc @@ -33,7 +33,6 @@ limitations under the License. #include "audio_input.h" #include "audio_input_file.h" #include "base64_encode.h" -#include "json_util.h" namespace assistant = google::assistant::embedded::v1alpha2; diff --git a/src/run_assistant_text.cc b/src/run_assistant_text.cc index 27496d9..5918f04 100644 --- a/src/run_assistant_text.cc +++ b/src/run_assistant_text.cc @@ -33,7 +33,6 @@ limitations under the License. #include "audio_input.h" #include "audio_input_file.h" #include "base64_encode.h" -#include "json_util.h" namespace assistant = google::assistant::embedded::v1alpha2;