Sound refactor (#1589)

* Soud refactor

* remove files from  files_common

* add timeout to set_volumn

* add param volume to init

* done

* test.cc

* fix typo

* add repeat param instead of loop

* revert submodule

* add member function currentSound

* remove function create_player from class member

* fix build error

fix repeat

* rename CHECK_RESULT to ReturnOnError

* set currentSound_ before posible err

* use std::map to initialize sound table

cleanup

cleanup

cleanup

fix bug in stop

change paramater name

* done

* remove function CreatePlayer, create player in init()

* resolve conflict

* remove sound test

* rebase

* remove whitespace

* Apply great review suggestion

* use player's SLVolumeItf interface to set volume

* use float

* leave the volume control the way it is
pull/1711/head
Dean Lee 2020-06-16 06:26:38 +08:00 committed by GitHub
parent 10cb6ab87a
commit 8cacc14b31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 159 additions and 377 deletions

View File

@ -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

View File

@ -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:

View File

@ -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 <sys/mman.h>

View File

@ -1,184 +0,0 @@
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#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";
}
}

View File

@ -1,21 +0,0 @@
#ifndef SLPLAY_H
#define SLPLAY_H
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <stdbool.h>
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

View File

@ -1,91 +1,137 @@
#include <stdlib.h>
#include "sound.hpp"
#include <math.h>
#include <stdlib.h>
#include <atomic>
#include "common/swaglog.h"
#include "common/timing.h"
typedef struct {
AudibleAlert alert;
const char* uri;
bool loop;
} sound_file;
#define LogOnError(func, msg) \
if ((func) != SL_RESULT_SUCCESS) { LOGW(msg); }
extern "C"{
#include "slplay.h"
}
#define ReturnOnError(func, msg) \
if ((func) != SL_RESULT_SUCCESS) { LOGW(msg); return false; }
int last_volume = 0;
static std::map<AudibleAlert, const char *> 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"}};
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;
}
}
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 },
struct Sound::Player {
SLObjectItf player;
SLPlayItf playItf;
// slplay_callback runs on a background thread,use atomic to ensure thread safe.
std::atomic<int> repeat;
};
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;
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};
}
setVolume(volume);
return true;
}
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 NULL;
return currentSound_;
}
void play_alert_sound(AudibleAlert alert) {
sound_file* sound = get_sound_file(alert);
char* error = NULL;
slplay_play(sound->uri, sound->loop, &error);
if(error) {
LOGW("error playing sound: %s", error);
void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event) {
Sound::Player *s = reinterpret_cast<Sound::Player *>(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);
}
}
void stop_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_stop_uri(sound->uri, &error);
if(error) {
LOGW("error stopping 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 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_);
}

View File

@ -1,17 +1,33 @@
#ifndef __SOUND_HPP
#define __SOUND_HPP
#pragma once
#include <map>
#include "cereal/gen/cpp/log.capnp.h"
#if defined(QCOM) || defined(QCOM2)
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#endif
typedef cereal::CarControl::HUDControl::AudibleAlert AudibleAlert;
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);
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<AudibleAlert, Player *> player_;
friend void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event);
#endif
};

View File

@ -1,3 +0,0 @@
#!/bin/sh
clang -fPIC -o play_sound play_sound.c ../slplay.c -I ../../ -I ../ -lOpenSLES -Wl,-rpath=/system/lib64

View File

@ -1,37 +0,0 @@
#include <stdio.h>
#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;
}

View File

@ -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 != s->sound.currentPlaying()) {
if (alert_sound == AudibleAlert::NONE) {
s->sound.stop();
} else {
s->sound.play(alert_sound);
}
if (alert_sound != sound_none){
play_alert_sound(alert_sound);
s->alert_type = scene.controls_state.getAlertType();
}
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);

View File

@ -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