1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
/*
* Copyright 2024 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "input/feedback_tts.hpp"
#include <cstdint>
#include <variant>
#include "lvgl/lvgl.h"
#include "core/lv_group.h"
#include "core/lv_obj.h"
#include "core/lv_obj_class.h"
#include "core/lv_obj_tree.h"
#include "tts/events.hpp"
#include "widgets/button/lv_button.h"
#include "widgets/label/lv_label.h"
#include "widgets/list/lv_list.h"
#include "tts/events.hpp"
#include "tts/provider.hpp"
namespace input {
TextToSpeech::TextToSpeech(tts::Provider& tts)
: tts_(tts), last_obj_(nullptr) {}
auto TextToSpeech::feedback(lv_group_t* group, uint8_t event_type) -> void {
if (group != last_group_) {
last_group_ = group;
last_obj_ = nullptr;
if (group) {
tts_.feed(tts::SimpleEvent::kContextChanged);
}
}
if (group) {
lv_obj_t* focused = lv_group_get_focused(group);
if (focused == last_obj_) {
return;
}
last_obj_ = focused;
if (focused != nullptr) {
describe(*focused);
}
}
}
auto TextToSpeech::describe(lv_obj_t& obj) -> void {
if (lv_obj_check_type(&obj, &lv_button_class) ||
lv_obj_check_type(&obj, &lv_list_button_class)) {
auto desc = findDescription(obj);
tts_.feed(tts::SelectionChanged{
.new_selection =
tts::SelectionChanged::Selection{
.description = desc,
.is_interactive = true,
},
});
} else {
auto desc = findDescription(obj);
tts_.feed(tts::SelectionChanged{
.new_selection =
tts::SelectionChanged::Selection{
.description = desc,
.is_interactive = false,
},
});
}
}
auto TextToSpeech::findDescription(lv_obj_t& obj)
-> std::optional<std::string> {
if (lv_obj_get_child_cnt(&obj) > 0) {
for (size_t i = 0; i < lv_obj_get_child_cnt(&obj); i++) {
auto res = findDescription(*lv_obj_get_child(&obj, i));
if (res) {
return res;
}
}
}
if (lv_obj_check_type(&obj, &lv_label_class)) {
std::string text = lv_label_get_text(&obj);
if (!text.empty()) {
return text;
}
}
return {};
}
} // namespace input
|