summaryrefslogtreecommitdiff
path: root/src/tangara/input/feedback_tts.cpp
blob: 04c2830d16e01d70cfa36d371d53b8e4198dba6f (plain)
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
98
99
100
101
102
103
/*
 * 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"
#include "feedback_tts.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::feedback(lv_group_t*, InputEvent event) -> void {
  return;
}

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