28class AudioRecorder final :
public MenuItem, FormattedTitle {
30 AudioRecorder(l10n::String newName, uint8_t sourceId)
31 : MenuItem(newName), FormattedTitle(newName, sourceId + 1), source_id_{sourceId} {}
33 [[nodiscard]] std::string_view
getTitle()
const override {
return FormattedTitle::title(); }
34 [[nodiscard]] std::string_view
getName()
const override {
return FormattedTitle::title(); }
37 soundEditor.shouldGoUpOneLevelOnBegin =
true;
38 soundEditor.setCurrentSource(source_id_);
40 if (parentMenuHeadingTo !=
nullptr && menuItemHeadingTo !=
nullptr) {
41 parentMenuHeadingTo->focusChild(menuItemHeadingTo);
42 soundEditor.navigationDepth = 0;
43 soundEditor.menuItemNavigationRecord[soundEditor.navigationDepth] = parentMenuHeadingTo;
44 soundEditor.shouldGoUpOneLevelOnBegin =
false;
46 parentMenuHeadingTo =
nullptr;
47 menuItemHeadingTo =
nullptr;
50 if (
bool success = openUI(&audioRecorder); !success) {
51 if (getCurrentUI() == &soundEditor) {
52 soundEditor.goUpOneLevel();
54 return uiTimerManager.unsetTimer(TimerName::SHORTCUT_BLINK);
57 audioRecorder.process();
61 const auto sound =
static_cast<Sound*
>(modControllable);
62 return sound->getSynthMode() == SynthMode::SUBTRACTIVE;
67 if (!
isRelevant(modControllable, source_id_)) {
68 display->displayPopup(l10n::get(l10n::String::STRING_FOR_CANT_RECORD_AUDIO_FM_MODE));
69 return MenuPermission::NO;
72 Sound* sound =
static_cast<Sound*
>(modControllable);
73 return soundEditor.checkPermissionToBeginSessionForRangeSpecificParam(sound, source_id_, currentRange);
82 using namespace hid::display;
86 const uint8_t start_x = slot.start_x + 8;
87 const uint8_t start_y = slot.start_y + kHorizontalMenuSlotYOffset + 6;
88 constexpr uint8_t circle_radius = 3;
89 image.drawCircle(start_x + circle_radius + 1, start_y + circle_radius + 1, circle_radius,
true);
90 image.drawString(
"rec", start_x + circle_radius * 2 + 5, start_y, kTextSpacingX, kTextSpacingY);
93 DEF_STACK_STRING_BUF(buf, kShortStringBufferSize);
94 buf.appendInt(source_id_ + 1);
95 uint8_t source_x = slot.start_x + slot.width - kTextBigSpacingX - 7;
96 uint8_t source_y = slot.start_y + kHorizontalMenuSlotYOffset + 4;
98 const bool full_inversion = FlashStorage::accessibilityMenuHighlighting == MenuHighlighting::FULL_INVERSION;
99 if (full_inversion || parent->getCurrentItem() ==
this) {
100 image.drawString(buf.data(), source_x, source_y, kTextBigSpacingX, kTextBigSizeY);
103 image.drawString(buf.data(), source_x - 1, source_y + 2, kTextSpacingX, kTextSpacingY);
107 if (!full_inversion && source_id_ == 0) {
108 const uint8_t y0 = slot.start_y + kHorizontalMenuSlotYOffset + 1;
109 const uint8_t y1 = y0 + 18;
110 for (uint8_t y = y0; y <= y1; y += 2) {
111 image.drawPixel(slot.start_x + slot.width - 1, y);
116 HorizontalMenu* parentMenuHeadingTo{
nullptr};
117 MenuItem* menuItemHeadingTo{
nullptr};