music_section_auth.h 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #pragma once
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <span>
  5. #include "../../encoding/bit_writer.h"
  6. #include "auth_fields.h"
  7. // Type-11 music sensor. The body opens with a 128-bit section selection mask, then one optional
  8. // condition ClientRef per section plus a final one that gates the whole sensor. One set bit lets
  9. // the native bank play that section's transition.
  10. namespace sunrise::middleware::bap::activity_message::music_section {
  11. namespace fields = auth_fields;
  12. inline constexpr std::uint8_t kSlotType = 11;
  13. inline constexpr std::uint32_t kComponentClass = 0x80804E8EU;
  14. inline constexpr std::uint32_t kSchema = 0x80804F58U;
  15. /** The mask spans four 32-bit lanes, one bit per section. */
  16. inline constexpr std::size_t kSectionCount = 128;
  17. inline constexpr std::size_t kMaskLaneCount = 4;
  18. inline constexpr std::uint8_t kMaskLaneWidth = 32;
  19. /** One condition ClientRef per section, then the sensor gate. All are left unset. */
  20. inline constexpr std::size_t kConditionRefCount = kSectionCount + 1;
  21. inline constexpr std::size_t kBits =
  22. kMaskLaneCount * kMaskLaneWidth + kConditionRefCount * fields::kClientRefBits;
  23. inline constexpr std::size_t kBytes = (kBits + 7) / 8;
  24. /**
  25. * Encodes the sensor body with at most one section selected.
  26. * @param section Section index below kSectionCount.
  27. * @param enabled False clears the mask.
  28. * @param written Receives kBytes.
  29. */
  30. [[nodiscard]] inline bool encode(std::uint8_t section,
  31. bool enabled,
  32. std::span<std::byte> output,
  33. std::size_t& written) noexcept {
  34. written = 0;
  35. if (section >= kSectionCount || output.size() < kBytes) {
  36. return false;
  37. }
  38. encoding::bits::Writer writer(output.first(kBytes));
  39. for (std::size_t lane = 0; lane < kMaskLaneCount; ++lane) {
  40. const bool selected = enabled && section / kMaskLaneWidth == lane;
  41. const std::uint32_t mask = selected ? std::uint32_t{1} << (section % kMaskLaneWidth) : 0U;
  42. if (!writer.write(mask, kMaskLaneWidth)) {
  43. return false;
  44. }
  45. }
  46. for (std::size_t index = 0; index < kConditionRefCount; ++index) {
  47. if (!fields::write_absent_client_ref(writer)) {
  48. return false;
  49. }
  50. }
  51. return fields::finish_exact(writer, kBits, kBytes, written);
  52. }
  53. } // namespace sunrise::middleware::bap::activity_message::music_section