Merge branch 'main' of codeberg.org:cool-tech-zone/tangara-fw

custom
ailurux 2 months ago
commit 29ad80d113
  1. BIN
      lua/img/back.png
  2. BIN
      lua/img/bat/0.png
  3. BIN
      lua/img/bat/100.png
  4. BIN
      lua/img/bat/20.png
  5. BIN
      lua/img/bat/40.png
  6. BIN
      lua/img/bat/60.png
  7. BIN
      lua/img/bat/80.png
  8. BIN
      lua/img/bat/chg.png
  9. BIN
      lua/img/bat/chg_outline.png
  10. BIN
      lua/img/bt.png
  11. BIN
      lua/img/bt_conn.png
  12. BIN
      lua/img/chevron.png
  13. BIN
      lua/img/db.png
  14. BIN
      lua/img/enqueue.png
  15. BIN
      lua/img/file_icons/directory.png
  16. BIN
      lua/img/file_icons/playlist.png
  17. BIN
      lua/img/files.png
  18. BIN
      lua/img/info.png
  19. BIN
      lua/img/listened.png
  20. BIN
      lua/img/menu.png
  21. BIN
      lua/img/next.png
  22. BIN
      lua/img/pause.png
  23. BIN
      lua/img/pausecirc.png
  24. BIN
      lua/img/play.png
  25. BIN
      lua/img/play_small.png
  26. BIN
      lua/img/playcirc.png
  27. BIN
      lua/img/prev.png
  28. BIN
      lua/img/queue.png
  29. BIN
      lua/img/repeat.png
  30. BIN
      lua/img/repeat_off.png
  31. BIN
      lua/img/repeat_queue.png
  32. BIN
      lua/img/settings.png
  33. BIN
      lua/img/shuffle.png
  34. BIN
      lua/img/shuffle_off.png
  35. BIN
      lua/img/shuffleplay.png
  36. BIN
      lua/img/unlistened.png
  37. BIN
      lua/img/usb.png
  38. 36
      src/tangara/app_console/app_console.cpp
  39. 34
      src/tangara/tts/README.md
  40. 2
      src/tangara/tts/player.cpp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 B

After

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 B

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 B

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 B

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 B

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

After

Width:  |  Height:  |  Size: 77 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 B

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

After

Width:  |  Height:  |  Size: 76 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 B

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 B

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 B

After

Width:  |  Height:  |  Size: 113 B

