diff --git a/release/files_common b/release/files_common index 7ef893ebc5..9728a0c4a6 100644 --- a/release/files_common +++ b/release/files_common @@ -322,9 +322,7 @@ selfdrive/test/test_fingerprints.py selfdrive/test/test_car_models.py selfdrive/ui/SConscript -selfdrive/ui/*.c selfdrive/ui/*.cc -selfdrive/ui/*.h selfdrive/ui/*.hpp selfdrive/ui/ui selfdrive/ui/spinner/Makefile diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 88bde059ea..8f22824fbb 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -4,7 +4,7 @@ src = ['ui.cc', 'paint.cc', 'sidebar.cc', '#phonelibs/nanovg/nanovg.c'] libs = [common, 'zmq', 'czmq', 'capnp', 'kj', 'm', cereal, messaging, gpucommon, visionipc] if arch == "aarch64": - src += ['sound.cc', 'slplay.c'] + src += ['sound.cc'] libs += ['EGL', 'GLESv3', 'gnustl_shared', 'log', 'utils', 'gui', 'hardware', 'ui', 'CB', 'gsl', 'adreno_utils', 'OpenSLES', 'cutils', 'uuid', 'OpenCL'] linkflags = ['-Wl,-rpath=/system/lib64,-rpath=/system/comma/usr/lib'] else: diff --git a/selfdrive/ui/linux.cc b/selfdrive/ui/linux.cc index 17a3938f75..97fe769e0a 100644 --- a/selfdrive/ui/linux.cc +++ b/selfdrive/ui/linux.cc @@ -82,13 +82,12 @@ int touch_read(TouchState *s, int* out_x, int* out_y) { #include "sound.hpp" -void ui_sound_init() {} -void ui_sound_destroy() {} - -void set_volume(int volume) {} - -void play_alert_sound(AudibleAlert alert) {} -void stop_alert_sound(AudibleAlert alert) {} +bool Sound::init(int volume) { return true; } +bool Sound::play(AudibleAlert alert, int repeat) { return true; } +void Sound::stop() {} +void Sound::setVolume(int volume, int timeout_seconds) {} +AudibleAlert Sound::currentPlaying() { return AudibleAlert::NONE; } +Sound::~Sound() {} #include "common/visionimg.h" #include diff --git a/selfdrive/ui/slplay.c b/selfdrive/ui/slplay.c deleted file mode 100644 index ddfbad56c5..0000000000 --- a/selfdrive/ui/slplay.c +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include -#include -#include -#include - -#include "common/timing.h" -#include "slplay.h" - -SLEngineItf engineInterface = NULL; -SLObjectItf outputMix = NULL; -SLObjectItf engine = NULL; -uri_player players[32] = {{NULL, NULL, NULL}}; - -uint64_t loop_start = 0; -uint64_t loop_start_ctx = 0; - -uri_player* get_player_by_uri(const char* uri) { - for (uri_player *s = players; s->uri != NULL; s++) { - if (strcmp(s->uri, uri) == 0) { - return s; - } - } - - return NULL; -} - -uri_player* slplay_create_player_for_uri(const char* uri, char **error) { - uri_player player = { uri, NULL, NULL }; - - SLresult result; - SLDataLocator_URI locUri = {SL_DATALOCATOR_URI, (SLchar *) uri}; - SLDataFormat_MIME formatMime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; - SLDataSource audioSrc = {&locUri, &formatMime}; - - SLDataLocator_OutputMix outMix = {SL_DATALOCATOR_OUTPUTMIX, outputMix}; - SLDataSink audioSnk = {&outMix, NULL}; - - result = (*engineInterface)->CreateAudioPlayer(engineInterface, &player.player, &audioSrc, &audioSnk, 0, NULL, NULL); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to create audio player"; - return NULL; - } - - result = (*(player.player))->Realize(player.player, SL_BOOLEAN_FALSE); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to realize audio player"; - return NULL; - } - - result = (*(player.player))->GetInterface(player.player, SL_IID_PLAY, &(player.playInterface)); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to get player interface"; - return NULL; - } - - result = (*(player.playInterface))->SetPlayState(player.playInterface, SL_PLAYSTATE_PAUSED); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to initialize playstate to SL_PLAYSTATE_PAUSED"; - return NULL; - } - - uri_player *p = players; - while (p->uri != NULL) { - p++; - } - *p = player; - - return p; -} - -void slplay_setup(char **error) { - SLresult result; - SLEngineOption engineOptions[] = {{SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE}}; - result = slCreateEngine(&engine, 1, engineOptions, 0, NULL, NULL); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to create OpenSL engine"; - } - - result = (*engine)->Realize(engine, SL_BOOLEAN_FALSE); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to realize OpenSL engine"; - } - - result = (*engine)->GetInterface(engine, SL_IID_ENGINE, &engineInterface); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to realize OpenSL engine"; - } - - const SLInterfaceID ids[1] = {SL_IID_VOLUME}; - const SLboolean req[1] = {SL_BOOLEAN_FALSE}; - result = (*engineInterface)->CreateOutputMix(engineInterface, &outputMix, 1, ids, req); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to create output mix"; - } - - result = (*outputMix)->Realize(outputMix, SL_BOOLEAN_FALSE); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to realize output mix"; - } -} - -void slplay_destroy() { - for (uri_player *player = players; player->uri != NULL; player++) { - if (player->player) { - (*(player->player))->Destroy(player->player); - } - } - - (*outputMix)->Destroy(outputMix); - (*engine)->Destroy(engine); -} - -void slplay_stop(uri_player* player, char **error) { - SLPlayItf playInterface = player->playInterface; - SLresult result; - - // stop a loop - loop_start = 0; - - result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_PAUSED); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to set SL_PLAYSTATE_STOPPED"; - return; - } -} - -void slplay_stop_uri(const char* uri, char **error) { - uri_player* player = get_player_by_uri(uri); - slplay_stop(player, error); -} - -void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event) { - uint64_t cb_loop_start = *((uint64_t*)context); - if (event == SL_PLAYEVENT_HEADATEND && cb_loop_start == loop_start) { - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); - (*playItf)->SetMarkerPosition(playItf, 0); - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); - } -} - -void slplay_play (const char *uri, bool loop, char **error) { - SLresult result; - - uri_player* player = get_player_by_uri(uri); - if (player == NULL) { - player = slplay_create_player_for_uri(uri, error); - if (*error) { - return; - } - } - - SLPlayItf playInterface = player->playInterface; - if (loop) { - loop_start = nanos_since_boot(); - loop_start_ctx = loop_start; - result = (*playInterface)->RegisterCallback(playInterface, slplay_callback, &loop_start_ctx); - if (result != SL_RESULT_SUCCESS) { - char error[64]; - snprintf(error, sizeof(error), "Failed to register callback. %d", result); - *error = error[0]; - return; - } - - result = (*playInterface)->SetCallbackEventsMask(playInterface, SL_PLAYEVENT_HEADATEND); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to set callback event mask"; - return; - } - } - - // Reset the audio player - result = (*playInterface)->ClearMarkerPosition(playInterface); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to clear marker position"; - return; - } - result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_PAUSED); - result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_STOPPED); - result = (*playInterface)->SetPlayState(playInterface, SL_PLAYSTATE_PLAYING); - if (result != SL_RESULT_SUCCESS) { - *error = "Failed to set SL_PLAYSTATE_PLAYING"; - } -} diff --git a/selfdrive/ui/slplay.h b/selfdrive/ui/slplay.h deleted file mode 100644 index f8c39ceeb7..0000000000 --- a/selfdrive/ui/slplay.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SLPLAY_H -#define SLPLAY_H - -#include -#include -#include - -typedef struct { - const char* uri; - SLObjectItf player; - SLPlayItf playInterface; -} uri_player; - -void slplay_setup(char **error); -uri_player* slplay_create_player_for_uri(const char* uri, char **error); -void slplay_play (const char *uri, bool loop, char **error); -void slplay_stop_uri (const char* uri, char **error); -void slplay_destroy(); - -#endif - diff --git a/selfdrive/ui/sound.cc b/selfdrive/ui/sound.cc index f64cde07ef..1b02f14321 100644 --- a/selfdrive/ui/sound.cc +++ b/selfdrive/ui/sound.cc @@ -1,91 +1,137 @@ -#include -#include "sound.hpp" +#include "sound.hpp" +#include +#include +#include #include "common/swaglog.h" +#include "common/timing.h" + +#define LogOnError(func, msg) \ + if ((func) != SL_RESULT_SUCCESS) { LOGW(msg); } + +#define ReturnOnError(func, msg) \ + if ((func) != SL_RESULT_SUCCESS) { LOGW(msg); return false; } + +static std::map sound_map{ + {AudibleAlert::CHIME_DISENGAGE, "../assets/sounds/disengaged.wav"}, + {AudibleAlert::CHIME_ENGAGE, "../assets/sounds/engaged.wav"}, + {AudibleAlert::CHIME_WARNING1, "../assets/sounds/warning_1.wav"}, + {AudibleAlert::CHIME_WARNING2, "../assets/sounds/warning_2.wav"}, + {AudibleAlert::CHIME_WARNING2_REPEAT, "../assets/sounds/warning_2.wav"}, + {AudibleAlert::CHIME_WARNING_REPEAT, "../assets/sounds/warning_repeat.wav"}, + {AudibleAlert::CHIME_ERROR, "../assets/sounds/error.wav"}, + {AudibleAlert::CHIME_PROMPT, "../assets/sounds/error.wav"}}; + +struct Sound::Player { + SLObjectItf player; + SLPlayItf playItf; + // slplay_callback runs on a background thread,use atomic to ensure thread safe. + std::atomic repeat; +}; -typedef struct { - AudibleAlert alert; - const char* uri; - bool loop; -} sound_file; +bool Sound::init(int volume) { + SLEngineOption engineOptions[] = {{SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE}}; + const SLInterfaceID ids[1] = {SL_IID_VOLUME}; + const SLboolean req[1] = {SL_BOOLEAN_FALSE}; + SLEngineItf engineInterface = NULL; + ReturnOnError(slCreateEngine(&engine_, 1, engineOptions, 0, NULL, NULL), "Failed to create OpenSL engine"); + ReturnOnError((*engine_)->Realize(engine_, SL_BOOLEAN_FALSE), "Failed to realize OpenSL engine"); + ReturnOnError((*engine_)->GetInterface(engine_, SL_IID_ENGINE, &engineInterface), "Failed to get OpenSL engine interface"); + ReturnOnError((*engineInterface)->CreateOutputMix(engineInterface, &outputMix_, 1, ids, req), "Failed to create output mix"); + ReturnOnError((*outputMix_)->Realize(outputMix_, SL_BOOLEAN_FALSE), "Failed to realize output mix"); + + for (auto &kv : sound_map) { + SLDataLocator_URI locUri = {SL_DATALOCATOR_URI, (SLchar *)kv.second}; + SLDataFormat_MIME formatMime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED}; + SLDataSource audioSrc = {&locUri, &formatMime}; + SLDataLocator_OutputMix outMix = {SL_DATALOCATOR_OUTPUTMIX, outputMix_}; + SLDataSink audioSnk = {&outMix, NULL}; + + SLObjectItf player = NULL; + SLPlayItf playItf = NULL; + ReturnOnError((*engineInterface)->CreateAudioPlayer(engineInterface, &player, &audioSrc, &audioSnk, 0, NULL, NULL), "Failed to create audio player"); + ReturnOnError((*player)->Realize(player, SL_BOOLEAN_FALSE), "Failed to realize audio player"); + ReturnOnError((*player)->GetInterface(player, SL_IID_PLAY, &playItf), "Failed to get player interface"); + ReturnOnError((*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED), "Failed to initialize playstate to SL_PLAYSTATE_PAUSED"); + + player_[kv.first] = new Sound::Player{player, playItf}; + } -extern "C"{ -#include "slplay.h" + setVolume(volume); + return true; } -int last_volume = 0; - -void set_volume(int volume) { - if (last_volume != volume) { - char volume_change_cmd[64]; - sprintf(volume_change_cmd, "service call audio 3 i32 3 i32 %d i32 1 &", volume); - - // 5 second timeout at 60fps - int volume_changed = system(volume_change_cmd); - last_volume = volume; +AudibleAlert Sound::currentPlaying() { + if (currentSound_ != AudibleAlert::NONE) { + auto playItf = player_.at(currentSound_)->playItf; + SLuint32 state; + if (SL_RESULT_SUCCESS == (*playItf)->GetPlayState(playItf, &state) && + (state == SL_PLAYSTATE_STOPPED || state == SL_PLAYSTATE_PAUSED)) { + currentSound_ = AudibleAlert::NONE; + } } + return currentSound_; } - -sound_file sound_table[] = { - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_DISENGAGE, "../assets/sounds/disengaged.wav", false }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_ENGAGE, "../assets/sounds/engaged.wav", false }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_WARNING1, "../assets/sounds/warning_1.wav", false }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_WARNING2, "../assets/sounds/warning_2.wav", false }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_WARNING2_REPEAT, "../assets/sounds/warning_2.wav", true }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_WARNING_REPEAT, "../assets/sounds/warning_repeat.wav", true }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_ERROR, "../assets/sounds/error.wav", false }, - { cereal::CarControl::HUDControl::AudibleAlert::CHIME_PROMPT, "../assets/sounds/error.wav", false }, - { cereal::CarControl::HUDControl::AudibleAlert::NONE, NULL, false }, -}; - -sound_file* get_sound_file(AudibleAlert alert) { - for (sound_file *s = sound_table; s->alert != cereal::CarControl::HUDControl::AudibleAlert::NONE; s++) { - if (s->alert == alert) { - return s; - } +void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event) { + Sound::Player *s = reinterpret_cast(context); + if (event == SL_PLAYEVENT_HEADATEND && s->repeat > 1) { + --s->repeat; + (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); + (*playItf)->SetMarkerPosition(playItf, 0); + (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); } - - return NULL; } -void play_alert_sound(AudibleAlert alert) { - sound_file* sound = get_sound_file(alert); - char* error = NULL; +bool Sound::play(AudibleAlert alert, int repeat) { + if (currentSound_ != AudibleAlert::NONE) { + stop(); + } + auto player = player_.at(alert); + SLPlayItf playItf = player->playItf; + player->repeat = repeat; + if (player->repeat > 0) { + ReturnOnError((*playItf)->RegisterCallback(playItf, slplay_callback, player), "Failed to register callback"); + ReturnOnError((*playItf)->SetCallbackEventsMask(playItf, SL_PLAYEVENT_HEADATEND), "Failed to set callback event mask"); + } - slplay_play(sound->uri, sound->loop, &error); - if(error) { - LOGW("error playing sound: %s", error); + // Reset the audio player + ReturnOnError((*playItf)->ClearMarkerPosition(playItf), "Failed to clear marker position"); + uint32_t states[] = {SL_PLAYSTATE_PAUSED, SL_PLAYSTATE_STOPPED, SL_PLAYSTATE_PLAYING}; + for (auto state : states) { + ReturnOnError((*playItf)->SetPlayState(playItf, state), "Failed to set SL_PLAYSTATE_PLAYING"); } + currentSound_ = alert; + return true; } -void stop_alert_sound(AudibleAlert alert) { - sound_file* sound = get_sound_file(alert); - char* error = NULL; - - slplay_stop_uri(sound->uri, &error); - if(error) { - LOGW("error stopping sound: %s", error); +void Sound::stop() { + if (currentSound_ != AudibleAlert::NONE) { + auto player = player_.at(currentSound_); + player->repeat = 0; + LogOnError((*(player->playItf))->SetPlayState(player->playItf, SL_PLAYSTATE_PAUSED), "Failed to set SL_PLAYSTATE_PAUSED"); + currentSound_ = AudibleAlert::NONE; } } -void ui_sound_init() { - char *error = NULL; - slplay_setup(&error); - if (error) goto fail; - - for (sound_file *s = sound_table; s->alert != cereal::CarControl::HUDControl::AudibleAlert::NONE; s++) { - slplay_create_player_for_uri(s->uri, &error); - if (error) goto fail; +void Sound::setVolume(int volume, int timeout_seconds) { + if (last_volume_ == volume) return; + + double current_time = nanos_since_boot(); + if ((current_time - last_set_volume_time_) > (timeout_seconds * (1e+9))) { + char volume_change_cmd[64]; + snprintf(volume_change_cmd, sizeof(volume_change_cmd), "service call audio 3 i32 3 i32 %d i32 1 &", volume); + system(volume_change_cmd); + last_volume_ = volume; + last_set_volume_time_ = current_time; } - return; - -fail: - LOGW(error); - exit(1); } -void ui_sound_destroy() { - slplay_destroy(); +Sound::~Sound() { + for (auto &kv : player_) { + (*(kv.second->player))->Destroy(kv.second->player); + delete kv.second; + } + if (outputMix_) (*outputMix_)->Destroy(outputMix_); + if (engine_) (*engine_)->Destroy(engine_); } - diff --git a/selfdrive/ui/sound.hpp b/selfdrive/ui/sound.hpp index ec8934ef38..6439571621 100644 --- a/selfdrive/ui/sound.hpp +++ b/selfdrive/ui/sound.hpp @@ -1,17 +1,33 @@ -#ifndef __SOUND_HPP -#define __SOUND_HPP - +#pragma once +#include #include "cereal/gen/cpp/log.capnp.h" -typedef cereal::CarControl::HUDControl::AudibleAlert AudibleAlert; - -void ui_sound_init(); -void ui_sound_destroy(); +#if defined(QCOM) || defined(QCOM2) +#include +#include +#endif -void set_volume(int volume); +typedef cereal::CarControl::HUDControl::AudibleAlert AudibleAlert; -void play_alert_sound(AudibleAlert alert); -void stop_alert_sound(AudibleAlert alert); +class Sound { + public: + Sound() = default; + bool init(int volume); + bool play(AudibleAlert alert, int repeat = 0); + void stop(); + void setVolume(int volume, int timeout_seconds = 5); + AudibleAlert currentPlaying(); + ~Sound(); + private: +#if defined(QCOM) || defined(QCOM2) + SLObjectItf engine_ = nullptr; + SLObjectItf outputMix_ = nullptr; + int last_volume_ = 0; + double last_set_volume_time_ = 0.; + AudibleAlert currentSound_ = AudibleAlert::NONE; + struct Player; + std::map player_; + friend void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event); #endif - +}; diff --git a/selfdrive/ui/test/build_play_sound.sh b/selfdrive/ui/test/build_play_sound.sh deleted file mode 100755 index 802bdee8fc..0000000000 --- a/selfdrive/ui/test/build_play_sound.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -clang -fPIC -o play_sound play_sound.c ../slplay.c -I ../../ -I ../ -lOpenSLES -Wl,-rpath=/system/lib64 - diff --git a/selfdrive/ui/test/play_sound.c b/selfdrive/ui/test/play_sound.c deleted file mode 100644 index 030a9f25a5..0000000000 --- a/selfdrive/ui/test/play_sound.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include "slplay.h" - -void play_sound(char *uri, int volume) { - char **error = NULL; - printf("call slplay_setup\n"); - slplay_setup(error); - if (error) { printf("%s\n", *error); return; } - - printf("call slplay_create_player_for_uri\n"); - slplay_create_player_for_uri(uri, error); - if (error) { printf("%s\n", *error); return; } - - printf("call slplay_play\n"); - - while (1) { - char volume_change_cmd[64]; - sprintf(volume_change_cmd, "service call audio 3 i32 3 i32 %d i32 1", volume); - system(volume_change_cmd); - - slplay_play(uri, false, error); - if (error) { printf("%s\n", *error); return; } - - sleep(1); - } -} - -int main(int argc, char *argv[]) { - int volume = 10; - if (argc > 2) { - volume = atoi(argv[2]); - } - printf("setting volume to %d\n", volume); - - play_sound(argv[1], volume); - return 0; -} diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 88e3328645..bc827c3c57 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -308,16 +308,12 @@ void handle_message(UIState *s, SubMaster &sm) { if (!scene.frontview){ s->controls_seen = true; } auto alert_sound = scene.controls_state.getAlertSound(); - const auto sound_none = cereal::CarControl::HUDControl::AudibleAlert::NONE; - if (alert_sound != s->alert_sound){ - if (s->alert_sound != sound_none){ - stop_alert_sound(s->alert_sound); - } - if (alert_sound != sound_none){ - play_alert_sound(alert_sound); - s->alert_type = scene.controls_state.getAlertType(); + if (alert_sound != s->sound.currentPlaying()) { + if (alert_sound == AudibleAlert::NONE) { + s->sound.stop(); + } else { + s->sound.play(alert_sound); } - s->alert_sound = alert_sound; } scene.alert_text1 = scene.controls_state.getAlertText1(); scene.alert_text2 = scene.controls_state.getAlertText2(); @@ -411,7 +407,6 @@ void handle_message(UIState *s, SubMaster &sm) { if (!s->started) { if (s->status != STATUS_STOPPED) { update_status(s, STATUS_STOPPED); - s->alert_sound_timeout = 0; s->vision_seen = false; s->controls_seen = false; s->active_app = cereal::UiLayoutState::App::HOME; @@ -754,7 +749,6 @@ int main(int argc, char* argv[]) { TouchState touch = {0}; touch_init(&touch); s->touch_fd = touch.fd; - ui_sound_init(); // light sensor scaling params const bool LEON = util::read_file("/proc/cmdline").find("letv") != std::string::npos; @@ -774,9 +768,8 @@ int main(int argc, char* argv[]) { const int MIN_VOLUME = LEON ? 12 : 9; const int MAX_VOLUME = LEON ? 15 : 12; + assert(s->sound.init(MIN_VOLUME)); - set_volume(MIN_VOLUME); - s->volume_timeout = 5 * UI_FREQ; int draws = 0; s->scene.satelliteCount = -1; @@ -858,13 +851,7 @@ int main(int argc, char* argv[]) { should_swap = true; } - if (s->volume_timeout > 0) { - s->volume_timeout--; - } else { - int volume = fmin(MAX_VOLUME, MIN_VOLUME + s->scene.controls_state.getVEgo() / 5); // up one notch every 5 m/s - set_volume(volume); - s->volume_timeout = 5 * UI_FREQ; - } + s->sound.setVolume(fmin(MAX_VOLUME, MIN_VOLUME + s->scene.controls_state.getVEgo() / 5), 5); // up one notch every 5 m/s // If car is started and controlsState times out, display an alert if (s->controls_timeout > 0) { @@ -877,25 +864,13 @@ int main(int argc, char* argv[]) { s->scene.alert_text1 = "TAKE CONTROL IMMEDIATELY"; s->scene.alert_text2 = "Controls Unresponsive"; - ui_draw_vision_alert(s, s->scene.alert_size, s->status, s->scene.alert_text1.c_str(), s->scene.alert_text2.c_str()); - s->alert_sound_timeout = 2 * UI_FREQ; - s->alert_sound = cereal::CarControl::HUDControl::AudibleAlert::CHIME_WARNING_REPEAT; - play_alert_sound(s->alert_sound); + s->sound.play(AudibleAlert::CHIME_WARNING_REPEAT, 3); // loop sound 3 times } - - s->alert_sound_timeout--; s->controls_seen = false; } - // stop playing alert sound - if ((!s->started || (s->started && s->alert_sound_timeout == 0)) && - s->alert_sound != cereal::CarControl::HUDControl::AudibleAlert::NONE) { - stop_alert_sound(s->alert_sound); - s->alert_sound = cereal::CarControl::HUDControl::AudibleAlert::NONE; - } - read_param_timeout(&s->is_metric, "IsMetric", &s->is_metric_timeout); read_param_timeout(&s->longitudinal_control, "LongitudinalControl", &s->longitudinal_control_timeout); read_param_timeout(&s->limit_set_speed, "LimitSetSpeed", &s->limit_set_speed_timeout); @@ -928,7 +903,6 @@ int main(int argc, char* argv[]) { } set_awake(s, true); - ui_sound_destroy(); // wake up bg thread to exit pthread_mutex_lock(&s->lock); diff --git a/selfdrive/ui/ui.hpp b/selfdrive/ui/ui.hpp index 2b70a9b27c..07f2428ca6 100644 --- a/selfdrive/ui/ui.hpp +++ b/selfdrive/ui/ui.hpp @@ -1,6 +1,4 @@ -#ifndef _UI_H -#define _UI_H - +#pragma once #include "messaging.hpp" #ifdef __APPLE__ @@ -214,9 +212,7 @@ typedef struct UIState { // timeouts int awake_timeout; - int volume_timeout; int controls_timeout; - int alert_sound_timeout; int speed_lim_off_timeout; int is_metric_timeout; int longitudinal_control_timeout; @@ -234,8 +230,6 @@ typedef struct UIState { bool limit_set_speed; float speed_lim_off; bool is_ego_over_limit; - std::string alert_type; - AudibleAlert alert_sound; float alert_blinking_alpha; bool alert_blinked; bool started; @@ -252,6 +246,8 @@ typedef struct UIState { model_path_vertices_data model_path_vertices[MODEL_LANE_PATH_CNT * 2]; track_vertices_data track_vertices[2]; + + Sound sound; } UIState; // API @@ -263,5 +259,3 @@ void ui_draw_image(NVGcontext *vg, float x, float y, float w, float h, int image void ui_draw_rect(NVGcontext *vg, float x, float y, float w, float h, NVGcolor color, float r = 0, int width = 0); void ui_draw_rect(NVGcontext *vg, float x, float y, float w, float h, NVGpaint &paint, float r = 0); void ui_nvg_init(UIState *s); - -#endif