Add preset polish and broadcast metadata (fw 0.8.0).

Ship station reorder, DAB playing ids in presets, RDS PS/RT and DAB DLS in tuner status, Si4684 data-service read, host tests, and UI now-playing lines.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 00:01:49 +02:00
co-authored by Cursor
parent 9f76ab9e74
commit 0fc714e431
34 changed files with 1379 additions and 65 deletions
@@ -102,6 +102,21 @@ public:
[[nodiscard]] std::expected<void, core::StationListError> removeAt(
std::size_t index);
/**
* @brief reorder — move a preset within the list and persist.
*
* @dname reorder
* @param fromIndex Current list position.
* @param toIndex Target list position.
* @return Ok on success, or StationListError.
* @pubstate mutates list_ and NVS on success.
*
* @author Michele Bigi
* @date 2026-07-06
*/
[[nodiscard]] std::expected<void, core::StationListError> reorder(
std::size_t fromIndex, std::size_t toIndex);
/**
* @brief tuneToIndex — recall a saved preset on the tuner.
*
@@ -62,8 +62,8 @@ std::expected<void, core::StationListError> StationService::add(
return added;
}
if (auto saved = persist(); !saved) {
list_.removeAt(list_.stations().size() - 1U);
return std::unexpected(core::StationListError::Full);
(void)list_.removeAt(list_.stations().size() - 1U);
return std::unexpected(core::StationListError::PersistFailed);
}
return {};
}
@@ -75,6 +75,22 @@ std::expected<void, core::StationListError> StationService::removeAt(
return removed;
}
if (auto saved = persist(); !saved) {
return std::unexpected(core::StationListError::PersistFailed);
}
return {};
}
std::expected<void, core::StationListError> StationService::reorder(
std::size_t fromIndex,
std::size_t toIndex)
{
if (auto moved = list_.move(fromIndex, toIndex); !moved) {
return moved;
}
if (auto saved = persist(); !saved) {
if (list_.move(toIndex, fromIndex)) {
return std::unexpected(core::StationListError::PersistFailed);
}
return std::unexpected(core::StationListError::NotFound);
}
return {};
@@ -20,6 +20,7 @@
#include <cstdint>
#include <expected>
#include <optional>
#include <vector>
namespace tuner {
@@ -72,7 +73,7 @@ public:
* @dname tuneDab
* @param freqIndex Ensemble index 037.
* @return Ok on success, or a TunerError from ITuner.
* @pubstate writes lastDabIndex_ on success.
* @pubstate writes lastDabIndex_ on success; clears last-played DAB ids.
*
* @author Michele Bigi
* @date 2026-07-06
@@ -129,7 +130,7 @@ public:
* @param serviceId Selected service identifier.
* @param componentId Audio component within the service.
* @return Ok on success, or a TunerError from ITuner.
* @pubstate delegates to tuner_.
* @pubstate delegates to tuner_; caches service/component for status JSON.
*
* @author Michele Bigi
* @date 2026-07-06
@@ -168,6 +169,8 @@ private:
std::uint8_t lastDabIndex_;
core::FrequencyKHz lastFmFrequency_;
std::uint8_t volume_;
std::optional<std::uint32_t> lastPlayedServiceId_;
std::optional<std::uint32_t> lastPlayedComponentId_;
};
} // namespace tuner
@@ -37,6 +37,10 @@ std::expected<core::TunerStatus, core::TunerError> TunerService::refreshStatus()
auto status = tuner_.readStatus();
if (status) {
volume_ = status->volume;
if (status->band == core::TunerBand::Dab) {
status->dabPlayingServiceId = lastPlayedServiceId_;
status->dabPlayingComponentId = lastPlayedComponentId_;
}
}
return status;
}
@@ -48,6 +52,8 @@ std::expected<void, core::TunerError> TunerService::tuneDab(
return result;
}
lastDabIndex_ = freqIndex;
lastPlayedServiceId_.reset();
lastPlayedComponentId_.reset();
return {};
}
@@ -81,7 +87,12 @@ std::expected<void, core::TunerError> TunerService::playDabService(
std::uint32_t serviceId,
std::uint32_t componentId)
{
return tuner_.playDabService(serviceId, componentId);
if (auto result = tuner_.playDabService(serviceId, componentId); !result) {
return result;
}
lastPlayedServiceId_ = serviceId;
lastPlayedComponentId_ = componentId;
return {};
}
std::expected<void, core::TunerError> TunerService::setVolume(std::uint8_t level)