@ -207,8 +207,14 @@ void RegisterDbInit() {
int CmdTasks(int argc, char** argv) { int CmdTasks(int argc, char** argv) {
#if (configUSE_TRACE_FACILITY == 0) #if (configUSE_TRACE_FACILITY == 0)
std::cout << "configUSE_TRACE_FACILITY must be enabled" << std::endl; std::cout
std::cout << "also consider configTASKLIST_USE_COREID" << std::endl; << "FreeRTOS is not configured to track task info." << std::endl
<< "You can enable task tracing via sdkconfig, by setting" << std::endl
<< "CONFIG_FREERTOS_USE_TRACE_FACILITY=y. Alternately, use" << std::endl
<< "idf.py menuconfig to enable Components/FreeRTOS/Kernel" << std::endl
<< "configUSE_TRACE_FACILITY to do the same." << std::endl << std::endl
<< "Also consider 'Enable display of xCoreID in vTaskList'," << std::endl
<< "or CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y" << std::endl;
return 1; return 1;
#endif #endif
@ -218,6 +224,14 @@ int CmdTasks(int argc, char** argv) {
return 1; return 1;
} }
// Sample the task runtime percentage over 2.5 seconds if collecting
// task statistics. Else, we don't need to sample for as long.
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
const int kSamplePeriodMs = 2500;
#else
const int kSamplePeriodMs = 10;
#endif
// Pad the number of tasks so that uxTaskGetSystemState still returns info // Pad the number of tasks so that uxTaskGetSystemState still returns info
// if new tasks are started during measurement. // if new tasks are started during measurement.
size_t num_tasks = uxTaskGetNumberOfTasks() + 4; size_t num_tasks = uxTaskGetNumberOfTasks() + 4;
@ -229,11 +243,23 @@ int CmdTasks(int argc, char** argv) {
size_t start_num_tasks = size_t start_num_tasks =
uxTaskGetSystemState(start_status, num_tasks, &start_elapsed_ticks); uxTaskGetSystemState(start_status, num_tasks, &start_elapsed_ticks);
vTaskDelay(pdMS_TO_TICKS(2500)); vTaskDelay(pdMS_TO_TICKS(kSamplePeriodMs));
size_t end_num_tasks = size_t end_num_tasks =
uxTaskGetSystemState(end_status, num_tasks, &end_elapsed_ticks); uxTaskGetSystemState(end_status, num_tasks, &end_elapsed_ticks);
uint32_t elapsed_ticks = end_elapsed_ticks - start_elapsed_ticks;
if (0 == elapsed_ticks) {
std::cout << "Warning: the scheduler is not recording run-time" << std::endl
<< "statistics, and this means that detailed task" << std::endl
<< "information is not available." << std::endl
<< "Enable CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS" << std::endl
<< "in sdkconfig to capture these stats, or via" << std::endl
<< "idf.py menuconfig, in Components/FreeRTOS/Kernel" << std::endl
<< "configGENERATE_RUN_TIME_STATS." << std::endl;
}
std::vector<std::pair<uint32_t, std::pmr::string>> info_strings; std::vector<std::pair<uint32_t, std::pmr::string>> info_strings;
for (int i = 0; i < start_num_tasks; i++) { for (int i = 0; i < start_num_tasks; i++) {
int k = -1; int k = -1;
@ -279,8 +305,12 @@ int CmdTasks(int argc, char** argv) {
str << "\t\t"; str << "\t\t";
} }
#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
str << std::fixed << std::setprecision(1) << (time_percent * 100); str << std::fixed << std::setprecision(1) << (time_percent * 100);
str << "%"; str << "%";
#else
str << "(unavailable)";
#endif
info_strings.push_back({run_time, std::pmr::string{str.str()}}); info_strings.push_back({run_time, std::pmr::string{str.str()}});
} }

@ -47,3 +47,37 @@ logs a `WARN`ing each time it cannot find a TTS sample. You can enable
these log messages on the console by using the command `loglevel warn`, these log messages on the console by using the command `loglevel warn`,
and then manipulating the click wheel to move through the UI to discover and then manipulating the click wheel to move through the UI to discover
other missing TTS samples. other missing TTS samples.
## Tasks and Event Passing
### In the `ui` task
There are two main threads involved with running TTS - firstly, the `ui`
task, which is rooted in `ui::UiTask::Main()` (`src/tangara/ui/lvgl_task.hpp)`.
By way of the LVGL stack, eventually navigation in the UI results in sending
a `tts::SelectionChanged` message from `input::TextToSpeech::describe()`
(`src/tangara/input/feedback_tts.cpp`) to `tts::Provider::feed()`
(`src/tangara/tts/provider.cpp`), all in the UI task.
The `tts::Provider` is responsible for translating the UI string from a lump
of text to a TTS sample filename, which is then passed along to the player
in `tts::Player::playFile()` (`src/tangara/tts/player.cpp`), still on the UI
thread.
The UI task has a smaller stack than the `worker_X` tasks, and are not
appropriate to use for audio decoding work, both because they would block any
UI updates, and also have insufficient stack space for audio decode activity.
### Transitioning to the `WorkerPool` background threads
`playFile()` uses `tasks::WorkerPool::Dispatch()` to fire off a lambda in a
different task - one of the background `worker_X` tasks, owned by `WorkerPool`.
Control returns to the UI thread in under 2ms, so it remains pretty responsive
throughout this flow.
The background worker uses `tts::Player::openAndDecode` to do the bulk of the
decode/resample/playback work, and it is on this background task that the
majority of the work occurs. Note that there is nothing stopping the TTS worker
from consuming a number of worker tasks at once, but we rely on the interaction
of stream cancellation behaviour between the workers to ensure that previous
samples' playback is promptly terminated after a new sample is requested.

@ -174,7 +174,7 @@ auto Player::decodeToSink(const codecs::ICodec::OutputFormat& format,
// The mixin PcmBuffer should almost always be draining, so we can force // The mixin PcmBuffer should almost always be draining, so we can force
// samples into it more aggressively than with the main music PcmBuffer. // samples into it more aggressively than with the main music PcmBuffer.
while (!stereo_buf.isEmpty()) { while (!stereo_buf.isEmpty() && !stream_cancelled_) {
size_t sent = output_.send(stereo_buf.readAcquire()); size_t sent = output_.send(stereo_buf.readAcquire());
stereo_buf.readCommit(sent); stereo_buf.readCommit(sent);
} }

Loading…
Cancel
Save