From 9bac532ff9f64c01eb39bca7ac0340d1193290b4 Mon Sep 17 00:00:00 2001 From: deanlee Date: Sun, 7 Nov 2021 01:47:37 +0800 Subject: [PATCH] move to ui/soundd --- .gitignore | 1 - release/files_common | 4 +- selfdrive/manager/process_config.py | 2 +- selfdrive/ui/SConscript | 2 +- selfdrive/ui/soundd.cc | 163 ---------------------------- selfdrive/ui/soundd/.gitignore | 1 + selfdrive/ui/soundd/main.cc | 19 ++++ selfdrive/ui/soundd/sound.cc | 110 +++++++++++++++++++ selfdrive/ui/soundd/sound.h | 38 +++++++ selfdrive/ui/{ => soundd}/soundd | 0 10 files changed, 173 insertions(+), 167 deletions(-) delete mode 100644 selfdrive/ui/soundd.cc create mode 100644 selfdrive/ui/soundd/.gitignore create mode 100644 selfdrive/ui/soundd/main.cc create mode 100644 selfdrive/ui/soundd/sound.cc create mode 100644 selfdrive/ui/soundd/sound.h rename selfdrive/ui/{ => soundd}/soundd (100%) diff --git a/.gitignore b/.gitignore index 79587d1d0c..5fc18bb077 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,6 @@ selfdrive/logcatd/logcatd selfdrive/mapd/default_speeds_by_region.json selfdrive/proclogd/proclogd selfdrive/ui/_ui -selfdrive/ui/_soundd selfdrive/test/longitudinal_maneuvers/out selfdrive/visiond/visiond selfdrive/loggerd/loggerd diff --git a/release/files_common b/release/files_common index d83e074ead..85dc7e9285 100644 --- a/release/files_common +++ b/release/files_common @@ -340,7 +340,9 @@ selfdrive/ui/*.h selfdrive/ui/ui selfdrive/ui/text selfdrive/ui/spinner -selfdrive/ui/soundd +selfdrive/ui/soundd/*.cc +selfdrive/ui/soundd/*.h +selfdrive/ui/soundd/soundd selfdrive/ui/qt/*.cc selfdrive/ui/qt/*.h diff --git a/selfdrive/manager/process_config.py b/selfdrive/manager/process_config.py index 8dc010e55a..8fc07a06ef 100644 --- a/selfdrive/manager/process_config.py +++ b/selfdrive/manager/process_config.py @@ -19,7 +19,7 @@ procs = [ NativeProcess("sensord", "selfdrive/sensord", ["./sensord"], enabled=not PC, persistent=EON, sigkill=EON), NativeProcess("ubloxd", "selfdrive/locationd", ["./ubloxd"], enabled=(not PC or WEBCAM)), NativeProcess("ui", "selfdrive/ui", ["./ui"], persistent=True, watchdog_max_dt=(5 if TICI else None)), - NativeProcess("soundd", "selfdrive/ui", ["./soundd"]), + NativeProcess("soundd", "selfdrive/ui/soundd", ["./soundd"]), NativeProcess("locationd", "selfdrive/locationd", ["./locationd"]), NativeProcess("boardd", "selfdrive/boardd", ["./boardd"], enabled=False), PythonProcess("calibrationd", "selfdrive.locationd.calibrationd"), diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 943c072a69..215a78c781 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -44,7 +44,7 @@ qt_env.Depends(assets, Glob('#selfdrive/assets/*', exclude=[assets, assets_src, asset_obj = qt_env.Object("assets", assets) # build soundd -qt_env.Program("_soundd", "soundd.cc", LIBS=qt_libs) +qt_env.Program("soundd/_soundd", ["soundd/main.cc", "soundd/sound.cc"], LIBS=qt_libs) if GetOption('test'): qt_env.Program("tests/playsound", "tests/playsound.cc", LIBS=base_libs) diff --git a/selfdrive/ui/soundd.cc b/selfdrive/ui/soundd.cc deleted file mode 100644 index 83063c1a54..0000000000 --- a/selfdrive/ui/soundd.cc +++ /dev/null @@ -1,163 +0,0 @@ -#include - -#include - -#include -#include -#include -#include - -#include "selfdrive/ui/qt/util.h" -#include "cereal/messaging/messaging.h" -#include "selfdrive/common/util.h" -#include "selfdrive/hardware/hw.h" -#include "selfdrive/ui/ui.h" - -// TODO: detect when we can't play sounds -// TODO: detect when we can't display the UI - -void sigHandler(int s) { - qApp->quit(); -} - -static std::tuple sound_list[] = { - {AudibleAlert::CHIME_DISENGAGE, "disengaged.wav", false}, - {AudibleAlert::CHIME_ENGAGE, "engaged.wav", false}, - {AudibleAlert::CHIME_WARNING1, "warning_1.wav", false}, - {AudibleAlert::CHIME_WARNING2, "warning_2.wav", false}, - {AudibleAlert::CHIME_WARNING2_REPEAT, "warning_2.wav", true}, - {AudibleAlert::CHIME_WARNING_REPEAT, "warning_repeat.wav", true}, - {AudibleAlert::CHIME_ERROR, "error.wav", false}, - {AudibleAlert::CHIME_PROMPT, "error.wav", false}, -}; - -class Sound : public QObject { -public: - explicit Sound(QObject *parent = 0) : sm({"carState", "controlsState"}) { - // TODO: merge again and add EQ in the amp config - const QString sound_asset_path = Hardware::TICI() ? "../assets/sounds_tici/" : "../assets/sounds/"; - for (auto &[alert, fn, loops] : sound_list) { - QSoundEffect *s = new QSoundEffect(this); - QObject::connect(s, &QSoundEffect::statusChanged, [=]() { - assert(s->status() != QSoundEffect::Error); - }); - s->setSource(QUrl::fromLocalFile(sound_asset_path + fn)); - s->setVolume(current_volume); - sounds[alert] = {s, loops ? QSoundEffect::Infinite : 0}; - } - - QTimer *timer = new QTimer(this); - QObject::connect(timer, &QTimer::timeout, this, &Sound::update); - timer->start(1000 / UI_FREQ); - }; - - void update() { - sm.update(0); - if (sm.updated("carState")) { - // scale volume with speed - float volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f, - Hardware::MIN_VOLUME, Hardware::MAX_VOLUME); - if (current_volume != volume) { - current_volume = volume; - for (auto &[s, loops] : sounds) { - s->setVolume(std::round(100 * volume) / 100); - } - } - } - - if (auto alert = Alert::get(sm, 1)) { - setAlert(alert->type, alert->sound); - } else { - setAlert({}, AudibleAlert::NONE); - } - } - - void setAlert(const QString &alert_type, AudibleAlert sound) { - if (alert_type != current_alert_type || current_sound != sound) { - current_alert_type = alert_type; - current_sound = sound; - // stop sounds - for (auto &[s, loops] : sounds) { - // Only stop repeating sounds - if (s->loopsRemaining() == QSoundEffect::Infinite) { - s->stop(); - } - } - - // play sound - if (sound != AudibleAlert::NONE) { - auto &[s, loops] = sounds[sound]; - s->setLoopCount(loops); - s->play(); - } - } - } - - AudibleAlert current_sound = AudibleAlert::NONE; - QString current_alert_type; - float current_volume = Hardware::MIN_VOLUME; - - QMap> sounds; - SubMaster sm; -}; - -const int test_loop_cnt = 2; - -void test_sound() { - PubMaster pm({"controlsState"}); - const int DT_CTRL = 10; // ms - for (int i = 0; i < test_loop_cnt; ++i) { - for (auto &[alert, fn, loops] : sound_list) { - printf("testing %s\n", qPrintable(fn)); - for (int j = 0; j < 1000 / DT_CTRL; ++j) { - MessageBuilder msg; - auto cs = msg.initEvent().initControlsState(); - cs.setAlertSound(alert); - cs.setAlertType(fn.toStdString()); - pm.send("controlsState", msg); - QThread::msleep(DT_CTRL); - } - } - } - QThread::currentThread()->quit(); -} - -void run_test(Sound *sound) { - static QMap> stats; - for (auto i = sound->sounds.constBegin(); i != sound->sounds.constEnd(); ++i) { - QObject::connect(i.value().first, &QSoundEffect::playingChanged, [s = i.value().first, a = i.key()]() { - if (s->isPlaying()) { - bool repeat = a == AudibleAlert::CHIME_WARNING_REPEAT || a == AudibleAlert::CHIME_WARNING2_REPEAT; - assert(s->loopsRemaining() == repeat ? QSoundEffect::Infinite : 1); - stats[a].first++; - } else { - stats[a].second++; - } - }); - } - - QThread *t = new QThread(qApp); - QObject::connect(t, &QThread::started, [=]() { test_sound(); }); - QObject::connect(t, &QThread::finished, [&]() { - for (auto [play, stop] : stats) { - assert(play == test_loop_cnt && stop == test_loop_cnt); - } - qApp->quit(); - }); - t->start(); -} - -int main(int argc, char **argv) { - qInstallMessageHandler(swagLogMessageHandler); - setpriority(PRIO_PROCESS, 0, -20); - - QApplication a(argc, argv); - std::signal(SIGINT, sigHandler); - std::signal(SIGTERM, sigHandler); - - Sound sound; - if (argc > 1 && strcmp(argv[1], "--test") == 0) { - run_test(&sound); - } - return a.exec(); -} diff --git a/selfdrive/ui/soundd/.gitignore b/selfdrive/ui/soundd/.gitignore new file mode 100644 index 0000000000..5fb1a93459 --- /dev/null +++ b/selfdrive/ui/soundd/.gitignore @@ -0,0 +1 @@ +_soundd \ No newline at end of file diff --git a/selfdrive/ui/soundd/main.cc b/selfdrive/ui/soundd/main.cc new file mode 100644 index 0000000000..209cb4b7ce --- /dev/null +++ b/selfdrive/ui/soundd/main.cc @@ -0,0 +1,19 @@ +#include "selfdrive/ui/soundd/sound.h" + +#include "selfdrive/ui/qt/util.h" + +void sigHandler(int s) { + qApp->quit(); +} + +int main(int argc, char **argv) { + qInstallMessageHandler(swagLogMessageHandler); + setpriority(PRIO_PROCESS, 0, -20); + + QApplication a(argc, argv); + std::signal(SIGINT, sigHandler); + std::signal(SIGTERM, sigHandler); + + Sound sound; + return a.exec(); +} diff --git a/selfdrive/ui/soundd/sound.cc b/selfdrive/ui/soundd/sound.cc new file mode 100644 index 0000000000..a95b9c4658 --- /dev/null +++ b/selfdrive/ui/soundd/sound.cc @@ -0,0 +1,110 @@ +#include "selfdrive/ui/soundd/sound.h" + +// TODO: detect when we can't play sounds +// TODO: detect when we can't display the UI + +Sound::Sound(QObject *parent) : sm({"carState", "controlsState"}) { + // TODO: merge again and add EQ in the amp config + const QString sound_asset_path = Hardware::TICI() ? "../../assets/sounds_tici/" : "../../assets/sounds/"; + for (auto &[alert, fn, loops] : sound_list) { + QSoundEffect *s = new QSoundEffect(this); + QObject::connect(s, &QSoundEffect::statusChanged, [=]() { + assert(s->status() != QSoundEffect::Error); + }); + s->setSource(QUrl::fromLocalFile(sound_asset_path + fn)); + s->setVolume(current_volume); + sounds[alert] = {s, loops ? QSoundEffect::Infinite : 0}; + } + + QTimer *timer = new QTimer(this); + QObject::connect(timer, &QTimer::timeout, this, &Sound::update); + timer->start(1000 / UI_FREQ); +}; + +void Sound::update() { + sm.update(0); + if (sm.updated("carState")) { + // scale volume with speed + float volume = util::map_val(sm["carState"].getCarState().getVEgo(), 0.f, 20.f, + Hardware::MIN_VOLUME, Hardware::MAX_VOLUME); + if (current_volume != volume) { + current_volume = volume; + for (auto &[s, loops] : sounds) { + s->setVolume(std::round(100 * volume) / 100); + } + } + } + + if (auto alert = Alert::get(sm, 1)) { + setAlert(alert->type, alert->sound); + } else { + setAlert({}, AudibleAlert::NONE); + } +} + +void Sound::setAlert(const QString &alert_type, AudibleAlert sound) { + if (alert_type != current_alert_type || current_sound != sound) { + current_alert_type = alert_type; + current_sound = sound; + // stop sounds + for (auto &[s, loops] : sounds) { + // Only stop repeating sounds + if (s->loopsRemaining() == QSoundEffect::Infinite) { + s->stop(); + } + } + + // play sound + if (sound != AudibleAlert::NONE) { + auto &[s, loops] = sounds[sound]; + s->setLoopCount(loops); + s->play(); + } + } +} + +// const int test_loop_cnt = 2; + +// void test_sound() { +// PubMaster pm({"controlsState"}); +// const int DT_CTRL = 10; // ms +// for (int i = 0; i < test_loop_cnt; ++i) { +// for (auto &[alert, fn, loops] : sound_list) { +// printf("testing %s\n", qPrintable(fn)); +// for (int j = 0; j < 1000 / DT_CTRL; ++j) { +// MessageBuilder msg; +// auto cs = msg.initEvent().initControlsState(); +// cs.setAlertSound(alert); +// cs.setAlertType(fn.toStdString()); +// pm.send("controlsState", msg); +// QThread::msleep(DT_CTRL); +// } +// } +// } +// QThread::currentThread()->quit(); +// } + +// void run_test(Sound *sound) { +// static QMap> stats; +// for (auto i = sound->sounds.constBegin(); i != sound->sounds.constEnd(); ++i) { +// QObject::connect(i.value().first, &QSoundEffect::playingChanged, [s = i.value().first, a = i.key()]() { +// if (s->isPlaying()) { +// bool repeat = a == AudibleAlert::CHIME_WARNING_REPEAT || a == AudibleAlert::CHIME_WARNING2_REPEAT; +// assert(s->loopsRemaining() == repeat ? QSoundEffect::Infinite : 1); +// stats[a].first++; +// } else { +// stats[a].second++; +// } +// }); +// } + +// QThread *t = new QThread(qApp); +// QObject::connect(t, &QThread::started, [=]() { test_sound(); }); +// QObject::connect(t, &QThread::finished, [&]() { +// for (auto [play, stop] : stats) { +// assert(play == test_loop_cnt && stop == test_loop_cnt); +// } +// qApp->quit(); +// }); +// t->start(); +// } diff --git a/selfdrive/ui/soundd/sound.h b/selfdrive/ui/soundd/sound.h new file mode 100644 index 0000000000..41f882c38c --- /dev/null +++ b/selfdrive/ui/soundd/sound.h @@ -0,0 +1,38 @@ +#include + +#include +#include +#include +#include +#include + +#include "cereal/messaging/messaging.h" +#include "selfdrive/common/util.h" +#include "selfdrive/hardware/hw.h" +#include "selfdrive/ui/ui.h" + +const std::tuple sound_list[] = { + {AudibleAlert::CHIME_DISENGAGE, "disengaged.wav", false}, + {AudibleAlert::CHIME_ENGAGE, "engaged.wav", false}, + {AudibleAlert::CHIME_WARNING1, "warning_1.wav", false}, + {AudibleAlert::CHIME_WARNING2, "warning_2.wav", false}, + {AudibleAlert::CHIME_WARNING2_REPEAT, "warning_2.wav", true}, + {AudibleAlert::CHIME_WARNING_REPEAT, "warning_repeat.wav", true}, + {AudibleAlert::CHIME_ERROR, "error.wav", false}, + {AudibleAlert::CHIME_PROMPT, "error.wav", false}, +}; + +class Sound : public QObject { +public: + explicit Sound(QObject *parent = 0); + void update(); + void setAlert(const QString &alert_type, AudibleAlert sound); + + protected: + AudibleAlert current_sound = AudibleAlert::NONE; + QString current_alert_type; + float current_volume = Hardware::MIN_VOLUME; + + QMap> sounds; + SubMaster sm; +}; diff --git a/selfdrive/ui/soundd b/selfdrive/ui/soundd/soundd similarity index 100% rename from selfdrive/ui/soundd rename to selfdrive/ui/soundd/soundd