From ffb098907770912dc3edb5ddb1b1196eefe32ef5 Mon Sep 17 00:00:00 2001 From: James Mulcahy Date: Wed, 7 Oct 2026 22:49:35 -0700 Subject: [PATCH 1/3] Add media player sources to the NSPanel protobufs Home Assistant media players have a list of sources (inputs) and can select one. A media player with a source volume strategy also has a source player feeding it, which has its own sources, for example the Sonos Favorites of the speaker an audio matrix zone is playing from. NSPanelEntityState.MediaPlayer gets both lists as a SourceSelection (sources, current source and whether one can be selected). source_player_sources is unset when there is no source player. MediaPlayerCommand selects a source from either list by name. The lists change when the player switches source, so an index from an older state could select the wrong one. An empty name means no change, as no source is called "". The firmware C files were also missing volume_step from #385 and pick it up here. Co-Authored-By: Claude Opus 5.5 --- .../include/protobuf/protobuf_nspanel.pb.cc | 144 +- .../include/protobuf/protobuf_nspanel.pb.h | 140 +- .../protobuf/protobuf_nspanel_entity.pb.cc | 559 ++++++- .../protobuf/protobuf_nspanel_entity.pb.h | 1290 ++++++++++++----- docker/protobuf/protobuf_nspanel.proto | 3 + docker/protobuf/protobuf_nspanel_entity.proto | 15 + protobuf_firmware/protobuf_nspanel.pb-c.c | 32 +- protobuf_firmware/protobuf_nspanel.pb-c.h | 7 +- .../protobuf_nspanel_entity.pb-c.c | 115 +- .../protobuf_nspanel_entity.pb-c.h | 41 +- 10 files changed, 1901 insertions(+), 445 deletions(-) diff --git a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc index 7ffd0ad4..059123fe 100644 --- a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc +++ b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.cc @@ -233,7 +233,13 @@ PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT inline constexpr NSPanelMQTTManagerCommand_MediaPlayerCommand::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : media_player_id_{0}, + : select_player_source_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + select_source_player_source_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + media_player_id_{0}, playback_action_{static_cast< ::NSPanelMQTTManagerCommand_MediaPlayerCommand_PlaybackAction >(0)}, volume_{0}, has_volume_{false}, @@ -841,6 +847,8 @@ const ::uint32_t PROTOBUF_FIELD_OFFSET(::NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.source_volume_), PROTOBUF_FIELD_OFFSET(::NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.has_muted_), PROTOBUF_FIELD_OFFSET(::NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.muted_), + PROTOBUF_FIELD_OFFSET(::NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.select_player_source_), + PROTOBUF_FIELD_OFFSET(::NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.select_source_player_source_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::NSPanelMQTTManagerCommand, _internal_metadata_), ~0u, // no _extensions_ @@ -882,7 +890,7 @@ static const ::_pbi::MigrationSchema {238, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ThermostatTemperatureCommand)}, {248, -1, -1, sizeof(::NSPanelMQTTManagerCommand_ThermostatCommand)}, {259, -1, -1, sizeof(::NSPanelMQTTManagerCommand_MediaPlayerCommand)}, - {275, -1, -1, sizeof(::NSPanelMQTTManagerCommand)}, + {277, -1, -1, sizeof(::NSPanelMQTTManagerCommand)}, }; static const ::_pb::Message* const file_default_instances[] = { &::_NSPanelConfig_RoomInfo_default_instance_._instance, @@ -998,7 +1006,7 @@ const char descriptor_table_protodef_protobuf_5fnspanel_2eproto[] ABSL_ATTRIBUTE "ing\030\010 \001(\t\032\222\001\n\014ForecastItem\022\024\n\014weather_ic" "on\030\001 \001(\t\022\034\n\024precipitation_string\030\002 \001(\t\022!" "\n\031temperature_maxmin_string\030\003 \001(\t\022\023\n\013win" - "d_string\030\004 \001(\t\022\026\n\016display_string\030\005 \001(\t\"\272" + "d_string\030\004 \001(\t\022\026\n\016display_string\030\005 \001(\t\"\375" "\020\n\031NSPanelMQTTManagerCommand\022M\n\022first_pa" "ge_turn_on\030\001 \001(\0132/.NSPanelMQTTManagerCom" "mand.FirstPageTurnLightOnH\000\022O\n\023first_pag" @@ -1041,26 +1049,27 @@ const char descriptor_table_protodef_protobuf_5fnspanel_2eproto[] ABSL_ATTRIBUTE "\025\n\rthermostat_id\030\001 \001(\005\022\023\n\013temperature\030\002 " "\001(\002\032M\n\021ThermostatCommand\022\025\n\rthermostat_i" "d\030\001 \001(\005\022\016\n\006option\030\002 \001(\t\022\021\n\tnew_value\030\003 \001" - "(\t\032\321\002\n\022MediaPlayerCommand\022\027\n\017media_playe" + "(\t\032\224\003\n\022MediaPlayerCommand\022\027\n\017media_playe" "r_id\030\001 \001(\005\022U\n\017playback_action\030\002 \001(\0162<.NS" "PanelMQTTManagerCommand.MediaPlayerComma" "nd.PlaybackAction\022\022\n\nhas_volume\030\003 \001(\010\022\016\n" "\006volume\030\004 \001(\005\022\031\n\021has_source_volume\030\005 \001(\010" "\022\025\n\rsource_volume\030\006 \001(\005\022\021\n\thas_muted\030\007 \001" - "(\010\022\r\n\005muted\030\010 \001(\010\"S\n\016PlaybackAction\022\010\n\004N" - "ONE\020\000\022\010\n\004PLAY\020\001\022\t\n\005PAUSE\020\002\022\016\n\nNEXT_TRACK" - "\020\003\022\022\n\016PREVIOUS_TRACK\020\004\"D\n\023AffectLightsOp" - "tions\022\007\n\003ALL\020\000\022\020\n\014TABLE_LIGHTS\020\001\022\022\n\016CEIL" - "ING_LIGHTS\020\002B\r\n\013CommandData*[\n\023NSPanelWa" - "rningLevel\022\014\n\010CRITICAL\020\000\022\t\n\005ERROR\020\001\022\013\n\007W" - "ARNING\020\002\022\010\n\004INFO\020\003\022\t\n\005DEBUG\020\004\022\t\n\005TRACE\020\005" - "b\006proto3" + "(\010\022\r\n\005muted\030\010 \001(\010\022\034\n\024select_player_sourc" + "e\030\t \001(\t\022#\n\033select_source_player_source\030\n" + " \001(\t\"S\n\016PlaybackAction\022\010\n\004NONE\020\000\022\010\n\004PLAY" + "\020\001\022\t\n\005PAUSE\020\002\022\016\n\nNEXT_TRACK\020\003\022\022\n\016PREVIOU" + "S_TRACK\020\004\"D\n\023AffectLightsOptions\022\007\n\003ALL\020" + "\000\022\020\n\014TABLE_LIGHTS\020\001\022\022\n\016CEILING_LIGHTS\020\002B" + "\r\n\013CommandData*[\n\023NSPanelWarningLevel\022\014\n" + "\010CRITICAL\020\000\022\t\n\005ERROR\020\001\022\013\n\007WARNING\020\002\022\010\n\004I" + "NFO\020\003\022\t\n\005DEBUG\020\004\022\t\n\005TRACE\020\005b\006proto3" }; static ::absl::once_flag descriptor_table_protobuf_5fnspanel_2eproto_once; PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_protobuf_5fnspanel_2eproto = { false, false, - 5888, + 5955, descriptor_table_protodef_protobuf_5fnspanel_2eproto, "protobuf_nspanel.proto", &descriptor_table_protobuf_5fnspanel_2eproto_once, @@ -7213,15 +7222,38 @@ NSPanelMQTTManagerCommand_MediaPlayerCommand::NSPanelMQTTManagerCommand_MediaPla SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:NSPanelMQTTManagerCommand.MediaPlayerCommand) } +inline PROTOBUF_NDEBUG_INLINE NSPanelMQTTManagerCommand_MediaPlayerCommand::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from, const ::NSPanelMQTTManagerCommand_MediaPlayerCommand& from_msg) + : select_player_source_(arena, from.select_player_source_), + select_source_player_source_(arena, from.select_source_player_source_), + _cached_size_{0} {} + NSPanelMQTTManagerCommand_MediaPlayerCommand::NSPanelMQTTManagerCommand_MediaPlayerCommand( - ::google::protobuf::Arena* arena, const NSPanelMQTTManagerCommand_MediaPlayerCommand& from) - : NSPanelMQTTManagerCommand_MediaPlayerCommand(arena) { - MergeFrom(from); + ::google::protobuf::Arena* arena, + const NSPanelMQTTManagerCommand_MediaPlayerCommand& from) + : ::google::protobuf::Message(arena) { + NSPanelMQTTManagerCommand_MediaPlayerCommand* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, media_player_id_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, media_player_id_), + offsetof(Impl_, source_volume_) - + offsetof(Impl_, media_player_id_) + + sizeof(Impl_::source_volume_)); + + // @@protoc_insertion_point(copy_constructor:NSPanelMQTTManagerCommand.MediaPlayerCommand) } inline PROTOBUF_NDEBUG_INLINE NSPanelMQTTManagerCommand_MediaPlayerCommand::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : _cached_size_{0} {} + : select_player_source_(arena), + select_source_player_source_(arena), + _cached_size_{0} {} inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); @@ -7239,6 +7271,8 @@ NSPanelMQTTManagerCommand_MediaPlayerCommand::~NSPanelMQTTManagerCommand_MediaPl } inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::SharedDtor() { ABSL_DCHECK(GetArena() == nullptr); + _impl_.select_player_source_.Destroy(); + _impl_.select_source_player_source_.Destroy(); _impl_.~Impl_(); } @@ -7263,15 +7297,15 @@ NSPanelMQTTManagerCommand_MediaPlayerCommand::GetClassData() const { return _data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<3, 8, 0, 0, 2> NSPanelMQTTManagerCommand_MediaPlayerCommand::_table_ = { +const ::_pbi::TcParseTable<4, 10, 0, 108, 2> NSPanelMQTTManagerCommand_MediaPlayerCommand::_table_ = { { 0, // no _has_bits_ 0, // no _extensions_ - 8, 56, // max_field_number, fast_idx_mask + 10, 120, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294967040, // skipmap + 4294966272, // skipmap offsetof(decltype(_table_), field_entries), - 8, // num_field_entries + 10, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries &_NSPanelMQTTManagerCommand_MediaPlayerCommand_default_instance_._instance, @@ -7281,9 +7315,7 @@ const ::_pbi::TcParseTable<3, 8, 0, 0, 2> NSPanelMQTTManagerCommand_MediaPlayerC ::_pbi::TcParser::GetTable<::NSPanelMQTTManagerCommand_MediaPlayerCommand>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE }, {{ - // bool muted = 8; - {::_pbi::TcParser::SingularVarintNoZag1(), - {64, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.muted_)}}, + {::_pbi::TcParser::MiniParse, {}}, // int32 media_player_id = 1; {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.media_player_id_), 63>(), {8, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.media_player_id_)}}, @@ -7305,6 +7337,20 @@ const ::_pbi::TcParseTable<3, 8, 0, 0, 2> NSPanelMQTTManagerCommand_MediaPlayerC // bool has_muted = 7; {::_pbi::TcParser::SingularVarintNoZag1(), {56, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.has_muted_)}}, + // bool muted = 8; + {::_pbi::TcParser::SingularVarintNoZag1(), + {64, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.muted_)}}, + // string select_player_source = 9; + {::_pbi::TcParser::FastUS1, + {74, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.select_player_source_)}}, + // string select_source_player_source = 10; + {::_pbi::TcParser::FastUS1, + {82, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.select_source_player_source_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, }}, {{ 65535, 65535 }}, {{ @@ -7332,9 +7378,19 @@ const ::_pbi::TcParseTable<3, 8, 0, 0, 2> NSPanelMQTTManagerCommand_MediaPlayerC // bool muted = 8; {PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.muted_), 0, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, + // string select_player_source = 9; + {PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.select_player_source_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string select_source_player_source = 10; + {PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.select_source_player_source_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, // no aux_entries {{ + "\54\0\0\0\0\0\0\0\0\24\33\0\0\0\0\0" + "NSPanelMQTTManagerCommand.MediaPlayerCommand" + "select_player_source" + "select_source_player_source" }}, }; @@ -7345,6 +7401,8 @@ PROTOBUF_NOINLINE void NSPanelMQTTManagerCommand_MediaPlayerCommand::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; + _impl_.select_player_source_.ClearToEmpty(); + _impl_.select_source_player_source_.ClearToEmpty(); ::memset(&_impl_.media_player_id_, 0, static_cast<::size_t>( reinterpret_cast(&_impl_.source_volume_) - reinterpret_cast(&_impl_.media_player_id_)) + sizeof(_impl_.source_volume_)); @@ -7414,6 +7472,22 @@ ::uint8_t* NSPanelMQTTManagerCommand_MediaPlayerCommand::_InternalSerialize( 8, this->_internal_muted(), target); } + // string select_player_source = 9; + if (!this->_internal_select_player_source().empty()) { + const std::string& _s = this->_internal_select_player_source(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "NSPanelMQTTManagerCommand.MediaPlayerCommand.select_player_source"); + target = stream->WriteStringMaybeAliased(9, _s, target); + } + + // string select_source_player_source = 10; + if (!this->_internal_select_source_player_source().empty()) { + const std::string& _s = this->_internal_select_source_player_source(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "NSPanelMQTTManagerCommand.MediaPlayerCommand.select_source_player_source"); + target = stream->WriteStringMaybeAliased(10, _s, target); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( @@ -7432,6 +7506,18 @@ ::size_t NSPanelMQTTManagerCommand_MediaPlayerCommand::ByteSizeLong() const { (void) cached_has_bits; ::_pbi::Prefetch5LinesFrom7Lines(reinterpret_cast(this)); + // string select_player_source = 9; + if (!this->_internal_select_player_source().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_select_player_source()); + } + + // string select_source_player_source = 10; + if (!this->_internal_select_source_player_source().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_select_source_player_source()); + } + // int32 media_player_id = 1; if (this->_internal_media_player_id() != 0) { total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( @@ -7488,6 +7574,12 @@ void NSPanelMQTTManagerCommand_MediaPlayerCommand::MergeImpl(::google::protobuf: ::uint32_t cached_has_bits = 0; (void) cached_has_bits; + if (!from._internal_select_player_source().empty()) { + _this->_internal_set_select_player_source(from._internal_select_player_source()); + } + if (!from._internal_select_source_player_source().empty()) { + _this->_internal_set_select_source_player_source(from._internal_select_source_player_source()); + } if (from._internal_media_player_id() != 0) { _this->_impl_.media_player_id_ = from._impl_.media_player_id_; } @@ -7525,7 +7617,11 @@ void NSPanelMQTTManagerCommand_MediaPlayerCommand::CopyFrom(const NSPanelMQTTMan void NSPanelMQTTManagerCommand_MediaPlayerCommand::InternalSwap(NSPanelMQTTManagerCommand_MediaPlayerCommand* PROTOBUF_RESTRICT other) { using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.select_player_source_, &other->_impl_.select_player_source_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.select_source_player_source_, &other->_impl_.select_source_player_source_, arena); ::google::protobuf::internal::memswap< PROTOBUF_FIELD_OFFSET(NSPanelMQTTManagerCommand_MediaPlayerCommand, _impl_.source_volume_) + sizeof(NSPanelMQTTManagerCommand_MediaPlayerCommand::_impl_.source_volume_) diff --git a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h index 2c49774b..720d45b8 100644 --- a/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h +++ b/docker/MQTTManager/include/protobuf/protobuf_nspanel.pb.h @@ -2385,6 +2385,8 @@ class NSPanelMQTTManagerCommand_MediaPlayerCommand final : public ::google::prot // accessors ------------------------------------------------------- enum : int { + kSelectPlayerSourceFieldNumber = 9, + kSelectSourcePlayerSourceFieldNumber = 10, kMediaPlayerIdFieldNumber = 1, kPlaybackActionFieldNumber = 2, kVolumeFieldNumber = 4, @@ -2394,6 +2396,38 @@ class NSPanelMQTTManagerCommand_MediaPlayerCommand final : public ::google::prot kMutedFieldNumber = 8, kSourceVolumeFieldNumber = 6, }; + // string select_player_source = 9; + void clear_select_player_source() ; + const std::string& select_player_source() const; + template + void set_select_player_source(Arg_&& arg, Args_... args); + std::string* mutable_select_player_source(); + PROTOBUF_NODISCARD std::string* release_select_player_source(); + void set_allocated_select_player_source(std::string* value); + + private: + const std::string& _internal_select_player_source() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_select_player_source( + const std::string& value); + std::string* _internal_mutable_select_player_source(); + + public: + // string select_source_player_source = 10; + void clear_select_source_player_source() ; + const std::string& select_source_player_source() const; + template + void set_select_source_player_source(Arg_&& arg, Args_... args); + std::string* mutable_select_source_player_source(); + PROTOBUF_NODISCARD std::string* release_select_source_player_source(); + void set_allocated_select_source_player_source(std::string* value); + + private: + const std::string& _internal_select_source_player_source() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_select_source_player_source( + const std::string& value); + std::string* _internal_mutable_select_source_player_source(); + + public: // int32 media_player_id = 1; void clear_media_player_id() ; ::int32_t media_player_id() const; @@ -2479,8 +2513,8 @@ class NSPanelMQTTManagerCommand_MediaPlayerCommand final : public ::google::prot class _Internal; friend class ::google::protobuf::internal::TcParser; static const ::google::protobuf::internal::TcParseTable< - 3, 8, 0, - 0, 2> + 4, 10, 0, + 108, 2> _table_; static constexpr const void* _raw_default_instance_ = @@ -2500,6 +2534,8 @@ class NSPanelMQTTManagerCommand_MediaPlayerCommand final : public ::google::prot inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const NSPanelMQTTManagerCommand_MediaPlayerCommand& from_msg); + ::google::protobuf::internal::ArenaStringPtr select_player_source_; + ::google::protobuf::internal::ArenaStringPtr select_source_player_source_; ::int32_t media_player_id_; int playback_action_; ::int32_t volume_; @@ -9638,6 +9674,106 @@ inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_set_muted(bo _impl_.muted_ = value; } +// string select_player_source = 9; +inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::clear_select_player_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_player_source_.ClearToEmpty(); +} +inline const std::string& NSPanelMQTTManagerCommand_MediaPlayerCommand::select_player_source() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_player_source) + return _internal_select_player_source(); +} +template +inline PROTOBUF_ALWAYS_INLINE void NSPanelMQTTManagerCommand_MediaPlayerCommand::set_select_player_source(Arg_&& arg, + Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_player_source_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_player_source) +} +inline std::string* NSPanelMQTTManagerCommand_MediaPlayerCommand::mutable_select_player_source() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_select_player_source(); + // @@protoc_insertion_point(field_mutable:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_player_source) + return _s; +} +inline const std::string& NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_select_player_source() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.select_player_source_.Get(); +} +inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_set_select_player_source(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_player_source_.Set(value, GetArena()); +} +inline std::string* NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_mutable_select_player_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.select_player_source_.Mutable( GetArena()); +} +inline std::string* NSPanelMQTTManagerCommand_MediaPlayerCommand::release_select_player_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_player_source) + return _impl_.select_player_source_.Release(); +} +inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::set_allocated_select_player_source(std::string* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_player_source_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.select_player_source_.IsDefault()) { + _impl_.select_player_source_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_player_source) +} + +// string select_source_player_source = 10; +inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::clear_select_source_player_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_source_player_source_.ClearToEmpty(); +} +inline const std::string& NSPanelMQTTManagerCommand_MediaPlayerCommand::select_source_player_source() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_source_player_source) + return _internal_select_source_player_source(); +} +template +inline PROTOBUF_ALWAYS_INLINE void NSPanelMQTTManagerCommand_MediaPlayerCommand::set_select_source_player_source(Arg_&& arg, + Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_source_player_source_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_source_player_source) +} +inline std::string* NSPanelMQTTManagerCommand_MediaPlayerCommand::mutable_select_source_player_source() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_select_source_player_source(); + // @@protoc_insertion_point(field_mutable:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_source_player_source) + return _s; +} +inline const std::string& NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_select_source_player_source() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.select_source_player_source_.Get(); +} +inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_set_select_source_player_source(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_source_player_source_.Set(value, GetArena()); +} +inline std::string* NSPanelMQTTManagerCommand_MediaPlayerCommand::_internal_mutable_select_source_player_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.select_source_player_source_.Mutable( GetArena()); +} +inline std::string* NSPanelMQTTManagerCommand_MediaPlayerCommand::release_select_source_player_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_source_player_source) + return _impl_.select_source_player_source_.Release(); +} +inline void NSPanelMQTTManagerCommand_MediaPlayerCommand::set_allocated_select_source_player_source(std::string* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.select_source_player_source_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.select_source_player_source_.IsDefault()) { + _impl_.select_source_player_source_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:NSPanelMQTTManagerCommand.MediaPlayerCommand.select_source_player_source) +} + // ------------------------------------------------------------------- // NSPanelMQTTManagerCommand diff --git a/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.cc b/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.cc index bd8b8fce..519c215d 100644 --- a/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.cc +++ b/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.cc @@ -48,48 +48,28 @@ struct NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValueDefau PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValueDefaultTypeInternal _NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue_default_instance_; -inline constexpr NSPanelEntityState_MediaPlayer::Impl_::Impl_( +inline constexpr NSPanelEntityState_MediaPlayer_SourceSelection::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : name_( - &::google::protobuf::internal::fixed_address_empty_string, - ::_pbi::ConstantInitialized()), - media_title_( + : sources_{}, + current_source_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), - media_artist_( - &::google::protobuf::internal::fixed_address_empty_string, - ::_pbi::ConstantInitialized()), - album_art_url_( - &::google::protobuf::internal::fixed_address_empty_string, - ::_pbi::ConstantInitialized()), - media_player_id_{0}, - state_{static_cast< ::NSPanelEntityState_MediaPlayer_PlaybackState >(0)}, - volume_{0}, - source_volume_{0}, - is_muted_{false}, - has_source_volume_{false}, - can_play_{false}, - can_pause_{false}, - can_next_track_{false}, - can_previous_track_{false}, - can_set_volume_{false}, - can_mute_{false}, - volume_step_{0}, + can_select_{false}, _cached_size_{0} {} template -PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer(::_pbi::ConstantInitialized) +PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer_SourceSelection::NSPanelEntityState_MediaPlayer_SourceSelection(::_pbi::ConstantInitialized) : _impl_(::_pbi::ConstantInitialized()) {} -struct NSPanelEntityState_MediaPlayerDefaultTypeInternal { - PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayerDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} - ~NSPanelEntityState_MediaPlayerDefaultTypeInternal() {} +struct NSPanelEntityState_MediaPlayer_SourceSelectionDefaultTypeInternal { + PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer_SourceSelectionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~NSPanelEntityState_MediaPlayer_SourceSelectionDefaultTypeInternal() {} union { - NSPanelEntityState_MediaPlayer _instance; + NSPanelEntityState_MediaPlayer_SourceSelection _instance; }; }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT - PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 NSPanelEntityState_MediaPlayerDefaultTypeInternal _NSPanelEntityState_MediaPlayer_default_instance_; + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 NSPanelEntityState_MediaPlayer_SourceSelectionDefaultTypeInternal _NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_; inline constexpr NSPanelEntityState_Light::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept @@ -149,6 +129,51 @@ struct NSPanelEntityState_Thermostat_ThermostatOptionDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 NSPanelEntityState_Thermostat_ThermostatOptionDefaultTypeInternal _NSPanelEntityState_Thermostat_ThermostatOption_default_instance_; +inline constexpr NSPanelEntityState_MediaPlayer::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + media_title_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + media_artist_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + album_art_url_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + player_sources_{nullptr}, + source_player_sources_{nullptr}, + media_player_id_{0}, + state_{static_cast< ::NSPanelEntityState_MediaPlayer_PlaybackState >(0)}, + volume_{0}, + source_volume_{0}, + is_muted_{false}, + has_source_volume_{false}, + can_play_{false}, + can_pause_{false}, + can_next_track_{false}, + can_previous_track_{false}, + can_set_volume_{false}, + can_mute_{false}, + volume_step_{0} {} + +template +PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct NSPanelEntityState_MediaPlayerDefaultTypeInternal { + PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayerDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~NSPanelEntityState_MediaPlayerDefaultTypeInternal() {} + union { + NSPanelEntityState_MediaPlayer _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 NSPanelEntityState_MediaPlayerDefaultTypeInternal _NSPanelEntityState_MediaPlayer_default_instance_; + inline constexpr NSPanelEntityState_Thermostat::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept : options_{}, @@ -257,6 +282,17 @@ const ::uint32_t PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_Thermostat, _impl_.step_size_), PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_Thermostat, _impl_.options_), ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer_SourceSelection, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.sources_), + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.current_source_), + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.can_select_), + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -281,6 +317,27 @@ const ::uint32_t PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _impl_.can_mute_), PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _impl_.album_art_url_), PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _impl_.volume_step_), + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _impl_.player_sources_), + PROTOBUF_FIELD_OFFSET(::NSPanelEntityState_MediaPlayer, _impl_.source_player_sources_), + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + 0, + 1, ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::NSPanelEntityState, _internal_metadata_), ~0u, // no _extensions_ @@ -301,20 +358,22 @@ static const ::_pbi::MigrationSchema {18, -1, -1, sizeof(::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue)}, {28, -1, -1, sizeof(::NSPanelEntityState_Thermostat_ThermostatOption)}, {40, -1, -1, sizeof(::NSPanelEntityState_Thermostat)}, - {55, -1, -1, sizeof(::NSPanelEntityState_MediaPlayer)}, - {80, -1, -1, sizeof(::NSPanelEntityState)}, + {55, -1, -1, sizeof(::NSPanelEntityState_MediaPlayer_SourceSelection)}, + {66, 93, -1, sizeof(::NSPanelEntityState_MediaPlayer)}, + {112, -1, -1, sizeof(::NSPanelEntityState)}, }; static const ::_pb::Message* const file_default_instances[] = { &::_NSPanelEntityState_Light_default_instance_._instance, &::_NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue_default_instance_._instance, &::_NSPanelEntityState_Thermostat_ThermostatOption_default_instance_._instance, &::_NSPanelEntityState_Thermostat_default_instance_._instance, + &::_NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_._instance, &::_NSPanelEntityState_MediaPlayer_default_instance_._instance, &::_NSPanelEntityState_default_instance_._instance, }; const char descriptor_table_protodef_protobuf_5fnspanel_5fentity_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( protodesc_cold) = { - "\n\035protobuf_nspanel_entity.proto\"\217\013\n\022NSPa" + "\n\035protobuf_nspanel_entity.proto\"\370\014\n\022NSPa" "nelEntityState\022*\n\005light\030\001 \001(\0132\031.NSPanelE" "ntityState.LightH\000\0224\n\nthermostat\030\002 \001(\0132\036" ".NSPanelEntityState.ThermostatH\000\0227\n\014medi" @@ -337,7 +396,7 @@ const char descriptor_table_protodef_protobuf_5fnspanel_5fentity_2eproto[] ABSL_ "\030\004 \003(\0132E.NSPanelEntityState.Thermostat.T" "hermostatOption.ThermostatOptionValue\0324\n" "\025ThermostatOptionValue\022\r\n\005value\030\001 \001(\t\022\014\n" - "\004icon\030\002 \001(\t\032\201\004\n\013MediaPlayer\022\027\n\017media_pla" + "\004icon\030\002 \001(\t\032\352\005\n\013MediaPlayer\022\027\n\017media_pla" "yer_id\030\001 \001(\005\022\014\n\004name\030\002 \001(\t\022<\n\005state\030\003 \001(" "\0162-.NSPanelEntityState.MediaPlayer.Playb" "ackState\022\023\n\013media_title\030\004 \001(\t\022\024\n\014media_a" @@ -347,22 +406,28 @@ const char descriptor_table_protodef_protobuf_5fnspanel_5fentity_2eproto[] ABSL_ "_pause\030\013 \001(\010\022\026\n\016can_next_track\030\014 \001(\010\022\032\n\022" "can_previous_track\030\r \001(\010\022\026\n\016can_set_volu" "me\030\016 \001(\010\022\020\n\010can_mute\030\017 \001(\010\022\025\n\ralbum_art_" - "url\030\020 \001(\t\022\023\n\013volume_step\030\021 \001(\005\"_\n\rPlayba" - "ckState\022\013\n\007UNKNOWN\020\000\022\007\n\003OFF\020\001\022\006\n\002ON\020\002\022\010\n" - "\004IDLE\020\003\022\013\n\007PLAYING\020\004\022\n\n\006PAUSED\020\005\022\r\n\tBUFF" - "ERING\020\006B\010\n\006entityb\006proto3" + "url\030\020 \001(\t\022\023\n\013volume_step\030\021 \001(\005\022G\n\016player" + "_sources\030\022 \001(\0132/.NSPanelEntityState.Medi" + "aPlayer.SourceSelection\022N\n\025source_player" + "_sources\030\023 \001(\0132/.NSPanelEntityState.Medi" + "aPlayer.SourceSelection\032N\n\017SourceSelecti" + "on\022\017\n\007sources\030\001 \003(\t\022\026\n\016current_source\030\002 " + "\001(\t\022\022\n\ncan_select\030\003 \001(\010\"_\n\rPlaybackState" + "\022\013\n\007UNKNOWN\020\000\022\007\n\003OFF\020\001\022\006\n\002ON\020\002\022\010\n\004IDLE\020\003" + "\022\013\n\007PLAYING\020\004\022\n\n\006PAUSED\020\005\022\r\n\tBUFFERING\020\006" + "B\010\n\006entityb\006proto3" }; static ::absl::once_flag descriptor_table_protobuf_5fnspanel_5fentity_2eproto_once; PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_protobuf_5fnspanel_5fentity_2eproto = { false, false, - 1465, + 1698, descriptor_table_protodef_protobuf_5fnspanel_5fentity_2eproto, "protobuf_nspanel_entity.proto", &descriptor_table_protobuf_5fnspanel_5fentity_2eproto_once, nullptr, 0, - 6, + 7, schemas, file_default_instances, TableStruct_protobuf_5fnspanel_5fentity_2eproto::offsets, @@ -1728,8 +1793,257 @@ ::google::protobuf::Metadata NSPanelEntityState_Thermostat::GetMetadata() const } // =================================================================== +class NSPanelEntityState_MediaPlayer_SourceSelection::_Internal { + public: +}; + +NSPanelEntityState_MediaPlayer_SourceSelection::NSPanelEntityState_MediaPlayer_SourceSelection(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:NSPanelEntityState.MediaPlayer.SourceSelection) +} +inline PROTOBUF_NDEBUG_INLINE NSPanelEntityState_MediaPlayer_SourceSelection::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from, const ::NSPanelEntityState_MediaPlayer_SourceSelection& from_msg) + : sources_{visibility, arena, from.sources_}, + current_source_(arena, from.current_source_), + _cached_size_{0} {} + +NSPanelEntityState_MediaPlayer_SourceSelection::NSPanelEntityState_MediaPlayer_SourceSelection( + ::google::protobuf::Arena* arena, + const NSPanelEntityState_MediaPlayer_SourceSelection& from) + : ::google::protobuf::Message(arena) { + NSPanelEntityState_MediaPlayer_SourceSelection* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.can_select_ = from._impl_.can_select_; + + // @@protoc_insertion_point(copy_constructor:NSPanelEntityState.MediaPlayer.SourceSelection) +} +inline PROTOBUF_NDEBUG_INLINE NSPanelEntityState_MediaPlayer_SourceSelection::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : sources_{visibility, arena}, + current_source_(arena), + _cached_size_{0} {} + +inline void NSPanelEntityState_MediaPlayer_SourceSelection::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.can_select_ = {}; +} +NSPanelEntityState_MediaPlayer_SourceSelection::~NSPanelEntityState_MediaPlayer_SourceSelection() { + // @@protoc_insertion_point(destructor:NSPanelEntityState.MediaPlayer.SourceSelection) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.current_source_.Destroy(); + _impl_.~Impl_(); +} + +const ::google::protobuf::MessageLite::ClassData* +NSPanelEntityState_MediaPlayer_SourceSelection::GetClassData() const { + PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: + ClassDataFull _data_ = { + { + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_._cached_size_), + false, + }, + &NSPanelEntityState_MediaPlayer_SourceSelection::MergeImpl, + &NSPanelEntityState_MediaPlayer_SourceSelection::kDescriptorMethods, + &descriptor_table_protobuf_5fnspanel_5fentity_2eproto, + nullptr, // tracker + }; + ::google::protobuf::internal::PrefetchToLocalCache(&_data_); + ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); + return _data_.base(); +} +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 3, 0, 76, 2> NSPanelEntityState_MediaPlayer_SourceSelection::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967288, // skipmap + offsetof(decltype(_table_), field_entries), + 3, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_._instance, + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::NSPanelEntityState_MediaPlayer_SourceSelection>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // repeated string sources = 1; + {::_pbi::TcParser::FastUR1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.sources_)}}, + // string current_source = 2; + {::_pbi::TcParser::FastUS1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.current_source_)}}, + // bool can_select = 3; + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.can_select_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated string sources = 1; + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.sources_), 0, 0, + (0 | ::_fl::kFcRepeated | ::_fl::kUtf8String | ::_fl::kRepSString)}, + // string current_source = 2; + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.current_source_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bool can_select = 3; + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer_SourceSelection, _impl_.can_select_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kBool)}, + }}, + // no aux_entries + {{ + "\56\7\16\0\0\0\0\0" + "NSPanelEntityState.MediaPlayer.SourceSelection" + "sources" + "current_source" + }}, +}; + +PROTOBUF_NOINLINE void NSPanelEntityState_MediaPlayer_SourceSelection::Clear() { +// @@protoc_insertion_point(message_clear_start:NSPanelEntityState.MediaPlayer.SourceSelection) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.sources_.Clear(); + _impl_.current_source_.ClearToEmpty(); + _impl_.can_select_ = false; + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +::uint8_t* NSPanelEntityState_MediaPlayer_SourceSelection::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:NSPanelEntityState.MediaPlayer.SourceSelection) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated string sources = 1; + for (int i = 0, n = this->_internal_sources_size(); i < n; ++i) { + const auto& s = this->_internal_sources().Get(i); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "NSPanelEntityState.MediaPlayer.SourceSelection.sources"); + target = stream->WriteString(1, s, target); + } + + // string current_source = 2; + if (!this->_internal_current_source().empty()) { + const std::string& _s = this->_internal_current_source(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "NSPanelEntityState.MediaPlayer.SourceSelection.current_source"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // bool can_select = 3; + if (this->_internal_can_select() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this->_internal_can_select(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:NSPanelEntityState.MediaPlayer.SourceSelection) + return target; +} + +::size_t NSPanelEntityState_MediaPlayer_SourceSelection::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:NSPanelEntityState.MediaPlayer.SourceSelection) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(reinterpret_cast(this)); + // repeated string sources = 1; + total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_sources().size()); + for (int i = 0, n = _internal_sources().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + _internal_sources().Get(i)); + } + // string current_source = 2; + if (!this->_internal_current_source().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_current_source()); + } + + // bool can_select = 3; + if (this->_internal_can_select() != 0) { + total_size += 2; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + + +void NSPanelEntityState_MediaPlayer_SourceSelection::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:NSPanelEntityState.MediaPlayer.SourceSelection) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_sources()->MergeFrom(from._internal_sources()); + if (!from._internal_current_source().empty()) { + _this->_internal_set_current_source(from._internal_current_source()); + } + if (from._internal_can_select() != 0) { + _this->_impl_.can_select_ = from._impl_.can_select_; + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void NSPanelEntityState_MediaPlayer_SourceSelection::CopyFrom(const NSPanelEntityState_MediaPlayer_SourceSelection& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:NSPanelEntityState.MediaPlayer.SourceSelection) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void NSPanelEntityState_MediaPlayer_SourceSelection::InternalSwap(NSPanelEntityState_MediaPlayer_SourceSelection* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.sources_.InternalSwap(&other->_impl_.sources_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.current_source_, &other->_impl_.current_source_, arena); + swap(_impl_.can_select_, other->_impl_.can_select_); +} + +::google::protobuf::Metadata NSPanelEntityState_MediaPlayer_SourceSelection::GetMetadata() const { + return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + class NSPanelEntityState_MediaPlayer::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_._has_bits_); }; NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena) @@ -1740,11 +2054,12 @@ NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer(::google::protobu inline PROTOBUF_NDEBUG_INLINE NSPanelEntityState_MediaPlayer::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::NSPanelEntityState_MediaPlayer& from_msg) - : name_(arena, from.name_), + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + name_(arena, from.name_), media_title_(arena, from.media_title_), media_artist_(arena, from.media_artist_), - album_art_url_(arena, from.album_art_url_), - _cached_size_{0} {} + album_art_url_(arena, from.album_art_url_) {} NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer( ::google::protobuf::Arena* arena, @@ -1755,6 +2070,13 @@ NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer( _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.player_sources_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::NSPanelEntityState_MediaPlayer_SourceSelection>( + arena, *from._impl_.player_sources_) + : nullptr; + _impl_.source_player_sources_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::NSPanelEntityState_MediaPlayer_SourceSelection>( + arena, *from._impl_.source_player_sources_) + : nullptr; ::memcpy(reinterpret_cast(&_impl_) + offsetof(Impl_, media_player_id_), reinterpret_cast(&from._impl_) + @@ -1768,19 +2090,19 @@ NSPanelEntityState_MediaPlayer::NSPanelEntityState_MediaPlayer( inline PROTOBUF_NDEBUG_INLINE NSPanelEntityState_MediaPlayer::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : name_(arena), + : _cached_size_{0}, + name_(arena), media_title_(arena), media_artist_(arena), - album_art_url_(arena), - _cached_size_{0} {} + album_art_url_(arena) {} inline void NSPanelEntityState_MediaPlayer::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); ::memset(reinterpret_cast(&_impl_) + - offsetof(Impl_, media_player_id_), + offsetof(Impl_, player_sources_), 0, offsetof(Impl_, volume_step_) - - offsetof(Impl_, media_player_id_) + + offsetof(Impl_, player_sources_) + sizeof(Impl_::volume_step_)); } NSPanelEntityState_MediaPlayer::~NSPanelEntityState_MediaPlayer() { @@ -1794,6 +2116,8 @@ inline void NSPanelEntityState_MediaPlayer::SharedDtor() { _impl_.media_title_.Destroy(); _impl_.media_artist_.Destroy(); _impl_.album_art_url_.Destroy(); + delete _impl_.player_sources_; + delete _impl_.source_player_sources_; _impl_.~Impl_(); } @@ -1818,17 +2142,17 @@ NSPanelEntityState_MediaPlayer::GetClassData() const { return _data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<5, 17, 0, 95, 2> NSPanelEntityState_MediaPlayer::_table_ = { +const ::_pbi::TcParseTable<5, 19, 2, 95, 2> NSPanelEntityState_MediaPlayer::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_._has_bits_), 0, // no _extensions_ - 17, 248, // max_field_number, fast_idx_mask + 19, 248, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294836224, // skipmap + 4294443008, // skipmap offsetof(decltype(_table_), field_entries), - 17, // num_field_entries - 0, // num_aux_entries - offsetof(decltype(_table_), field_names), // no aux_entries + 19, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), &_NSPanelEntityState_MediaPlayer_default_instance_._instance, nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback @@ -1888,8 +2212,12 @@ const ::_pbi::TcParseTable<5, 17, 0, 95, 2> NSPanelEntityState_MediaPlayer::_tab // int32 volume_step = 17; {::_pbi::TcParser::FastV32S2, {392, 63, 0, PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.volume_step_)}}, - {::_pbi::TcParser::MiniParse, {}}, - {::_pbi::TcParser::MiniParse, {}}, + // .NSPanelEntityState.MediaPlayer.SourceSelection player_sources = 18; + {::_pbi::TcParser::FastMtS2, + {402, 0, 0, PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.player_sources_)}}, + // .NSPanelEntityState.MediaPlayer.SourceSelection source_player_sources = 19; + {::_pbi::TcParser::FastMtS2, + {410, 1, 1, PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.source_player_sources_)}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, @@ -1906,59 +2234,66 @@ const ::_pbi::TcParseTable<5, 17, 0, 95, 2> NSPanelEntityState_MediaPlayer::_tab 65535, 65535 }}, {{ // int32 media_player_id = 1; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_player_id_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_player_id_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, // string name = 2; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.name_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.name_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, // .NSPanelEntityState.MediaPlayer.PlaybackState state = 3; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.state_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.state_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, // string media_title = 4; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_title_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_title_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, // string media_artist = 5; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_artist_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_artist_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, // int32 volume = 6; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.volume_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.volume_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, // bool is_muted = 7; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.is_muted_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.is_muted_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // bool has_source_volume = 8; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.has_source_volume_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.has_source_volume_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // int32 source_volume = 9; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.source_volume_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.source_volume_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, // bool can_play = 10; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_play_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_play_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // bool can_pause = 11; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_pause_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_pause_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // bool can_next_track = 12; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_next_track_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_next_track_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // bool can_previous_track = 13; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_previous_track_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_previous_track_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // bool can_set_volume = 14; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_set_volume_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_set_volume_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // bool can_mute = 15; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_mute_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.can_mute_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kBool)}, // string album_art_url = 16; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.album_art_url_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.album_art_url_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, // int32 volume_step = 17; - {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.volume_step_), 0, 0, + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.volume_step_), -1, 0, (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, - }}, - // no aux_entries - {{ + // .NSPanelEntityState.MediaPlayer.SourceSelection player_sources = 18; + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.player_sources_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .NSPanelEntityState.MediaPlayer.SourceSelection source_player_sources = 19; + {PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.source_player_sources_), _Internal::kHasBitsOffset + 1, 1, + (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, {{ + {::_pbi::TcParser::GetTable<::NSPanelEntityState_MediaPlayer_SourceSelection>()}, + {::_pbi::TcParser::GetTable<::NSPanelEntityState_MediaPlayer_SourceSelection>()}, + }}, {{ "\36\0\4\0\13\14\0\0\0\0\0\0\0\0\0\0\15\0\0\0\0\0\0\0" "NSPanelEntityState.MediaPlayer" "name" @@ -1979,9 +2314,21 @@ PROTOBUF_NOINLINE void NSPanelEntityState_MediaPlayer::Clear() { _impl_.media_title_.ClearToEmpty(); _impl_.media_artist_.ClearToEmpty(); _impl_.album_art_url_.ClearToEmpty(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + ABSL_DCHECK(_impl_.player_sources_ != nullptr); + _impl_.player_sources_->Clear(); + } + if (cached_has_bits & 0x00000002u) { + ABSL_DCHECK(_impl_.source_player_sources_ != nullptr); + _impl_.source_player_sources_->Clear(); + } + } ::memset(&_impl_.media_player_id_, 0, static_cast<::size_t>( reinterpret_cast(&_impl_.volume_step_) - reinterpret_cast(&_impl_.media_player_id_)) + sizeof(_impl_.volume_step_)); + _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } @@ -2115,6 +2462,19 @@ ::uint8_t* NSPanelEntityState_MediaPlayer::_InternalSerialize( 17, this->_internal_volume_step(), target); } + cached_has_bits = _impl_._has_bits_[0]; + // .NSPanelEntityState.MediaPlayer.SourceSelection player_sources = 18; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 18, *_impl_.player_sources_, _impl_.player_sources_->GetCachedSize(), target, stream); + } + + // .NSPanelEntityState.MediaPlayer.SourceSelection source_player_sources = 19; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 19, *_impl_.source_player_sources_, _impl_.source_player_sources_->GetCachedSize(), target, stream); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( @@ -2157,6 +2517,21 @@ ::size_t NSPanelEntityState_MediaPlayer::ByteSizeLong() const { this->_internal_album_art_url()); } + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // .NSPanelEntityState.MediaPlayer.SourceSelection player_sources = 18; + if (cached_has_bits & 0x00000001u) { + total_size += + 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.player_sources_); + } + + // .NSPanelEntityState.MediaPlayer.SourceSelection source_player_sources = 19; + if (cached_has_bits & 0x00000002u) { + total_size += + 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.source_player_sources_); + } + + } // int32 media_player_id = 1; if (this->_internal_media_player_id() != 0) { total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( @@ -2234,6 +2609,7 @@ ::size_t NSPanelEntityState_MediaPlayer::ByteSizeLong() const { void NSPanelEntityState_MediaPlayer::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); auto& from = static_cast(from_msg); + ::google::protobuf::Arena* arena = _this->GetArena(); // @@protoc_insertion_point(class_specific_merge_from_start:NSPanelEntityState.MediaPlayer) ABSL_DCHECK_NE(&from, _this); ::uint32_t cached_has_bits = 0; @@ -2251,6 +2627,27 @@ void NSPanelEntityState_MediaPlayer::MergeImpl(::google::protobuf::MessageLite& if (!from._internal_album_art_url().empty()) { _this->_internal_set_album_art_url(from._internal_album_art_url()); } + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + ABSL_DCHECK(from._impl_.player_sources_ != nullptr); + if (_this->_impl_.player_sources_ == nullptr) { + _this->_impl_.player_sources_ = + ::google::protobuf::Message::CopyConstruct<::NSPanelEntityState_MediaPlayer_SourceSelection>(arena, *from._impl_.player_sources_); + } else { + _this->_impl_.player_sources_->MergeFrom(*from._impl_.player_sources_); + } + } + if (cached_has_bits & 0x00000002u) { + ABSL_DCHECK(from._impl_.source_player_sources_ != nullptr); + if (_this->_impl_.source_player_sources_ == nullptr) { + _this->_impl_.source_player_sources_ = + ::google::protobuf::Message::CopyConstruct<::NSPanelEntityState_MediaPlayer_SourceSelection>(arena, *from._impl_.source_player_sources_); + } else { + _this->_impl_.source_player_sources_->MergeFrom(*from._impl_.source_player_sources_); + } + } + } if (from._internal_media_player_id() != 0) { _this->_impl_.media_player_id_ = from._impl_.media_player_id_; } @@ -2290,6 +2687,7 @@ void NSPanelEntityState_MediaPlayer::MergeImpl(::google::protobuf::MessageLite& if (from._internal_volume_step() != 0) { _this->_impl_.volume_step_ = from._impl_.volume_step_; } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -2306,6 +2704,7 @@ void NSPanelEntityState_MediaPlayer::InternalSwap(NSPanelEntityState_MediaPlayer auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.media_title_, &other->_impl_.media_title_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.media_artist_, &other->_impl_.media_artist_, arena); @@ -2313,9 +2712,9 @@ void NSPanelEntityState_MediaPlayer::InternalSwap(NSPanelEntityState_MediaPlayer ::google::protobuf::internal::memswap< PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.volume_step_) + sizeof(NSPanelEntityState_MediaPlayer::_impl_.volume_step_) - - PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.media_player_id_)>( - reinterpret_cast(&_impl_.media_player_id_), - reinterpret_cast(&other->_impl_.media_player_id_)); + - PROTOBUF_FIELD_OFFSET(NSPanelEntityState_MediaPlayer, _impl_.player_sources_)>( + reinterpret_cast(&_impl_.player_sources_), + reinterpret_cast(&other->_impl_.player_sources_)); } ::google::protobuf::Metadata NSPanelEntityState_MediaPlayer::GetMetadata() const { diff --git a/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.h b/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.h index d7cfb6d0..84139b73 100644 --- a/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.h +++ b/docker/MQTTManager/include/protobuf/protobuf_nspanel_entity.pb.h @@ -59,6 +59,9 @@ extern NSPanelEntityState_LightDefaultTypeInternal _NSPanelEntityState_Light_def class NSPanelEntityState_MediaPlayer; struct NSPanelEntityState_MediaPlayerDefaultTypeInternal; extern NSPanelEntityState_MediaPlayerDefaultTypeInternal _NSPanelEntityState_MediaPlayer_default_instance_; +class NSPanelEntityState_MediaPlayer_SourceSelection; +struct NSPanelEntityState_MediaPlayer_SourceSelectionDefaultTypeInternal; +extern NSPanelEntityState_MediaPlayer_SourceSelectionDefaultTypeInternal _NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_; class NSPanelEntityState_Thermostat; struct NSPanelEntityState_ThermostatDefaultTypeInternal; extern NSPanelEntityState_ThermostatDefaultTypeInternal _NSPanelEntityState_Thermostat_default_instance_; @@ -345,23 +348,23 @@ class NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue final }; // ------------------------------------------------------------------- -class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message -/* @@protoc_insertion_point(class_definition:NSPanelEntityState.MediaPlayer) */ { +class NSPanelEntityState_MediaPlayer_SourceSelection final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:NSPanelEntityState.MediaPlayer.SourceSelection) */ { public: - inline NSPanelEntityState_MediaPlayer() : NSPanelEntityState_MediaPlayer(nullptr) {} - ~NSPanelEntityState_MediaPlayer() override; + inline NSPanelEntityState_MediaPlayer_SourceSelection() : NSPanelEntityState_MediaPlayer_SourceSelection(nullptr) {} + ~NSPanelEntityState_MediaPlayer_SourceSelection() override; template - explicit PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer( + explicit PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer_SourceSelection( ::google::protobuf::internal::ConstantInitialized); - inline NSPanelEntityState_MediaPlayer(const NSPanelEntityState_MediaPlayer& from) : NSPanelEntityState_MediaPlayer(nullptr, from) {} - inline NSPanelEntityState_MediaPlayer(NSPanelEntityState_MediaPlayer&& from) noexcept - : NSPanelEntityState_MediaPlayer(nullptr, std::move(from)) {} - inline NSPanelEntityState_MediaPlayer& operator=(const NSPanelEntityState_MediaPlayer& from) { + inline NSPanelEntityState_MediaPlayer_SourceSelection(const NSPanelEntityState_MediaPlayer_SourceSelection& from) : NSPanelEntityState_MediaPlayer_SourceSelection(nullptr, from) {} + inline NSPanelEntityState_MediaPlayer_SourceSelection(NSPanelEntityState_MediaPlayer_SourceSelection&& from) noexcept + : NSPanelEntityState_MediaPlayer_SourceSelection(nullptr, std::move(from)) {} + inline NSPanelEntityState_MediaPlayer_SourceSelection& operator=(const NSPanelEntityState_MediaPlayer_SourceSelection& from) { CopyFrom(from); return *this; } - inline NSPanelEntityState_MediaPlayer& operator=(NSPanelEntityState_MediaPlayer&& from) noexcept { + inline NSPanelEntityState_MediaPlayer_SourceSelection& operator=(NSPanelEntityState_MediaPlayer_SourceSelection&& from) noexcept { if (this == &from) return *this; if (GetArena() == from.GetArena() #ifdef PROTOBUF_FORCE_COPY_IN_MOVE @@ -393,16 +396,16 @@ class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message static const ::google::protobuf::Reflection* GetReflection() { return default_instance().GetMetadata().reflection; } - static const NSPanelEntityState_MediaPlayer& default_instance() { + static const NSPanelEntityState_MediaPlayer_SourceSelection& default_instance() { return *internal_default_instance(); } - static inline const NSPanelEntityState_MediaPlayer* internal_default_instance() { - return reinterpret_cast( - &_NSPanelEntityState_MediaPlayer_default_instance_); + static inline const NSPanelEntityState_MediaPlayer_SourceSelection* internal_default_instance() { + return reinterpret_cast( + &_NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_); } static constexpr int kIndexInFileMessages = 4; - friend void swap(NSPanelEntityState_MediaPlayer& a, NSPanelEntityState_MediaPlayer& b) { a.Swap(&b); } - inline void Swap(NSPanelEntityState_MediaPlayer* other) { + friend void swap(NSPanelEntityState_MediaPlayer_SourceSelection& a, NSPanelEntityState_MediaPlayer_SourceSelection& b) { a.Swap(&b); } + inline void Swap(NSPanelEntityState_MediaPlayer_SourceSelection* other) { if (other == this) return; #ifdef PROTOBUF_FORCE_COPY_IN_SWAP if (GetArena() != nullptr && GetArena() == other->GetArena()) { @@ -414,7 +417,7 @@ class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message ::google::protobuf::internal::GenericSwap(this, other); } } - void UnsafeArenaSwap(NSPanelEntityState_MediaPlayer* other) { + void UnsafeArenaSwap(NSPanelEntityState_MediaPlayer_SourceSelection* other) { if (other == this) return; ABSL_DCHECK(GetArena() == other->GetArena()); InternalSwap(other); @@ -422,13 +425,13 @@ class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - NSPanelEntityState_MediaPlayer* New(::google::protobuf::Arena* arena = nullptr) const final { - return ::google::protobuf::Message::DefaultConstruct(arena); + NSPanelEntityState_MediaPlayer_SourceSelection* New(::google::protobuf::Arena* arena = nullptr) const final { + return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; - void CopyFrom(const NSPanelEntityState_MediaPlayer& from); + void CopyFrom(const NSPanelEntityState_MediaPlayer_SourceSelection& from); using ::google::protobuf::Message::MergeFrom; - void MergeFrom(const NSPanelEntityState_MediaPlayer& from) { NSPanelEntityState_MediaPlayer::MergeImpl(*this, from); } + void MergeFrom(const NSPanelEntityState_MediaPlayer_SourceSelection& from) { NSPanelEntityState_MediaPlayer_SourceSelection::MergeImpl(*this, from); } private: static void MergeImpl( @@ -449,16 +452,16 @@ class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message private: void SharedCtor(::google::protobuf::Arena* arena); void SharedDtor(); - void InternalSwap(NSPanelEntityState_MediaPlayer* other); + void InternalSwap(NSPanelEntityState_MediaPlayer_SourceSelection* other); private: friend class ::google::protobuf::internal::AnyMetadata; - static ::absl::string_view FullMessageName() { return "NSPanelEntityState.MediaPlayer"; } + static ::absl::string_view FullMessageName() { return "NSPanelEntityState.MediaPlayer.SourceSelection"; } protected: - explicit NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena); - NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena, const NSPanelEntityState_MediaPlayer& from); - NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena, NSPanelEntityState_MediaPlayer&& from) noexcept - : NSPanelEntityState_MediaPlayer(arena) { + explicit NSPanelEntityState_MediaPlayer_SourceSelection(::google::protobuf::Arena* arena); + NSPanelEntityState_MediaPlayer_SourceSelection(::google::protobuf::Arena* arena, const NSPanelEntityState_MediaPlayer_SourceSelection& from); + NSPanelEntityState_MediaPlayer_SourceSelection(::google::protobuf::Arena* arena, NSPanelEntityState_MediaPlayer_SourceSelection&& from) noexcept + : NSPanelEntityState_MediaPlayer_SourceSelection(arena) { *this = ::std::move(from); } const ::google::protobuf::Message::ClassData* GetClassData() const final; @@ -466,256 +469,78 @@ class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message public: ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- - using PlaybackState = NSPanelEntityState_MediaPlayer_PlaybackState; - static constexpr PlaybackState UNKNOWN = NSPanelEntityState_MediaPlayer_PlaybackState_UNKNOWN; - static constexpr PlaybackState OFF = NSPanelEntityState_MediaPlayer_PlaybackState_OFF; - static constexpr PlaybackState ON = NSPanelEntityState_MediaPlayer_PlaybackState_ON; - static constexpr PlaybackState IDLE = NSPanelEntityState_MediaPlayer_PlaybackState_IDLE; - static constexpr PlaybackState PLAYING = NSPanelEntityState_MediaPlayer_PlaybackState_PLAYING; - static constexpr PlaybackState PAUSED = NSPanelEntityState_MediaPlayer_PlaybackState_PAUSED; - static constexpr PlaybackState BUFFERING = NSPanelEntityState_MediaPlayer_PlaybackState_BUFFERING; - static inline bool PlaybackState_IsValid(int value) { - return NSPanelEntityState_MediaPlayer_PlaybackState_IsValid(value); - } - static constexpr PlaybackState PlaybackState_MIN = NSPanelEntityState_MediaPlayer_PlaybackState_PlaybackState_MIN; - static constexpr PlaybackState PlaybackState_MAX = NSPanelEntityState_MediaPlayer_PlaybackState_PlaybackState_MAX; - static constexpr int PlaybackState_ARRAYSIZE = NSPanelEntityState_MediaPlayer_PlaybackState_PlaybackState_ARRAYSIZE; - static inline const ::google::protobuf::EnumDescriptor* PlaybackState_descriptor() { - return NSPanelEntityState_MediaPlayer_PlaybackState_descriptor(); - } - template - static inline const std::string& PlaybackState_Name(T value) { - return NSPanelEntityState_MediaPlayer_PlaybackState_Name(value); - } - static inline bool PlaybackState_Parse(absl::string_view name, PlaybackState* value) { - return NSPanelEntityState_MediaPlayer_PlaybackState_Parse(name, value); - } // accessors ------------------------------------------------------- enum : int { - kNameFieldNumber = 2, - kMediaTitleFieldNumber = 4, - kMediaArtistFieldNumber = 5, - kAlbumArtUrlFieldNumber = 16, - kMediaPlayerIdFieldNumber = 1, - kStateFieldNumber = 3, - kVolumeFieldNumber = 6, - kSourceVolumeFieldNumber = 9, - kIsMutedFieldNumber = 7, - kHasSourceVolumeFieldNumber = 8, - kCanPlayFieldNumber = 10, - kCanPauseFieldNumber = 11, - kCanNextTrackFieldNumber = 12, - kCanPreviousTrackFieldNumber = 13, - kCanSetVolumeFieldNumber = 14, - kCanMuteFieldNumber = 15, - kVolumeStepFieldNumber = 17, + kSourcesFieldNumber = 1, + kCurrentSourceFieldNumber = 2, + kCanSelectFieldNumber = 3, }; - // string name = 2; - void clear_name() ; - const std::string& name() const; - template - void set_name(Arg_&& arg, Args_... args); - std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); - void set_allocated_name(std::string* value); - - private: - const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); - std::string* _internal_mutable_name(); - - public: - // string media_title = 4; - void clear_media_title() ; - const std::string& media_title() const; - template - void set_media_title(Arg_&& arg, Args_... args); - std::string* mutable_media_title(); - PROTOBUF_NODISCARD std::string* release_media_title(); - void set_allocated_media_title(std::string* value); - + // repeated string sources = 1; + int sources_size() const; private: - const std::string& _internal_media_title() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_media_title( - const std::string& value); - std::string* _internal_mutable_media_title(); + int _internal_sources_size() const; public: - // string media_artist = 5; - void clear_media_artist() ; - const std::string& media_artist() const; - template - void set_media_artist(Arg_&& arg, Args_... args); - std::string* mutable_media_artist(); - PROTOBUF_NODISCARD std::string* release_media_artist(); - void set_allocated_media_artist(std::string* value); + void clear_sources() ; + const std::string& sources(int index) const; + std::string* mutable_sources(int index); + void set_sources(int index, const std::string& value); + void set_sources(int index, std::string&& value); + void set_sources(int index, const char* value); + void set_sources(int index, const char* value, std::size_t size); + void set_sources(int index, absl::string_view value); + std::string* add_sources(); + void add_sources(const std::string& value); + void add_sources(std::string&& value); + void add_sources(const char* value); + void add_sources(const char* value, std::size_t size); + void add_sources(absl::string_view value); + const ::google::protobuf::RepeatedPtrField& sources() const; + ::google::protobuf::RepeatedPtrField* mutable_sources(); private: - const std::string& _internal_media_artist() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_media_artist( - const std::string& value); - std::string* _internal_mutable_media_artist(); + const ::google::protobuf::RepeatedPtrField& _internal_sources() const; + ::google::protobuf::RepeatedPtrField* _internal_mutable_sources(); public: - // string album_art_url = 16; - void clear_album_art_url() ; - const std::string& album_art_url() const; + // string current_source = 2; + void clear_current_source() ; + const std::string& current_source() const; template - void set_album_art_url(Arg_&& arg, Args_... args); - std::string* mutable_album_art_url(); - PROTOBUF_NODISCARD std::string* release_album_art_url(); - void set_allocated_album_art_url(std::string* value); + void set_current_source(Arg_&& arg, Args_... args); + std::string* mutable_current_source(); + PROTOBUF_NODISCARD std::string* release_current_source(); + void set_allocated_current_source(std::string* value); private: - const std::string& _internal_album_art_url() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_album_art_url( + const std::string& _internal_current_source() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_current_source( const std::string& value); - std::string* _internal_mutable_album_art_url(); - - public: - // int32 media_player_id = 1; - void clear_media_player_id() ; - ::int32_t media_player_id() const; - void set_media_player_id(::int32_t value); - - private: - ::int32_t _internal_media_player_id() const; - void _internal_set_media_player_id(::int32_t value); - - public: - // .NSPanelEntityState.MediaPlayer.PlaybackState state = 3; - void clear_state() ; - ::NSPanelEntityState_MediaPlayer_PlaybackState state() const; - void set_state(::NSPanelEntityState_MediaPlayer_PlaybackState value); - - private: - ::NSPanelEntityState_MediaPlayer_PlaybackState _internal_state() const; - void _internal_set_state(::NSPanelEntityState_MediaPlayer_PlaybackState value); - - public: - // int32 volume = 6; - void clear_volume() ; - ::int32_t volume() const; - void set_volume(::int32_t value); - - private: - ::int32_t _internal_volume() const; - void _internal_set_volume(::int32_t value); - - public: - // int32 source_volume = 9; - void clear_source_volume() ; - ::int32_t source_volume() const; - void set_source_volume(::int32_t value); - - private: - ::int32_t _internal_source_volume() const; - void _internal_set_source_volume(::int32_t value); - - public: - // bool is_muted = 7; - void clear_is_muted() ; - bool is_muted() const; - void set_is_muted(bool value); - - private: - bool _internal_is_muted() const; - void _internal_set_is_muted(bool value); - - public: - // bool has_source_volume = 8; - void clear_has_source_volume() ; - bool has_source_volume() const; - void set_has_source_volume(bool value); - - private: - bool _internal_has_source_volume() const; - void _internal_set_has_source_volume(bool value); - - public: - // bool can_play = 10; - void clear_can_play() ; - bool can_play() const; - void set_can_play(bool value); - - private: - bool _internal_can_play() const; - void _internal_set_can_play(bool value); - - public: - // bool can_pause = 11; - void clear_can_pause() ; - bool can_pause() const; - void set_can_pause(bool value); - - private: - bool _internal_can_pause() const; - void _internal_set_can_pause(bool value); - - public: - // bool can_next_track = 12; - void clear_can_next_track() ; - bool can_next_track() const; - void set_can_next_track(bool value); - - private: - bool _internal_can_next_track() const; - void _internal_set_can_next_track(bool value); - - public: - // bool can_previous_track = 13; - void clear_can_previous_track() ; - bool can_previous_track() const; - void set_can_previous_track(bool value); - - private: - bool _internal_can_previous_track() const; - void _internal_set_can_previous_track(bool value); - - public: - // bool can_set_volume = 14; - void clear_can_set_volume() ; - bool can_set_volume() const; - void set_can_set_volume(bool value); - - private: - bool _internal_can_set_volume() const; - void _internal_set_can_set_volume(bool value); - - public: - // bool can_mute = 15; - void clear_can_mute() ; - bool can_mute() const; - void set_can_mute(bool value); - - private: - bool _internal_can_mute() const; - void _internal_set_can_mute(bool value); + std::string* _internal_mutable_current_source(); public: - // int32 volume_step = 17; - void clear_volume_step() ; - ::int32_t volume_step() const; - void set_volume_step(::int32_t value); + // bool can_select = 3; + void clear_can_select() ; + bool can_select() const; + void set_can_select(bool value); private: - ::int32_t _internal_volume_step() const; - void _internal_set_volume_step(::int32_t value); + bool _internal_can_select() const; + void _internal_set_can_select(bool value); public: - // @@protoc_insertion_point(class_scope:NSPanelEntityState.MediaPlayer) + // @@protoc_insertion_point(class_scope:NSPanelEntityState.MediaPlayer.SourceSelection) private: class _Internal; friend class ::google::protobuf::internal::TcParser; static const ::google::protobuf::internal::TcParseTable< - 5, 17, 0, - 95, 2> + 2, 3, 0, + 76, 2> _table_; static constexpr const void* _raw_default_instance_ = - &_NSPanelEntityState_MediaPlayer_default_instance_; + &_NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_; friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; @@ -730,24 +555,10 @@ class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message ::google::protobuf::Arena* arena); inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, - const NSPanelEntityState_MediaPlayer& from_msg); - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr media_title_; - ::google::protobuf::internal::ArenaStringPtr media_artist_; - ::google::protobuf::internal::ArenaStringPtr album_art_url_; - ::int32_t media_player_id_; - int state_; - ::int32_t volume_; - ::int32_t source_volume_; - bool is_muted_; - bool has_source_volume_; - bool can_play_; - bool can_pause_; - bool can_next_track_; - bool can_previous_track_; - bool can_set_volume_; - bool can_mute_; - ::int32_t volume_step_; + const NSPanelEntityState_MediaPlayer_SourceSelection& from_msg); + ::google::protobuf::RepeatedPtrField sources_; + ::google::protobuf::internal::ArenaStringPtr current_source_; + bool can_select_; mutable ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; @@ -1183,89 +994,520 @@ class NSPanelEntityState_Thermostat_ThermostatOption final : public ::google::pr // nested types ---------------------------------------------------- using ThermostatOptionValue = NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue; - // accessors ------------------------------------------------------- - enum : int { - kOptionsFieldNumber = 4, - kNameFieldNumber = 1, - kCurrentValueFieldNumber = 2, - kCurrentIconFieldNumber = 3, - }; - // repeated .NSPanelEntityState.Thermostat.ThermostatOption.ThermostatOptionValue options = 4; - int options_size() const; + // accessors ------------------------------------------------------- + enum : int { + kOptionsFieldNumber = 4, + kNameFieldNumber = 1, + kCurrentValueFieldNumber = 2, + kCurrentIconFieldNumber = 3, + }; + // repeated .NSPanelEntityState.Thermostat.ThermostatOption.ThermostatOptionValue options = 4; + int options_size() const; + private: + int _internal_options_size() const; + + public: + void clear_options() ; + ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue* mutable_options(int index); + ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>* mutable_options(); + + private: + const ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>& _internal_options() const; + ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>* _internal_mutable_options(); + public: + const ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue& options(int index) const; + ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue* add_options(); + const ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>& options() const; + // string name = 1; + void clear_name() ; + const std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* value); + + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( + const std::string& value); + std::string* _internal_mutable_name(); + + public: + // string current_value = 2; + void clear_current_value() ; + const std::string& current_value() const; + template + void set_current_value(Arg_&& arg, Args_... args); + std::string* mutable_current_value(); + PROTOBUF_NODISCARD std::string* release_current_value(); + void set_allocated_current_value(std::string* value); + + private: + const std::string& _internal_current_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_current_value( + const std::string& value); + std::string* _internal_mutable_current_value(); + + public: + // string current_icon = 3; + void clear_current_icon() ; + const std::string& current_icon() const; + template + void set_current_icon(Arg_&& arg, Args_... args); + std::string* mutable_current_icon(); + PROTOBUF_NODISCARD std::string* release_current_icon(); + void set_allocated_current_icon(std::string* value); + + private: + const std::string& _internal_current_icon() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_current_icon( + const std::string& value); + std::string* _internal_mutable_current_icon(); + + public: + // @@protoc_insertion_point(class_scope:NSPanelEntityState.Thermostat.ThermostatOption) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 2, 4, 1, + 84, 2> + _table_; + + static constexpr const void* _raw_default_instance_ = + &_NSPanelEntityState_Thermostat_ThermostatOption_default_instance_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from, + const NSPanelEntityState_Thermostat_ThermostatOption& from_msg); + ::google::protobuf::RepeatedPtrField< ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue > options_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::google::protobuf::internal::ArenaStringPtr current_value_; + ::google::protobuf::internal::ArenaStringPtr current_icon_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_protobuf_5fnspanel_5fentity_2eproto; +}; +// ------------------------------------------------------------------- + +class NSPanelEntityState_MediaPlayer final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:NSPanelEntityState.MediaPlayer) */ { + public: + inline NSPanelEntityState_MediaPlayer() : NSPanelEntityState_MediaPlayer(nullptr) {} + ~NSPanelEntityState_MediaPlayer() override; + template + explicit PROTOBUF_CONSTEXPR NSPanelEntityState_MediaPlayer( + ::google::protobuf::internal::ConstantInitialized); + + inline NSPanelEntityState_MediaPlayer(const NSPanelEntityState_MediaPlayer& from) : NSPanelEntityState_MediaPlayer(nullptr, from) {} + inline NSPanelEntityState_MediaPlayer(NSPanelEntityState_MediaPlayer&& from) noexcept + : NSPanelEntityState_MediaPlayer(nullptr, std::move(from)) {} + inline NSPanelEntityState_MediaPlayer& operator=(const NSPanelEntityState_MediaPlayer& from) { + CopyFrom(from); + return *this; + } + inline NSPanelEntityState_MediaPlayer& operator=(NSPanelEntityState_MediaPlayer&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() +#ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr +#endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const NSPanelEntityState_MediaPlayer& default_instance() { + return *internal_default_instance(); + } + static inline const NSPanelEntityState_MediaPlayer* internal_default_instance() { + return reinterpret_cast( + &_NSPanelEntityState_MediaPlayer_default_instance_); + } + static constexpr int kIndexInFileMessages = 5; + friend void swap(NSPanelEntityState_MediaPlayer& a, NSPanelEntityState_MediaPlayer& b) { a.Swap(&b); } + inline void Swap(NSPanelEntityState_MediaPlayer* other) { + if (other == this) return; +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && GetArena() == other->GetArena()) { +#else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NSPanelEntityState_MediaPlayer* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + NSPanelEntityState_MediaPlayer* New(::google::protobuf::Arena* arena = nullptr) const final { + return ::google::protobuf::Message::DefaultConstruct(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const NSPanelEntityState_MediaPlayer& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom(const NSPanelEntityState_MediaPlayer& from) { NSPanelEntityState_MediaPlayer::MergeImpl(*this, from); } + + private: + static void MergeImpl( + ::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ::size_t ByteSizeLong() const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(NSPanelEntityState_MediaPlayer* other); + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { return "NSPanelEntityState.MediaPlayer"; } + + protected: + explicit NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena); + NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena, const NSPanelEntityState_MediaPlayer& from); + NSPanelEntityState_MediaPlayer(::google::protobuf::Arena* arena, NSPanelEntityState_MediaPlayer&& from) noexcept + : NSPanelEntityState_MediaPlayer(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::Message::ClassData* GetClassData() const final; + + public: + ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + using SourceSelection = NSPanelEntityState_MediaPlayer_SourceSelection; + using PlaybackState = NSPanelEntityState_MediaPlayer_PlaybackState; + static constexpr PlaybackState UNKNOWN = NSPanelEntityState_MediaPlayer_PlaybackState_UNKNOWN; + static constexpr PlaybackState OFF = NSPanelEntityState_MediaPlayer_PlaybackState_OFF; + static constexpr PlaybackState ON = NSPanelEntityState_MediaPlayer_PlaybackState_ON; + static constexpr PlaybackState IDLE = NSPanelEntityState_MediaPlayer_PlaybackState_IDLE; + static constexpr PlaybackState PLAYING = NSPanelEntityState_MediaPlayer_PlaybackState_PLAYING; + static constexpr PlaybackState PAUSED = NSPanelEntityState_MediaPlayer_PlaybackState_PAUSED; + static constexpr PlaybackState BUFFERING = NSPanelEntityState_MediaPlayer_PlaybackState_BUFFERING; + static inline bool PlaybackState_IsValid(int value) { + return NSPanelEntityState_MediaPlayer_PlaybackState_IsValid(value); + } + static constexpr PlaybackState PlaybackState_MIN = NSPanelEntityState_MediaPlayer_PlaybackState_PlaybackState_MIN; + static constexpr PlaybackState PlaybackState_MAX = NSPanelEntityState_MediaPlayer_PlaybackState_PlaybackState_MAX; + static constexpr int PlaybackState_ARRAYSIZE = NSPanelEntityState_MediaPlayer_PlaybackState_PlaybackState_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* PlaybackState_descriptor() { + return NSPanelEntityState_MediaPlayer_PlaybackState_descriptor(); + } + template + static inline const std::string& PlaybackState_Name(T value) { + return NSPanelEntityState_MediaPlayer_PlaybackState_Name(value); + } + static inline bool PlaybackState_Parse(absl::string_view name, PlaybackState* value) { + return NSPanelEntityState_MediaPlayer_PlaybackState_Parse(name, value); + } + + // accessors ------------------------------------------------------- + enum : int { + kNameFieldNumber = 2, + kMediaTitleFieldNumber = 4, + kMediaArtistFieldNumber = 5, + kAlbumArtUrlFieldNumber = 16, + kPlayerSourcesFieldNumber = 18, + kSourcePlayerSourcesFieldNumber = 19, + kMediaPlayerIdFieldNumber = 1, + kStateFieldNumber = 3, + kVolumeFieldNumber = 6, + kSourceVolumeFieldNumber = 9, + kIsMutedFieldNumber = 7, + kHasSourceVolumeFieldNumber = 8, + kCanPlayFieldNumber = 10, + kCanPauseFieldNumber = 11, + kCanNextTrackFieldNumber = 12, + kCanPreviousTrackFieldNumber = 13, + kCanSetVolumeFieldNumber = 14, + kCanMuteFieldNumber = 15, + kVolumeStepFieldNumber = 17, + }; + // string name = 2; + void clear_name() ; + const std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* value); + + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( + const std::string& value); + std::string* _internal_mutable_name(); + + public: + // string media_title = 4; + void clear_media_title() ; + const std::string& media_title() const; + template + void set_media_title(Arg_&& arg, Args_... args); + std::string* mutable_media_title(); + PROTOBUF_NODISCARD std::string* release_media_title(); + void set_allocated_media_title(std::string* value); + + private: + const std::string& _internal_media_title() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_media_title( + const std::string& value); + std::string* _internal_mutable_media_title(); + + public: + // string media_artist = 5; + void clear_media_artist() ; + const std::string& media_artist() const; + template + void set_media_artist(Arg_&& arg, Args_... args); + std::string* mutable_media_artist(); + PROTOBUF_NODISCARD std::string* release_media_artist(); + void set_allocated_media_artist(std::string* value); + + private: + const std::string& _internal_media_artist() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_media_artist( + const std::string& value); + std::string* _internal_mutable_media_artist(); + + public: + // string album_art_url = 16; + void clear_album_art_url() ; + const std::string& album_art_url() const; + template + void set_album_art_url(Arg_&& arg, Args_... args); + std::string* mutable_album_art_url(); + PROTOBUF_NODISCARD std::string* release_album_art_url(); + void set_allocated_album_art_url(std::string* value); + + private: + const std::string& _internal_album_art_url() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_album_art_url( + const std::string& value); + std::string* _internal_mutable_album_art_url(); + + public: + // .NSPanelEntityState.MediaPlayer.SourceSelection player_sources = 18; + bool has_player_sources() const; + void clear_player_sources() ; + const ::NSPanelEntityState_MediaPlayer_SourceSelection& player_sources() const; + PROTOBUF_NODISCARD ::NSPanelEntityState_MediaPlayer_SourceSelection* release_player_sources(); + ::NSPanelEntityState_MediaPlayer_SourceSelection* mutable_player_sources(); + void set_allocated_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value); + void unsafe_arena_set_allocated_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value); + ::NSPanelEntityState_MediaPlayer_SourceSelection* unsafe_arena_release_player_sources(); + + private: + const ::NSPanelEntityState_MediaPlayer_SourceSelection& _internal_player_sources() const; + ::NSPanelEntityState_MediaPlayer_SourceSelection* _internal_mutable_player_sources(); + + public: + // .NSPanelEntityState.MediaPlayer.SourceSelection source_player_sources = 19; + bool has_source_player_sources() const; + void clear_source_player_sources() ; + const ::NSPanelEntityState_MediaPlayer_SourceSelection& source_player_sources() const; + PROTOBUF_NODISCARD ::NSPanelEntityState_MediaPlayer_SourceSelection* release_source_player_sources(); + ::NSPanelEntityState_MediaPlayer_SourceSelection* mutable_source_player_sources(); + void set_allocated_source_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value); + void unsafe_arena_set_allocated_source_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value); + ::NSPanelEntityState_MediaPlayer_SourceSelection* unsafe_arena_release_source_player_sources(); + + private: + const ::NSPanelEntityState_MediaPlayer_SourceSelection& _internal_source_player_sources() const; + ::NSPanelEntityState_MediaPlayer_SourceSelection* _internal_mutable_source_player_sources(); + + public: + // int32 media_player_id = 1; + void clear_media_player_id() ; + ::int32_t media_player_id() const; + void set_media_player_id(::int32_t value); + + private: + ::int32_t _internal_media_player_id() const; + void _internal_set_media_player_id(::int32_t value); + + public: + // .NSPanelEntityState.MediaPlayer.PlaybackState state = 3; + void clear_state() ; + ::NSPanelEntityState_MediaPlayer_PlaybackState state() const; + void set_state(::NSPanelEntityState_MediaPlayer_PlaybackState value); + + private: + ::NSPanelEntityState_MediaPlayer_PlaybackState _internal_state() const; + void _internal_set_state(::NSPanelEntityState_MediaPlayer_PlaybackState value); + + public: + // int32 volume = 6; + void clear_volume() ; + ::int32_t volume() const; + void set_volume(::int32_t value); + + private: + ::int32_t _internal_volume() const; + void _internal_set_volume(::int32_t value); + + public: + // int32 source_volume = 9; + void clear_source_volume() ; + ::int32_t source_volume() const; + void set_source_volume(::int32_t value); + + private: + ::int32_t _internal_source_volume() const; + void _internal_set_source_volume(::int32_t value); + + public: + // bool is_muted = 7; + void clear_is_muted() ; + bool is_muted() const; + void set_is_muted(bool value); + + private: + bool _internal_is_muted() const; + void _internal_set_is_muted(bool value); + + public: + // bool has_source_volume = 8; + void clear_has_source_volume() ; + bool has_source_volume() const; + void set_has_source_volume(bool value); + + private: + bool _internal_has_source_volume() const; + void _internal_set_has_source_volume(bool value); + + public: + // bool can_play = 10; + void clear_can_play() ; + bool can_play() const; + void set_can_play(bool value); + + private: + bool _internal_can_play() const; + void _internal_set_can_play(bool value); + + public: + // bool can_pause = 11; + void clear_can_pause() ; + bool can_pause() const; + void set_can_pause(bool value); + + private: + bool _internal_can_pause() const; + void _internal_set_can_pause(bool value); + + public: + // bool can_next_track = 12; + void clear_can_next_track() ; + bool can_next_track() const; + void set_can_next_track(bool value); + private: - int _internal_options_size() const; + bool _internal_can_next_track() const; + void _internal_set_can_next_track(bool value); public: - void clear_options() ; - ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue* mutable_options(int index); - ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>* mutable_options(); + // bool can_previous_track = 13; + void clear_can_previous_track() ; + bool can_previous_track() const; + void set_can_previous_track(bool value); private: - const ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>& _internal_options() const; - ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>* _internal_mutable_options(); + bool _internal_can_previous_track() const; + void _internal_set_can_previous_track(bool value); + public: - const ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue& options(int index) const; - ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue* add_options(); - const ::google::protobuf::RepeatedPtrField<::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue>& options() const; - // string name = 1; - void clear_name() ; - const std::string& name() const; - template - void set_name(Arg_&& arg, Args_... args); - std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); - void set_allocated_name(std::string* value); + // bool can_set_volume = 14; + void clear_can_set_volume() ; + bool can_set_volume() const; + void set_can_set_volume(bool value); private: - const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); - std::string* _internal_mutable_name(); + bool _internal_can_set_volume() const; + void _internal_set_can_set_volume(bool value); public: - // string current_value = 2; - void clear_current_value() ; - const std::string& current_value() const; - template - void set_current_value(Arg_&& arg, Args_... args); - std::string* mutable_current_value(); - PROTOBUF_NODISCARD std::string* release_current_value(); - void set_allocated_current_value(std::string* value); + // bool can_mute = 15; + void clear_can_mute() ; + bool can_mute() const; + void set_can_mute(bool value); private: - const std::string& _internal_current_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_current_value( - const std::string& value); - std::string* _internal_mutable_current_value(); + bool _internal_can_mute() const; + void _internal_set_can_mute(bool value); public: - // string current_icon = 3; - void clear_current_icon() ; - const std::string& current_icon() const; - template - void set_current_icon(Arg_&& arg, Args_... args); - std::string* mutable_current_icon(); - PROTOBUF_NODISCARD std::string* release_current_icon(); - void set_allocated_current_icon(std::string* value); + // int32 volume_step = 17; + void clear_volume_step() ; + ::int32_t volume_step() const; + void set_volume_step(::int32_t value); private: - const std::string& _internal_current_icon() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_current_icon( - const std::string& value); - std::string* _internal_mutable_current_icon(); + ::int32_t _internal_volume_step() const; + void _internal_set_volume_step(::int32_t value); public: - // @@protoc_insertion_point(class_scope:NSPanelEntityState.Thermostat.ThermostatOption) + // @@protoc_insertion_point(class_scope:NSPanelEntityState.MediaPlayer) private: class _Internal; friend class ::google::protobuf::internal::TcParser; static const ::google::protobuf::internal::TcParseTable< - 2, 4, 1, - 84, 2> + 5, 19, 2, + 95, 2> _table_; static constexpr const void* _raw_default_instance_ = - &_NSPanelEntityState_Thermostat_ThermostatOption_default_instance_; + &_NSPanelEntityState_MediaPlayer_default_instance_; friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; @@ -1280,12 +1522,28 @@ class NSPanelEntityState_Thermostat_ThermostatOption final : public ::google::pr ::google::protobuf::Arena* arena); inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, - const NSPanelEntityState_Thermostat_ThermostatOption& from_msg); - ::google::protobuf::RepeatedPtrField< ::NSPanelEntityState_Thermostat_ThermostatOption_ThermostatOptionValue > options_; - ::google::protobuf::internal::ArenaStringPtr name_; - ::google::protobuf::internal::ArenaStringPtr current_value_; - ::google::protobuf::internal::ArenaStringPtr current_icon_; + const NSPanelEntityState_MediaPlayer& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr name_; + ::google::protobuf::internal::ArenaStringPtr media_title_; + ::google::protobuf::internal::ArenaStringPtr media_artist_; + ::google::protobuf::internal::ArenaStringPtr album_art_url_; + ::NSPanelEntityState_MediaPlayer_SourceSelection* player_sources_; + ::NSPanelEntityState_MediaPlayer_SourceSelection* source_player_sources_; + ::int32_t media_player_id_; + int state_; + ::int32_t volume_; + ::int32_t source_volume_; + bool is_muted_; + bool has_source_volume_; + bool can_play_; + bool can_pause_; + bool can_next_track_; + bool can_previous_track_; + bool can_set_volume_; + bool can_mute_; + ::int32_t volume_step_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; @@ -1611,7 +1869,7 @@ class NSPanelEntityState final : public ::google::protobuf::Message return reinterpret_cast( &_NSPanelEntityState_default_instance_); } - static constexpr int kIndexInFileMessages = 5; + static constexpr int kIndexInFileMessages = 6; friend void swap(NSPanelEntityState& a, NSPanelEntityState& b) { a.Swap(&b); } inline void Swap(NSPanelEntityState* other) { if (other == this) return; @@ -2578,6 +2836,184 @@ NSPanelEntityState_Thermostat::_internal_mutable_options() { // ------------------------------------------------------------------- +// NSPanelEntityState_MediaPlayer_SourceSelection + +// repeated string sources = 1; +inline int NSPanelEntityState_MediaPlayer_SourceSelection::_internal_sources_size() const { + return _internal_sources().size(); +} +inline int NSPanelEntityState_MediaPlayer_SourceSelection::sources_size() const { + return _internal_sources_size(); +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::clear_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sources_.Clear(); +} +inline std::string* NSPanelEntityState_MediaPlayer_SourceSelection::add_sources() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + std::string* _s = _internal_mutable_sources()->Add(); + // @@protoc_insertion_point(field_add_mutable:NSPanelEntityState.MediaPlayer.SourceSelection.sources) + return _s; +} +inline const std::string& NSPanelEntityState_MediaPlayer_SourceSelection::sources(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelEntityState.MediaPlayer.SourceSelection.sources) + return _internal_sources().Get(index); +} +inline std::string* NSPanelEntityState_MediaPlayer_SourceSelection::mutable_sources(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:NSPanelEntityState.MediaPlayer.SourceSelection.sources) + return _internal_mutable_sources()->Mutable(index); +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_sources(int index, const std::string& value) { + _internal_mutable_sources()->Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_sources(int index, std::string&& value) { + _internal_mutable_sources()->Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_sources(int index, const char* value) { + ABSL_DCHECK(value != nullptr); + _internal_mutable_sources()->Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_sources(int index, const char* value, + std::size_t size) { + _internal_mutable_sources()->Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_sources(int index, absl::string_view value) { + _internal_mutable_sources()->Mutable(index)->assign( + value.data(), value.size()); + // @@protoc_insertion_point(field_set_string_piece:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::add_sources(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_sources()->Add()->assign(value); + // @@protoc_insertion_point(field_add:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::add_sources(std::string&& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_sources()->Add(std::move(value)); + // @@protoc_insertion_point(field_add:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::add_sources(const char* value) { + ABSL_DCHECK(value != nullptr); + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_sources()->Add()->assign(value); + // @@protoc_insertion_point(field_add_char:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::add_sources(const char* value, std::size_t size) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_sources()->Add()->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::add_sources(absl::string_view value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _internal_mutable_sources()->Add()->assign(value.data(), + value.size()); + // @@protoc_insertion_point(field_add_string_piece:NSPanelEntityState.MediaPlayer.SourceSelection.sources) +} +inline const ::google::protobuf::RepeatedPtrField& +NSPanelEntityState_MediaPlayer_SourceSelection::sources() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:NSPanelEntityState.MediaPlayer.SourceSelection.sources) + return _internal_sources(); +} +inline ::google::protobuf::RepeatedPtrField* +NSPanelEntityState_MediaPlayer_SourceSelection::mutable_sources() ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:NSPanelEntityState.MediaPlayer.SourceSelection.sources) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_sources(); +} +inline const ::google::protobuf::RepeatedPtrField& +NSPanelEntityState_MediaPlayer_SourceSelection::_internal_sources() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.sources_; +} +inline ::google::protobuf::RepeatedPtrField* +NSPanelEntityState_MediaPlayer_SourceSelection::_internal_mutable_sources() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.sources_; +} + +// string current_source = 2; +inline void NSPanelEntityState_MediaPlayer_SourceSelection::clear_current_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.current_source_.ClearToEmpty(); +} +inline const std::string& NSPanelEntityState_MediaPlayer_SourceSelection::current_source() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelEntityState.MediaPlayer.SourceSelection.current_source) + return _internal_current_source(); +} +template +inline PROTOBUF_ALWAYS_INLINE void NSPanelEntityState_MediaPlayer_SourceSelection::set_current_source(Arg_&& arg, + Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.current_source_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:NSPanelEntityState.MediaPlayer.SourceSelection.current_source) +} +inline std::string* NSPanelEntityState_MediaPlayer_SourceSelection::mutable_current_source() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_current_source(); + // @@protoc_insertion_point(field_mutable:NSPanelEntityState.MediaPlayer.SourceSelection.current_source) + return _s; +} +inline const std::string& NSPanelEntityState_MediaPlayer_SourceSelection::_internal_current_source() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.current_source_.Get(); +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::_internal_set_current_source(const std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.current_source_.Set(value, GetArena()); +} +inline std::string* NSPanelEntityState_MediaPlayer_SourceSelection::_internal_mutable_current_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.current_source_.Mutable( GetArena()); +} +inline std::string* NSPanelEntityState_MediaPlayer_SourceSelection::release_current_source() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:NSPanelEntityState.MediaPlayer.SourceSelection.current_source) + return _impl_.current_source_.Release(); +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_allocated_current_source(std::string* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.current_source_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.current_source_.IsDefault()) { + _impl_.current_source_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:NSPanelEntityState.MediaPlayer.SourceSelection.current_source) +} + +// bool can_select = 3; +inline void NSPanelEntityState_MediaPlayer_SourceSelection::clear_can_select() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.can_select_ = false; +} +inline bool NSPanelEntityState_MediaPlayer_SourceSelection::can_select() const { + // @@protoc_insertion_point(field_get:NSPanelEntityState.MediaPlayer.SourceSelection.can_select) + return _internal_can_select(); +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::set_can_select(bool value) { + _internal_set_can_select(value); + // @@protoc_insertion_point(field_set:NSPanelEntityState.MediaPlayer.SourceSelection.can_select) +} +inline bool NSPanelEntityState_MediaPlayer_SourceSelection::_internal_can_select() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.can_select_; +} +inline void NSPanelEntityState_MediaPlayer_SourceSelection::_internal_set_can_select(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.can_select_ = value; +} + +// ------------------------------------------------------------------- + // NSPanelEntityState_MediaPlayer // int32 media_player_id = 1; @@ -3066,6 +3502,198 @@ inline void NSPanelEntityState_MediaPlayer::_internal_set_volume_step(::int32_t _impl_.volume_step_ = value; } +// .NSPanelEntityState.MediaPlayer.SourceSelection player_sources = 18; +inline bool NSPanelEntityState_MediaPlayer::has_player_sources() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + PROTOBUF_ASSUME(!value || _impl_.player_sources_ != nullptr); + return value; +} +inline void NSPanelEntityState_MediaPlayer::clear_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.player_sources_ != nullptr) _impl_.player_sources_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const ::NSPanelEntityState_MediaPlayer_SourceSelection& NSPanelEntityState_MediaPlayer::_internal_player_sources() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::NSPanelEntityState_MediaPlayer_SourceSelection* p = _impl_.player_sources_; + return p != nullptr ? *p : reinterpret_cast(::_NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_); +} +inline const ::NSPanelEntityState_MediaPlayer_SourceSelection& NSPanelEntityState_MediaPlayer::player_sources() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelEntityState.MediaPlayer.player_sources) + return _internal_player_sources(); +} +inline void NSPanelEntityState_MediaPlayer::unsafe_arena_set_allocated_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.player_sources_); + } + _impl_.player_sources_ = reinterpret_cast<::NSPanelEntityState_MediaPlayer_SourceSelection*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:NSPanelEntityState.MediaPlayer.player_sources) +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::release_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000001u; + ::NSPanelEntityState_MediaPlayer_SourceSelection* released = _impl_.player_sources_; + _impl_.player_sources_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::unsafe_arena_release_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:NSPanelEntityState.MediaPlayer.player_sources) + + _impl_._has_bits_[0] &= ~0x00000001u; + ::NSPanelEntityState_MediaPlayer_SourceSelection* temp = _impl_.player_sources_; + _impl_.player_sources_ = nullptr; + return temp; +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::_internal_mutable_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.player_sources_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::NSPanelEntityState_MediaPlayer_SourceSelection>(GetArena()); + _impl_.player_sources_ = reinterpret_cast<::NSPanelEntityState_MediaPlayer_SourceSelection*>(p); + } + return _impl_.player_sources_; +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::mutable_player_sources() ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000001u; + ::NSPanelEntityState_MediaPlayer_SourceSelection* _msg = _internal_mutable_player_sources(); + // @@protoc_insertion_point(field_mutable:NSPanelEntityState.MediaPlayer.player_sources) + return _msg; +} +inline void NSPanelEntityState_MediaPlayer::set_allocated_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete (_impl_.player_sources_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + + _impl_.player_sources_ = reinterpret_cast<::NSPanelEntityState_MediaPlayer_SourceSelection*>(value); + // @@protoc_insertion_point(field_set_allocated:NSPanelEntityState.MediaPlayer.player_sources) +} + +// .NSPanelEntityState.MediaPlayer.SourceSelection source_player_sources = 19; +inline bool NSPanelEntityState_MediaPlayer::has_source_player_sources() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.source_player_sources_ != nullptr); + return value; +} +inline void NSPanelEntityState_MediaPlayer::clear_source_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.source_player_sources_ != nullptr) _impl_.source_player_sources_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::NSPanelEntityState_MediaPlayer_SourceSelection& NSPanelEntityState_MediaPlayer::_internal_source_player_sources() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::NSPanelEntityState_MediaPlayer_SourceSelection* p = _impl_.source_player_sources_; + return p != nullptr ? *p : reinterpret_cast(::_NSPanelEntityState_MediaPlayer_SourceSelection_default_instance_); +} +inline const ::NSPanelEntityState_MediaPlayer_SourceSelection& NSPanelEntityState_MediaPlayer::source_player_sources() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:NSPanelEntityState.MediaPlayer.source_player_sources) + return _internal_source_player_sources(); +} +inline void NSPanelEntityState_MediaPlayer::unsafe_arena_set_allocated_source_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.source_player_sources_); + } + _impl_.source_player_sources_ = reinterpret_cast<::NSPanelEntityState_MediaPlayer_SourceSelection*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:NSPanelEntityState.MediaPlayer.source_player_sources) +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::release_source_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000002u; + ::NSPanelEntityState_MediaPlayer_SourceSelection* released = _impl_.source_player_sources_; + _impl_.source_player_sources_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::unsafe_arena_release_source_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:NSPanelEntityState.MediaPlayer.source_player_sources) + + _impl_._has_bits_[0] &= ~0x00000002u; + ::NSPanelEntityState_MediaPlayer_SourceSelection* temp = _impl_.source_player_sources_; + _impl_.source_player_sources_ = nullptr; + return temp; +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::_internal_mutable_source_player_sources() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.source_player_sources_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::NSPanelEntityState_MediaPlayer_SourceSelection>(GetArena()); + _impl_.source_player_sources_ = reinterpret_cast<::NSPanelEntityState_MediaPlayer_SourceSelection*>(p); + } + return _impl_.source_player_sources_; +} +inline ::NSPanelEntityState_MediaPlayer_SourceSelection* NSPanelEntityState_MediaPlayer::mutable_source_player_sources() ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000002u; + ::NSPanelEntityState_MediaPlayer_SourceSelection* _msg = _internal_mutable_source_player_sources(); + // @@protoc_insertion_point(field_mutable:NSPanelEntityState.MediaPlayer.source_player_sources) + return _msg; +} +inline void NSPanelEntityState_MediaPlayer::set_allocated_source_player_sources(::NSPanelEntityState_MediaPlayer_SourceSelection* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete (_impl_.source_player_sources_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + + _impl_.source_player_sources_ = reinterpret_cast<::NSPanelEntityState_MediaPlayer_SourceSelection*>(value); + // @@protoc_insertion_point(field_set_allocated:NSPanelEntityState.MediaPlayer.source_player_sources) +} + // ------------------------------------------------------------------- // NSPanelEntityState diff --git a/docker/protobuf/protobuf_nspanel.proto b/docker/protobuf/protobuf_nspanel.proto index 78fc5a4a..79934353 100644 --- a/docker/protobuf/protobuf_nspanel.proto +++ b/docker/protobuf/protobuf_nspanel.proto @@ -267,6 +267,9 @@ message NSPanelMQTTManagerCommand { int32 source_volume = 6; // Volume in 0-100% bool has_muted = 7; bool muted = 8; + // Name of a source to select, as sent in the state's source lists. Empty means no change. + string select_player_source = 9; + string select_source_player_source = 10; } oneof CommandData { diff --git a/docker/protobuf/protobuf_nspanel_entity.proto b/docker/protobuf/protobuf_nspanel_entity.proto index 0cbe4322..5c04867a 100644 --- a/docker/protobuf/protobuf_nspanel_entity.proto +++ b/docker/protobuf/protobuf_nspanel_entity.proto @@ -84,6 +84,21 @@ message NSPanelEntityState { // How much one volume up/down press changes the volume and source volume, in 1-100%. int32 volume_step = 17; + + message SourceSelection { + repeated string sources = 1; + // Empty if unknown. Not every player reports its current source, and it + // is not always one of the listed sources. + string current_source = 2; + bool can_select = 3; + } + + // Sources (inputs) of this player. + SourceSelection player_sources = 18; + // Sources of the source player feeding this player, if it has one (see + // source_volume). Unset when there is no source player. Changes completely + // when the player switches to another source. + SourceSelection source_player_sources = 19; } oneof entity { diff --git a/protobuf_firmware/protobuf_nspanel.pb-c.c b/protobuf_firmware/protobuf_nspanel.pb-c.c index 700dd92f..ee780b2b 100644 --- a/protobuf_firmware/protobuf_nspanel.pb-c.c +++ b/protobuf_firmware/protobuf_nspanel.pb-c.c @@ -2628,7 +2628,7 @@ const ProtobufCEnumDescriptor nspanel_mqttmanager_command__media_player_command_ nspanel_mqttmanager_command__media_player_command__playback_action__value_ranges, NULL,NULL,NULL,NULL /* reserved[1234] */ }; -static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__media_player_command__field_descriptors[8] = +static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__media_player_command__field_descriptors[10] = { { "media_player_id", @@ -2726,6 +2726,30 @@ static const ProtobufCFieldDescriptor nspanel_mqttmanager_command__media_player_ 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "select_player_source", + 9, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(NSPanelMQTTManagerCommand__MediaPlayerCommand, select_player_source), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "select_source_player_source", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(NSPanelMQTTManagerCommand__MediaPlayerCommand, select_source_player_source), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned nspanel_mqttmanager_command__media_player_command__field_indices_by_name[] = { 6, /* field[6] = has_muted */ @@ -2734,13 +2758,15 @@ static const unsigned nspanel_mqttmanager_command__media_player_command__field_i 0, /* field[0] = media_player_id */ 7, /* field[7] = muted */ 1, /* field[1] = playback_action */ + 8, /* field[8] = select_player_source */ + 9, /* field[9] = select_source_player_source */ 5, /* field[5] = source_volume */ 3, /* field[3] = volume */ }; static const ProtobufCIntRange nspanel_mqttmanager_command__media_player_command__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 8 } + { 0, 10 } }; const ProtobufCMessageDescriptor nspanel_mqttmanager_command__media_player_command__descriptor = { @@ -2750,7 +2776,7 @@ const ProtobufCMessageDescriptor nspanel_mqttmanager_command__media_player_comma "NSPanelMQTTManagerCommand__MediaPlayerCommand", "", sizeof(NSPanelMQTTManagerCommand__MediaPlayerCommand), - 8, + 10, nspanel_mqttmanager_command__media_player_command__field_descriptors, nspanel_mqttmanager_command__media_player_command__field_indices_by_name, 1, nspanel_mqttmanager_command__media_player_command__number_ranges, diff --git a/protobuf_firmware/protobuf_nspanel.pb-c.h b/protobuf_firmware/protobuf_nspanel.pb-c.h index 54158df8..e290525b 100644 --- a/protobuf_firmware/protobuf_nspanel.pb-c.h +++ b/protobuf_firmware/protobuf_nspanel.pb-c.h @@ -461,10 +461,15 @@ struct NSPanelMQTTManagerCommand__MediaPlayerCommand int32_t source_volume; protobuf_c_boolean has_muted; protobuf_c_boolean muted; + /* + * Name of a source to select, as sent in the state's source lists. Empty means no change. + */ + char *select_player_source; + char *select_source_player_source; }; #define NSPANEL_MQTTMANAGER_COMMAND__MEDIA_PLAYER_COMMAND__INIT \ { PROTOBUF_C_MESSAGE_INIT (&nspanel_mqttmanager_command__media_player_command__descriptor) \ - , 0, NSPANEL_MQTTMANAGER_COMMAND__MEDIA_PLAYER_COMMAND__PLAYBACK_ACTION__NONE, 0, 0, 0, 0, 0, 0 } + , 0, NSPANEL_MQTTMANAGER_COMMAND__MEDIA_PLAYER_COMMAND__PLAYBACK_ACTION__NONE, 0, 0, 0, 0, 0, 0, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string } typedef enum { diff --git a/protobuf_firmware/protobuf_nspanel_entity.pb-c.c b/protobuf_firmware/protobuf_nspanel_entity.pb-c.c index 4776cf1e..19b23dd8 100644 --- a/protobuf_firmware/protobuf_nspanel_entity.pb-c.c +++ b/protobuf_firmware/protobuf_nspanel_entity.pb-c.c @@ -31,6 +31,12 @@ void nspanel_entity_state__thermostat__init static const NSPanelEntityState__Thermostat init_value = NSPANEL_ENTITY_STATE__THERMOSTAT__INIT; *message = init_value; } +void nspanel_entity_state__media_player__source_selection__init + (NSPanelEntityState__MediaPlayer__SourceSelection *message) +{ + static const NSPanelEntityState__MediaPlayer__SourceSelection init_value = NSPANEL_ENTITY_STATE__MEDIA_PLAYER__SOURCE_SELECTION__INIT; + *message = init_value; +} void nspanel_entity_state__media_player__init (NSPanelEntityState__MediaPlayer *message) { @@ -509,6 +515,70 @@ const ProtobufCMessageDescriptor nspanel_entity_state__thermostat__descriptor = (ProtobufCMessageInit) nspanel_entity_state__thermostat__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor nspanel_entity_state__media_player__source_selection__field_descriptors[3] = +{ + { + "sources", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_STRING, + offsetof(NSPanelEntityState__MediaPlayer__SourceSelection, n_sources), + offsetof(NSPanelEntityState__MediaPlayer__SourceSelection, sources), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "current_source", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(NSPanelEntityState__MediaPlayer__SourceSelection, current_source), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "can_select", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(NSPanelEntityState__MediaPlayer__SourceSelection, can_select), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned nspanel_entity_state__media_player__source_selection__field_indices_by_name[] = { + 2, /* field[2] = can_select */ + 1, /* field[1] = current_source */ + 0, /* field[0] = sources */ +}; +static const ProtobufCIntRange nspanel_entity_state__media_player__source_selection__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 3 } +}; +const ProtobufCMessageDescriptor nspanel_entity_state__media_player__source_selection__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "NSPanelEntityState.MediaPlayer.SourceSelection", + "SourceSelection", + "NSPanelEntityState__MediaPlayer__SourceSelection", + "", + sizeof(NSPanelEntityState__MediaPlayer__SourceSelection), + 3, + nspanel_entity_state__media_player__source_selection__field_descriptors, + nspanel_entity_state__media_player__source_selection__field_indices_by_name, + 1, nspanel_entity_state__media_player__source_selection__number_ranges, + (ProtobufCMessageInit) nspanel_entity_state__media_player__source_selection__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCEnumValue nspanel_entity_state__media_player__playback_state__enum_values_by_number[7] = { { "UNKNOWN", "NSPANEL_ENTITY_STATE__MEDIA_PLAYER__PLAYBACK_STATE__UNKNOWN", 0 }, @@ -547,7 +617,7 @@ const ProtobufCEnumDescriptor nspanel_entity_state__media_player__playback_state nspanel_entity_state__media_player__playback_state__value_ranges, NULL,NULL,NULL,NULL /* reserved[1234] */ }; -static const ProtobufCFieldDescriptor nspanel_entity_state__media_player__field_descriptors[16] = +static const ProtobufCFieldDescriptor nspanel_entity_state__media_player__field_descriptors[19] = { { "media_player_id", @@ -741,6 +811,42 @@ static const ProtobufCFieldDescriptor nspanel_entity_state__media_player__field_ 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "volume_step", + 17, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(NSPanelEntityState__MediaPlayer, volume_step), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "player_sources", + 18, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(NSPanelEntityState__MediaPlayer, player_sources), + &nspanel_entity_state__media_player__source_selection__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "source_player_sources", + 19, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(NSPanelEntityState__MediaPlayer, source_player_sources), + &nspanel_entity_state__media_player__source_selection__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned nspanel_entity_state__media_player__field_indices_by_name[] = { 15, /* field[15] = album_art_url */ @@ -756,14 +862,17 @@ static const unsigned nspanel_entity_state__media_player__field_indices_by_name[ 0, /* field[0] = media_player_id */ 3, /* field[3] = media_title */ 1, /* field[1] = name */ + 17, /* field[17] = player_sources */ + 18, /* field[18] = source_player_sources */ 8, /* field[8] = source_volume */ 2, /* field[2] = state */ 5, /* field[5] = volume */ + 16, /* field[16] = volume_step */ }; static const ProtobufCIntRange nspanel_entity_state__media_player__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 16 } + { 0, 19 } }; const ProtobufCMessageDescriptor nspanel_entity_state__media_player__descriptor = { @@ -773,7 +882,7 @@ const ProtobufCMessageDescriptor nspanel_entity_state__media_player__descriptor "NSPanelEntityState__MediaPlayer", "", sizeof(NSPanelEntityState__MediaPlayer), - 16, + 19, nspanel_entity_state__media_player__field_descriptors, nspanel_entity_state__media_player__field_indices_by_name, 1, nspanel_entity_state__media_player__number_ranges, diff --git a/protobuf_firmware/protobuf_nspanel_entity.pb-c.h b/protobuf_firmware/protobuf_nspanel_entity.pb-c.h index 4d2d1925..09242909 100644 --- a/protobuf_firmware/protobuf_nspanel_entity.pb-c.h +++ b/protobuf_firmware/protobuf_nspanel_entity.pb-c.h @@ -21,6 +21,7 @@ typedef struct NSPanelEntityState__Thermostat NSPanelEntityState__Thermostat; typedef struct NSPanelEntityState__Thermostat__ThermostatOption NSPanelEntityState__Thermostat__ThermostatOption; typedef struct NSPanelEntityState__Thermostat__ThermostatOption__ThermostatOptionValue NSPanelEntityState__Thermostat__ThermostatOption__ThermostatOptionValue; typedef struct NSPanelEntityState__MediaPlayer NSPanelEntityState__MediaPlayer; +typedef struct NSPanelEntityState__MediaPlayer__SourceSelection NSPanelEntityState__MediaPlayer__SourceSelection; /* --- enums --- */ @@ -104,6 +105,23 @@ struct NSPanelEntityState__Thermostat , 0, (char *)protobuf_c_empty_string, 0, 0, 0, 0, 0,NULL } +struct NSPanelEntityState__MediaPlayer__SourceSelection +{ + ProtobufCMessage base; + size_t n_sources; + char **sources; + /* + * Empty if unknown. Not every player reports its current source, and it + * is not always one of the listed sources. + */ + char *current_source; + protobuf_c_boolean can_select; +}; +#define NSPANEL_ENTITY_STATE__MEDIA_PLAYER__SOURCE_SELECTION__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&nspanel_entity_state__media_player__source_selection__descriptor) \ + , 0,NULL, (char *)protobuf_c_empty_string, 0 } + + struct NSPanelEntityState__MediaPlayer { ProtobufCMessage base; @@ -138,10 +156,24 @@ struct NSPanelEntityState__MediaPlayer * the panel can compare it with the last URL to tell when to fetch again. */ char *album_art_url; + /* + * How much one volume up/down press changes the volume and source volume, in 1-100%. + */ + int32_t volume_step; + /* + * Sources (inputs) of this player. + */ + NSPanelEntityState__MediaPlayer__SourceSelection *player_sources; + /* + * Sources of the source player feeding this player, if it has one (see + * source_volume). Unset when there is no source player. Changes completely + * when the player switches to another source. + */ + NSPanelEntityState__MediaPlayer__SourceSelection *source_player_sources; }; #define NSPANEL_ENTITY_STATE__MEDIA_PLAYER__INIT \ { PROTOBUF_C_MESSAGE_INIT (&nspanel_entity_state__media_player__descriptor) \ - , 0, (char *)protobuf_c_empty_string, NSPANEL_ENTITY_STATE__MEDIA_PLAYER__PLAYBACK_STATE__UNKNOWN, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (char *)protobuf_c_empty_string } + , 0, (char *)protobuf_c_empty_string, NSPANEL_ENTITY_STATE__MEDIA_PLAYER__PLAYBACK_STATE__UNKNOWN, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (char *)protobuf_c_empty_string, 0, NULL, NULL } typedef enum { @@ -179,6 +211,9 @@ void nspanel_entity_state__thermostat__thermostat_option__init /* NSPanelEntityState__Thermostat methods */ void nspanel_entity_state__thermostat__init (NSPanelEntityState__Thermostat *message); +/* NSPanelEntityState__MediaPlayer__SourceSelection methods */ +void nspanel_entity_state__media_player__source_selection__init + (NSPanelEntityState__MediaPlayer__SourceSelection *message); /* NSPanelEntityState__MediaPlayer methods */ void nspanel_entity_state__media_player__init (NSPanelEntityState__MediaPlayer *message); @@ -215,6 +250,9 @@ typedef void (*NSPanelEntityState__Thermostat__ThermostatOption_Closure) typedef void (*NSPanelEntityState__Thermostat_Closure) (const NSPanelEntityState__Thermostat *message, void *closure_data); +typedef void (*NSPanelEntityState__MediaPlayer__SourceSelection_Closure) + (const NSPanelEntityState__MediaPlayer__SourceSelection *message, + void *closure_data); typedef void (*NSPanelEntityState__MediaPlayer_Closure) (const NSPanelEntityState__MediaPlayer *message, void *closure_data); @@ -234,6 +272,7 @@ extern const ProtobufCMessageDescriptor nspanel_entity_state__thermostat__descri extern const ProtobufCMessageDescriptor nspanel_entity_state__thermostat__thermostat_option__descriptor; extern const ProtobufCMessageDescriptor nspanel_entity_state__thermostat__thermostat_option__thermostat_option_value__descriptor; extern const ProtobufCMessageDescriptor nspanel_entity_state__media_player__descriptor; +extern const ProtobufCMessageDescriptor nspanel_entity_state__media_player__source_selection__descriptor; extern const ProtobufCEnumDescriptor nspanel_entity_state__media_player__playback_state__descriptor; PROTOBUF_C__END_DECLS From d084dcdaab11679618aaf4e3e2545687c7d76b27 Mon Sep 17 00:00:00 2001 From: James Mulcahy Date: Wed, 7 Oct 2026 22:49:35 -0700 Subject: [PATCH 2/3] Send media player sources to NSPanels and let panels select them The manager now reads source_list and source from Home Assistant and sends them to the NSPanel with the media player state. Select commands from the panel call media_player.select_source. Sources of the source player (the player feeding this one, as set up with the source volume strategy) are sent too. Only the source_entity strategy used to follow the source player in Home Assistant, the player_attributes strategy only read attributes of the player itself and so could not see the source player's sources. Following the source player now lives in HomeAssistantSourcePlayer, which both strategies use. They only differ in where the source volume comes from. When the player switches source, the sources of the previous source player are dropped straight away rather than offered until the new ones arrive. The NSPanel can only receive 4 KB in one MQTT message, so at most 32 sources of up to 64 bytes each are sent per list. Longer names are shortened without splitting a UTF-8 character, and the shortened name the panel sends back is matched to the full one before selecting it. Co-Authored-By: Claude Opus 5.5 --- docker/MQTTManager/CMakeLists.txt | 2 +- .../home_assistant_media_player.cpp | 23 ++- .../home_assistant_media_player.hpp | 6 +- .../home_assistant_source_player.cpp | 168 ++++++++++++++++++ .../home_assistant_source_player.hpp | 88 +++++++++ .../home_assistant_source_volume.cpp | 152 ++++------------ .../home_assistant_source_volume.hpp | 43 +++-- .../include/media_player/media_player.cpp | 100 ++++++++++- .../include/media_player/media_player.hpp | 66 +++++++ 9 files changed, 498 insertions(+), 150 deletions(-) create mode 100644 docker/MQTTManager/include/media_player/home_assistant_source_player.cpp create mode 100644 docker/MQTTManager/include/media_player/home_assistant_source_player.hpp diff --git a/docker/MQTTManager/CMakeLists.txt b/docker/MQTTManager/CMakeLists.txt index 6a78036b..8504f034 100644 --- a/docker/MQTTManager/CMakeLists.txt +++ b/docker/MQTTManager/CMakeLists.txt @@ -109,7 +109,7 @@ set_target_properties(MQTTManager_Thermostat PROPERTIES PUBLIC_HEADER ${CMAKE_IN target_include_directories(MQTTManager_Thermostat PUBLIC ${CMAKE_INCLUDE_SRC_DIRECTORY}) target_link_libraries(MQTTManager_Thermostat MQTTManager_HomeAssistantManager MQTTManager_OpenhabManager spdlog::spdlog nlohmann_json::nlohmann_json MQTT_Manager Boost::boost MQTTManager_Entity Protobuf_MQTTManager MQTTManager_CommandManager gtest::gtest) -add_library(MQTTManager_MediaPlayer STATIC ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/media_player.cpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/media_player.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_media_player.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_media_player.cpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_source_volume.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_source_volume.cpp) +add_library(MQTTManager_MediaPlayer STATIC ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/media_player.cpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/media_player.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_media_player.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_media_player.cpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_source_volume.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_source_volume.cpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_source_player.hpp ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/home_assistant_source_player.cpp) set_target_properties(MQTTManager_MediaPlayer PROPERTIES PUBLIC_HEADER ${CMAKE_INCLUDE_SRC_DIRECTORY}/media_player/media_player.hpp) target_include_directories(MQTTManager_MediaPlayer PUBLIC ${CMAKE_INCLUDE_SRC_DIRECTORY}) target_link_libraries(MQTTManager_MediaPlayer MQTTManager_HomeAssistantManager MQTTManager_WebHelper spdlog::spdlog nlohmann_json::nlohmann_json MQTT_Manager Boost::boost MQTTManager_Entity Protobuf_MQTTManager MQTTManager_CommandManager gtest::gtest) diff --git a/docker/MQTTManager/include/media_player/home_assistant_media_player.cpp b/docker/MQTTManager/include/media_player/home_assistant_media_player.cpp index b54947e4..d0fdd1a2 100644 --- a/docker/MQTTManager/include/media_player/home_assistant_media_player.cpp +++ b/docker/MQTTManager/include/media_player/home_assistant_media_player.cpp @@ -1,6 +1,7 @@ #include "home_assistant_media_player.hpp" #include "database_manager/database_manager.hpp" #include "entity/entity.hpp" +#include "media_player/home_assistant_source_player.hpp" #include "media_player/home_assistant_source_volume.hpp" #include "media_player/media_player.hpp" #include "protobuf_nspanel_entity.pb.h" @@ -67,7 +68,7 @@ void HomeAssistantMediaPlayer::reload_config() { this->_create_source_volume_strategy(entity_data.value_or(nlohmann::json::object())); // The name or source volume might have changed, unchanged states are not sent again. - this->_update_source_volume_and_send_state(); + this->_update_source_player_and_send_state(); if (home_assistant_name_changed && !this->_home_assistant_name.empty()) { // This will also request the current state from Home Assistant. @@ -113,7 +114,7 @@ void HomeAssistantMediaPlayer::_create_source_volume_strategy(const nlohmann::js } auto strategy = std::shared_ptr(HomeAssistantSourceVolumeStrategy::create(this->_id, entity_data, [this]() { - this->_update_source_volume_and_send_state(); + this->_update_source_player_and_send_state(); })); nlohmann::json player_attributes; @@ -132,11 +133,12 @@ std::shared_ptr HomeAssistantMediaPlayer::_ge return this->_source_volume_strategy; } -void HomeAssistantMediaPlayer::_update_source_volume_and_send_state() { +void HomeAssistantMediaPlayer::_update_source_player_and_send_state() { auto strategy = this->_get_source_volume_strategy(); std::optional source_volume = strategy ? strategy->get_source_volume() : std::nullopt; this->_has_source_volume = source_volume.has_value(); this->_source_volume = source_volume.value_or(0); + this->_set_source_player_sources(strategy ? strategy->get_source_player_sources() : std::nullopt); this->send_state_update_to_nspanel(); } @@ -169,6 +171,7 @@ void HomeAssistantMediaPlayer::home_assistant_event_callback(nlohmann::json data // Entity was removed from Home Assistant. this->_state = NSPanelEntityState_MediaPlayer_PlaybackState_UNKNOWN; this->_set_album_art_source(""); + this->_set_player_sources(MediaPlayerSources()); } else { std::string new_state = new_state_data.contains("state") && new_state_data["state"].is_string() ? new_state_data["state"].get() : ""; if (new_state.compare("playing") == 0) { @@ -213,6 +216,7 @@ void HomeAssistantMediaPlayer::home_assistant_event_callback(nlohmann::json data this->_can_previous_track = supported_features & HomeAssistantMediaPlayer::feature_previous_track; this->_can_set_volume = supported_features & HomeAssistantMediaPlayer::feature_volume_set; this->_can_mute = supported_features & HomeAssistantMediaPlayer::feature_volume_mute; + this->_set_player_sources(HomeAssistantSourcePlayer::sources_from_attributes(attributes)); } std::shared_ptr strategy; @@ -229,7 +233,7 @@ void HomeAssistantMediaPlayer::home_assistant_event_callback(nlohmann::json data return; } - this->_update_source_volume_and_send_state(); + this->_update_source_player_and_send_state(); if (previous_icon_color != this->get_icon_color()) { this->_signal_entity_changed(); } @@ -310,3 +314,14 @@ bool HomeAssistantMediaPlayer::_download_album_art(const std::string &source, st void HomeAssistantMediaPlayer::set_muted(bool muted) { this->_call_service("volume_mute", {{"is_volume_muted", muted}}); } + +void HomeAssistantMediaPlayer::select_player_source(const std::string &source) { + this->_call_service("select_source", {{"source", source}}); +} + +void HomeAssistantMediaPlayer::select_source_player_source(const std::string &source) { + auto strategy = this->_get_source_volume_strategy(); + if (strategy) { + strategy->select_source_player_source(source); + } +} diff --git a/docker/MQTTManager/include/media_player/home_assistant_media_player.hpp b/docker/MQTTManager/include/media_player/home_assistant_media_player.hpp index f5c8a1c7..0b0c3da7 100644 --- a/docker/MQTTManager/include/media_player/home_assistant_media_player.hpp +++ b/docker/MQTTManager/include/media_player/home_assistant_media_player.hpp @@ -23,6 +23,8 @@ class HomeAssistantMediaPlayer : public MediaPlayerEntity { void set_volume(uint8_t volume); void set_source_volume(uint8_t volume); void set_muted(bool muted); + void select_player_source(const std::string &source); + void select_source_player_source(const std::string &source); protected: /** @@ -50,9 +52,9 @@ class HomeAssistantMediaPlayer : public MediaPlayerEntity { std::shared_ptr _get_source_volume_strategy(); /** - * Update source volume from the strategy and send the new state to the NSPanel. + * Update source volume and source player sources from the strategy and send the new state to the NSPanel. */ - void _update_source_volume_and_send_state(); + void _update_source_player_and_send_state(); /** * Call a "media_player" domain service in Home Assistant. diff --git a/docker/MQTTManager/include/media_player/home_assistant_source_player.cpp b/docker/MQTTManager/include/media_player/home_assistant_source_player.cpp new file mode 100644 index 00000000..84c955b0 --- /dev/null +++ b/docker/MQTTManager/include/media_player/home_assistant_source_player.cpp @@ -0,0 +1,168 @@ +#include "media_player/home_assistant_source_player.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +HomeAssistantSourcePlayer::HomeAssistantSourcePlayer(std::string source_entity_attribute, std::function on_change) { + this->_source_entity_attribute = source_entity_attribute; + this->_on_change = on_change; +} + +HomeAssistantSourcePlayer::~HomeAssistantSourcePlayer() { + std::lock_guard lock_guard(this->_mutex); + if (!this->_entity_id.empty()) { + HomeAssistantManager::detach_event_observer(this->_entity_id, boost::bind(&HomeAssistantSourcePlayer::home_assistant_event_callback, this, _1)); + } +} + +void HomeAssistantSourcePlayer::update_from_player_attributes(const nlohmann::json &attributes) { + std::string new_entity_id; + if (attributes.contains(this->_source_entity_attribute) && attributes[this->_source_entity_attribute].is_string()) { + new_entity_id = attributes[this->_source_entity_attribute]; + } + + std::string old_entity_id; + { + std::lock_guard lock_guard(this->_mutex); + if (new_entity_id.compare(this->_entity_id) == 0) { + return; + } + old_entity_id = this->_entity_id; + this->_entity_id = new_entity_id; + // Forget the previous source player straight away, so its sources are never offered for the new one. + this->_volume.reset(); + this->_sources = MediaPlayerSources(); + } + + SPDLOG_DEBUG("Media player source changed from '{}' to '{}'.", old_entity_id, new_entity_id); + if (!old_entity_id.empty()) { + HomeAssistantManager::detach_event_observer(old_entity_id, boost::bind(&HomeAssistantSourcePlayer::home_assistant_event_callback, this, _1)); + } + if (!new_entity_id.empty()) { + // Attaching an observer requests all states from Home Assistant, the current state of the source player will arrive through the event callback. + HomeAssistantManager::attach_event_observer(new_entity_id, boost::bind(&HomeAssistantSourcePlayer::home_assistant_event_callback, this, _1)); + } +} + +std::string HomeAssistantSourcePlayer::get_entity_id() { + std::lock_guard lock_guard(this->_mutex); + return this->_entity_id; +} + +std::optional HomeAssistantSourcePlayer::get_volume() { + std::lock_guard lock_guard(this->_mutex); + return this->_volume; +} + +std::optional HomeAssistantSourcePlayer::get_sources() { + std::lock_guard lock_guard(this->_mutex); + if (this->_entity_id.empty()) { + return std::nullopt; + } + return this->_sources; +} + +void HomeAssistantSourcePlayer::set_volume(uint8_t volume) { + std::string entity_id = this->get_entity_id(); + if (entity_id.empty()) { + SPDLOG_WARN("Received command to set source volume but the media player does not report a source entity."); + return; + } + HomeAssistantSourcePlayer::call_service(entity_id, "volume_set", {{"volume_level", volume / 100.0}}); +} + +void HomeAssistantSourcePlayer::select_source(const std::string &source) { + std::string entity_id = this->get_entity_id(); + if (entity_id.empty()) { + SPDLOG_WARN("Received command to select a source player source but the media player does not report a source entity."); + return; + } + HomeAssistantSourcePlayer::call_service(entity_id, "select_source", {{"source", source}}); +} + +void HomeAssistantSourcePlayer::home_assistant_event_callback(nlohmann::json event_data) { + try { + if (!event_data.contains("event") || !event_data["event"].contains("data")) { + return; + } + nlohmann::json data = event_data["event"]["data"]; + if (!data.contains("entity_id") || !data["entity_id"].is_string()) { + return; + } + + bool changed = false; + { + std::lock_guard lock_guard(this->_mutex); + if (data["entity_id"].get().compare(this->_entity_id) != 0) { + return; // Event for a previous source. + } + + std::optional new_volume = this->_volume; + MediaPlayerSources new_sources; + if (!data.contains("new_state") || data["new_state"].is_null()) { + new_volume.reset(); + } else if (data["new_state"].contains("attributes") && data["new_state"]["attributes"].is_object()) { + const nlohmann::json &attributes = data["new_state"]["attributes"]; + // Home Assistant does not report volume while a media player is off, keep the last known value in that case. + if (attributes.contains("volume_level")) { + new_volume = HomeAssistantSourcePlayer::volume_from_json(attributes["volume_level"]); + } + new_sources = HomeAssistantSourcePlayer::sources_from_attributes(attributes); + } + + changed = new_volume != this->_volume || new_sources != this->_sources; + this->_volume = new_volume; + this->_sources = std::move(new_sources); + } + + if (changed && this->_on_change) { + this->_on_change(); + } + } catch (std::exception &e) { + SPDLOG_ERROR("Caught exception during processing of media player source event. Error: {}", e.what()); + } +} + +MediaPlayerSources HomeAssistantSourcePlayer::sources_from_attributes(const nlohmann::json &attributes) { + MediaPlayerSources sources; + if (attributes.contains("source_list") && attributes["source_list"].is_array()) { + for (const nlohmann::json &source : attributes["source_list"]) { + if (source.is_string()) { + sources.sources.push_back(source); + } + } + } + if (attributes.contains("source") && attributes["source"].is_string()) { + sources.current_source = attributes["source"]; + } + uint32_t supported_features = 0; + if (attributes.contains("supported_features") && attributes["supported_features"].is_number_unsigned()) { + supported_features = attributes["supported_features"]; + } + sources.can_select = (supported_features & HomeAssistantSourcePlayer::feature_select_source) && !sources.sources.empty(); + return sources; +} + +std::optional HomeAssistantSourcePlayer::volume_from_json(const nlohmann::json &volume_level) { + if (!volume_level.is_number()) { + return std::nullopt; + } + return std::lround(std::clamp(volume_level.get(), 0.0, 1.0) * 100); +} + +void HomeAssistantSourcePlayer::call_service(const std::string &entity_id, const std::string &service, nlohmann::json service_data) { + nlohmann::json command = { + {"type", "call_service"}, + {"domain", "media_player"}, + {"target", {{"entity_id", entity_id}}}, + {"service", service}}; + if (!service_data.empty()) { + command["service_data"] = service_data; + } + HomeAssistantManager::send_json(command); +} diff --git a/docker/MQTTManager/include/media_player/home_assistant_source_player.hpp b/docker/MQTTManager/include/media_player/home_assistant_source_player.hpp new file mode 100644 index 00000000..78e8d1c3 --- /dev/null +++ b/docker/MQTTManager/include/media_player/home_assistant_source_player.hpp @@ -0,0 +1,88 @@ +#ifndef MQTT_MANAGER_HOME_ASSISTANT_SOURCE_PLAYER_HPP +#define MQTT_MANAGER_HOME_ASSISTANT_SOURCE_PLAYER_HPP + +#include "media_player/media_player.hpp" +#include +#include +#include +#include +#include +#include + +/** + * Follows the source player feeding a media player in Home Assistant. The media player reports the + * entity ID of its current source player in a state attribute, the source player is itself a media + * player in Home Assistant. + */ +class HomeAssistantSourcePlayer { +public: + /** + * @param source_entity_attribute: Media player state attribute holding the entity ID of the source player. + * @param on_change: Called when the source player changes state without the media player itself changing. + */ + HomeAssistantSourcePlayer(std::string source_entity_attribute, std::function on_change); + ~HomeAssistantSourcePlayer(); + + /** + * Process new state attributes of the media player. Follows the source player when it changes. + */ + void update_from_player_attributes(const nlohmann::json &attributes); + + /** + * Get the entity ID of the current source player, or an empty string if there is none. + */ + std::string get_entity_id(); + + /** + * Get the volume of the source player in 0-100%, if known. + */ + std::optional get_volume(); + + /** + * Get the sources of the source player, or nothing if there is no source player. + */ + std::optional get_sources(); + + /** + * Set the volume of the source player. + * @param volume: Volume in 0-100% + */ + void set_volume(uint8_t volume); + + /** + * Select a source of the source player. + */ + void select_source(const std::string &source); + + void home_assistant_event_callback(nlohmann::json event_data); + + /** + * Read the sources of a media player from its Home Assistant state attributes. + */ + static MediaPlayerSources sources_from_attributes(const nlohmann::json &attributes); + + /** + * Convert a Home Assistant volume level (0.0-1.0) to 0-100%. + * Home Assistant always reports volume_level as 0.0-1.0, whatever the device uses. 0-100 is only used towards the NSPanel. + */ + static std::optional volume_from_json(const nlohmann::json &volume_level); + + /** + * Call a "media_player" domain service in Home Assistant on the given entity. + */ + static void call_service(const std::string &entity_id, const std::string &service, nlohmann::json service_data = nlohmann::json::object()); + + // Media player feature flag from Home Assistant (MediaPlayerEntityFeature). + static constexpr uint32_t feature_select_source = 2048; + +private: + std::string _source_entity_attribute; + std::function _on_change; + + std::mutex _mutex; + std::string _entity_id; + std::optional _volume; + MediaPlayerSources _sources; +}; + +#endif // !MQTT_MANAGER_HOME_ASSISTANT_SOURCE_PLAYER_HPP diff --git a/docker/MQTTManager/include/media_player/home_assistant_source_volume.cpp b/docker/MQTTManager/include/media_player/home_assistant_source_volume.cpp index 0de8c5de..083b479a 100644 --- a/docker/MQTTManager/include/media_player/home_assistant_source_volume.cpp +++ b/docker/MQTTManager/include/media_player/home_assistant_source_volume.cpp @@ -1,8 +1,5 @@ #include "media_player/home_assistant_source_volume.hpp" -#include -#include -#include -#include +#include "media_player/home_assistant_source_player.hpp" #include #include #include @@ -29,7 +26,7 @@ std::unique_ptr HomeAssistantSourceVolumeStra if (source_entity_attribute.empty() || source_volume_attribute.empty()) { SPDLOG_ERROR("Media player {}: source volume strategy 'player_attributes' requires both a source entity attribute and a source volume attribute. Source volume will not be available.", media_player_id); } else { - return std::make_unique(source_entity_attribute, source_volume_attribute); + return std::make_unique(source_entity_attribute, source_volume_attribute, on_change); } } else if (strategy.compare("source_entity") == 0) { if (source_entity_attribute.empty()) { @@ -43,23 +40,6 @@ std::unique_ptr HomeAssistantSourceVolumeStra return std::make_unique(); } -std::optional HomeAssistantSourceVolumeStrategy::_volume_from_json(const nlohmann::json &volume_level) { - if (!volume_level.is_number()) { - return std::nullopt; - } - return std::lround(std::clamp(volume_level.get(), 0.0, 1.0) * 100); -} - -void HomeAssistantSourceVolumeStrategy::_send_volume_set(const std::string &entity_id, uint8_t volume) { - nlohmann::json command = { - {"type", "call_service"}, - {"domain", "media_player"}, - {"target", {{"entity_id", entity_id}}}, - {"service", "volume_set"}, - {"service_data", {{"volume_level", volume / 100.0}}}}; - HomeAssistantManager::send_json(command); -} - // No source volume void NoSourceVolumeStrategy::update_from_player_attributes([[maybe_unused]] const nlohmann::json &attributes) { @@ -73,24 +53,28 @@ void NoSourceVolumeStrategy::set_source_volume([[maybe_unused]] uint8_t volume) SPDLOG_WARN("Received command to set source volume but no source volume strategy is configured."); } +std::optional NoSourceVolumeStrategy::get_source_player_sources() { + return std::nullopt; +} + +void NoSourceVolumeStrategy::select_source_player_source([[maybe_unused]] const std::string &source) { + SPDLOG_WARN("Received command to select a source player source but no source volume strategy is configured."); +} + // Player attributes -PlayerAttributesSourceVolumeStrategy::PlayerAttributesSourceVolumeStrategy(std::string source_entity_attribute, std::string source_volume_attribute) { - this->_source_entity_attribute = source_entity_attribute; +PlayerAttributesSourceVolumeStrategy::PlayerAttributesSourceVolumeStrategy(std::string source_entity_attribute, std::string source_volume_attribute, std::function on_change) : _source_player(source_entity_attribute, on_change) { this->_source_volume_attribute = source_volume_attribute; } void PlayerAttributesSourceVolumeStrategy::update_from_player_attributes(const nlohmann::json &attributes) { + this->_source_player.update_from_player_attributes(attributes); + std::lock_guard lock_guard(this->_mutex); - this->_source_entity_id.clear(); this->_source_volume.reset(); - - if (attributes.contains(this->_source_entity_attribute) && attributes[this->_source_entity_attribute].is_string()) { - this->_source_entity_id = attributes[this->_source_entity_attribute]; - } // Only report a source volume if we also know where to send volume changes. - if (!this->_source_entity_id.empty() && attributes.contains(this->_source_volume_attribute)) { - this->_source_volume = HomeAssistantSourceVolumeStrategy::_volume_from_json(attributes[this->_source_volume_attribute]); + if (!this->_source_player.get_entity_id().empty() && attributes.contains(this->_source_volume_attribute)) { + this->_source_volume = HomeAssistantSourcePlayer::volume_from_json(attributes[this->_source_volume_attribute]); } } @@ -100,110 +84,38 @@ std::optional PlayerAttributesSourceVolumeStrategy::get_source_volume() } void PlayerAttributesSourceVolumeStrategy::set_source_volume(uint8_t volume) { - std::string source_entity_id; - { - std::lock_guard lock_guard(this->_mutex); - source_entity_id = this->_source_entity_id; - } - if (source_entity_id.empty()) { - SPDLOG_WARN("Received command to set source volume but the media player does not report a source entity."); - return; - } - HomeAssistantSourceVolumeStrategy::_send_volume_set(source_entity_id, volume); + this->_source_player.set_volume(volume); } -// Source entity - -SourceEntitySourceVolumeStrategy::SourceEntitySourceVolumeStrategy(std::string source_entity_attribute, std::function on_change) { - this->_source_entity_attribute = source_entity_attribute; - this->_on_change = on_change; +std::optional PlayerAttributesSourceVolumeStrategy::get_source_player_sources() { + return this->_source_player.get_sources(); } -SourceEntitySourceVolumeStrategy::~SourceEntitySourceVolumeStrategy() { - std::lock_guard lock_guard(this->_mutex); - if (!this->_source_entity_id.empty()) { - HomeAssistantManager::detach_event_observer(this->_source_entity_id, boost::bind(&SourceEntitySourceVolumeStrategy::home_assistant_event_callback, this, _1)); - } +void PlayerAttributesSourceVolumeStrategy::select_source_player_source(const std::string &source) { + this->_source_player.select_source(source); } -void SourceEntitySourceVolumeStrategy::update_from_player_attributes(const nlohmann::json &attributes) { - std::string new_source_entity_id; - if (attributes.contains(this->_source_entity_attribute) && attributes[this->_source_entity_attribute].is_string()) { - new_source_entity_id = attributes[this->_source_entity_attribute]; - } +// Source entity - std::string old_source_entity_id; - { - std::lock_guard lock_guard(this->_mutex); - if (new_source_entity_id.compare(this->_source_entity_id) == 0) { - return; - } - old_source_entity_id = this->_source_entity_id; - this->_source_entity_id = new_source_entity_id; - this->_source_volume.reset(); - } +SourceEntitySourceVolumeStrategy::SourceEntitySourceVolumeStrategy(std::string source_entity_attribute, std::function on_change) : _source_player(source_entity_attribute, on_change) { +} - SPDLOG_DEBUG("Media player source changed from '{}' to '{}'.", old_source_entity_id, new_source_entity_id); - if (!old_source_entity_id.empty()) { - HomeAssistantManager::detach_event_observer(old_source_entity_id, boost::bind(&SourceEntitySourceVolumeStrategy::home_assistant_event_callback, this, _1)); - } - if (!new_source_entity_id.empty()) { - // Attaching an observer requests all states from Home Assistant, the current source volume will arrive through the event callback. - HomeAssistantManager::attach_event_observer(new_source_entity_id, boost::bind(&SourceEntitySourceVolumeStrategy::home_assistant_event_callback, this, _1)); - } +void SourceEntitySourceVolumeStrategy::update_from_player_attributes(const nlohmann::json &attributes) { + this->_source_player.update_from_player_attributes(attributes); } std::optional SourceEntitySourceVolumeStrategy::get_source_volume() { - std::lock_guard lock_guard(this->_mutex); - return this->_source_volume; + return this->_source_player.get_volume(); } void SourceEntitySourceVolumeStrategy::set_source_volume(uint8_t volume) { - std::string source_entity_id; - { - std::lock_guard lock_guard(this->_mutex); - source_entity_id = this->_source_entity_id; - } - if (source_entity_id.empty()) { - SPDLOG_WARN("Received command to set source volume but the media player does not report a source entity."); - return; - } - HomeAssistantSourceVolumeStrategy::_send_volume_set(source_entity_id, volume); + this->_source_player.set_volume(volume); } -void SourceEntitySourceVolumeStrategy::home_assistant_event_callback(nlohmann::json event_data) { - try { - if (!event_data.contains("event") || !event_data["event"].contains("data")) { - return; - } - nlohmann::json data = event_data["event"]["data"]; - if (!data.contains("entity_id") || !data["entity_id"].is_string()) { - return; - } - - bool changed = false; - { - std::lock_guard lock_guard(this->_mutex); - if (data["entity_id"].get().compare(this->_source_entity_id) != 0) { - return; // Event for a previous source. - } - - std::optional new_volume = this->_source_volume; - if (!data.contains("new_state") || data["new_state"].is_null()) { - new_volume.reset(); - } else if (data["new_state"].contains("attributes") && data["new_state"]["attributes"].contains("volume_level")) { - new_volume = HomeAssistantSourceVolumeStrategy::_volume_from_json(data["new_state"]["attributes"]["volume_level"]); - } - // Home Assistant does not report volume while a media player is off, keep the last known value in that case. - - changed = new_volume != this->_source_volume; - this->_source_volume = new_volume; - } +std::optional SourceEntitySourceVolumeStrategy::get_source_player_sources() { + return this->_source_player.get_sources(); +} - if (changed && this->_on_change) { - this->_on_change(); - } - } catch (std::exception &e) { - SPDLOG_ERROR("Caught exception during processing of media player source event. Error: {}", e.what()); - } +void SourceEntitySourceVolumeStrategy::select_source_player_source(const std::string &source) { + this->_source_player.select_source(source); } diff --git a/docker/MQTTManager/include/media_player/home_assistant_source_volume.hpp b/docker/MQTTManager/include/media_player/home_assistant_source_volume.hpp index 1c76a152..538c0235 100644 --- a/docker/MQTTManager/include/media_player/home_assistant_source_volume.hpp +++ b/docker/MQTTManager/include/media_player/home_assistant_source_volume.hpp @@ -1,6 +1,8 @@ #ifndef MQTT_MANAGER_HOME_ASSISTANT_SOURCE_VOLUME_HPP #define MQTT_MANAGER_HOME_ASSISTANT_SOURCE_VOLUME_HPP +#include "media_player/home_assistant_source_player.hpp" +#include "media_player/media_player.hpp" #include #include #include @@ -13,6 +15,7 @@ * Some setups (for example multi-room audio matrices) have a separate volume for the source * feeding a media player. How that source and its volume are exposed in Home Assistant differs * between integrations, a strategy selected per media player decides how to handle it. + * The strategy also gives access to the sources of the source player. */ class HomeAssistantSourceVolumeStrategy { public: @@ -35,24 +38,22 @@ class HomeAssistantSourceVolumeStrategy { virtual void set_source_volume(uint8_t volume) = 0; /** - * Create the strategy selected for the media player. - * @param media_player_id: ID of the media player, used for logging. - * @param entity_data: The media player's entity_data from the DB. - * @param on_change: Called when the source volume changes without the media player itself changing. + * Get the sources of the source player currently feeding the media player, or nothing if there is no source player. */ - static std::unique_ptr create(uint32_t media_player_id, const nlohmann::json &entity_data, std::function on_change); + virtual std::optional get_source_player_sources() = 0; -protected: /** - * Convert a Home Assistant volume level (0.0-1.0) to 0-100%. - * Home Assistant always reports volume_level as 0.0-1.0, whatever the device uses. 0-100 is only used towards the NSPanel. + * Select a source of the source player currently feeding the media player. */ - static std::optional _volume_from_json(const nlohmann::json &volume_level); + virtual void select_source_player_source(const std::string &source) = 0; /** - * Set the volume of the given Home Assistant media player. + * Create the strategy selected for the media player. + * @param media_player_id: ID of the media player, used for logging. + * @param entity_data: The media player's entity_data from the DB. + * @param on_change: Called when the source volume or sources change without the media player itself changing. */ - static void _send_volume_set(const std::string &entity_id, uint8_t volume); + static std::unique_ptr create(uint32_t media_player_id, const nlohmann::json &entity_data, std::function on_change); }; /** @@ -63,6 +64,8 @@ class NoSourceVolumeStrategy : public HomeAssistantSourceVolumeStrategy { void update_from_player_attributes(const nlohmann::json &attributes); std::optional get_source_volume(); void set_source_volume(uint8_t volume); + std::optional get_source_player_sources(); + void select_source_player_source(const std::string &source); }; /** @@ -71,17 +74,18 @@ class NoSourceVolumeStrategy : public HomeAssistantSourceVolumeStrategy { */ class PlayerAttributesSourceVolumeStrategy : public HomeAssistantSourceVolumeStrategy { public: - PlayerAttributesSourceVolumeStrategy(std::string source_entity_attribute, std::string source_volume_attribute); + PlayerAttributesSourceVolumeStrategy(std::string source_entity_attribute, std::string source_volume_attribute, std::function on_change); void update_from_player_attributes(const nlohmann::json &attributes); std::optional get_source_volume(); void set_source_volume(uint8_t volume); + std::optional get_source_player_sources(); + void select_source_player_source(const std::string &source); private: - std::string _source_entity_attribute; std::string _source_volume_attribute; + HomeAssistantSourcePlayer _source_player; std::mutex _mutex; - std::string _source_entity_id; std::optional _source_volume; }; @@ -92,19 +96,14 @@ class PlayerAttributesSourceVolumeStrategy : public HomeAssistantSourceVolumeStr class SourceEntitySourceVolumeStrategy : public HomeAssistantSourceVolumeStrategy { public: SourceEntitySourceVolumeStrategy(std::string source_entity_attribute, std::function on_change); - ~SourceEntitySourceVolumeStrategy(); void update_from_player_attributes(const nlohmann::json &attributes); std::optional get_source_volume(); void set_source_volume(uint8_t volume); - void home_assistant_event_callback(nlohmann::json event_data); + std::optional get_source_player_sources(); + void select_source_player_source(const std::string &source); private: - std::string _source_entity_attribute; - std::function _on_change; - - std::mutex _mutex; - std::string _source_entity_id; - std::optional _source_volume; + HomeAssistantSourcePlayer _source_player; }; #endif // !MQTT_MANAGER_HOME_ASSISTANT_SOURCE_VOLUME_HPP diff --git a/docker/MQTTManager/include/media_player/media_player.cpp b/docker/MQTTManager/include/media_player/media_player.cpp index 0f6a0510..315693b8 100644 --- a/docker/MQTTManager/include/media_player/media_player.cpp +++ b/docker/MQTTManager/include/media_player/media_player.cpp @@ -94,6 +94,13 @@ void MediaPlayerEntity::send_state_update_to_nspanel() { media_player_state->set_can_mute(this->_can_mute); media_player_state->set_album_art_url(this->_get_album_art_url()); media_player_state->set_volume_step(this->_volume_step); + { + std::lock_guard lock_guard(this->_sources_mutex); + MediaPlayerEntity::_fill_source_selection(media_player_state->mutable_player_sources(), this->_player_sources); + if (this->_source_player_sources.has_value()) { + MediaPlayerEntity::_fill_source_selection(media_player_state->mutable_source_player_sources(), this->_source_player_sources.value()); + } + } google::protobuf::util::MessageDifferencer differencer; if (!differencer.Compare(this->_last_media_player_state, state)) { @@ -128,7 +135,7 @@ void MediaPlayerEntity::command_callback(NSPanelMQTTManagerCommand &command) { this->previous_track(); break; case NSPanelMQTTManagerCommand_MediaPlayerCommand_PlaybackAction_NONE: - // The command only changes volume or mute. + // The command only changes volume, mute or source. break; default: SPDLOG_WARN("Received unknown playback action {} for media player {}::{}.", static_cast(media_player_command.playback_action()), this->_id, this->_name); @@ -146,6 +153,97 @@ void MediaPlayerEntity::command_callback(NSPanelMQTTManagerCommand &command) { if (media_player_command.has_muted()) { this->set_muted(media_player_command.muted()); } + + if (!media_player_command.select_player_source().empty()) { + std::optional source; + { + std::lock_guard lock_guard(this->_sources_mutex); + source = this->_find_source(this->_player_sources, media_player_command.select_player_source(), "source"); + } + if (source.has_value()) { + this->select_player_source(source.value()); + } + } + + if (!media_player_command.select_source_player_source().empty()) { + std::optional source; + { + std::lock_guard lock_guard(this->_sources_mutex); + source = this->_find_source(this->_source_player_sources, media_player_command.select_source_player_source(), "source player source"); + } + if (source.has_value()) { + this->select_source_player_source(source.value()); + } + } +} + +void MediaPlayerEntity::_set_player_sources(MediaPlayerSources sources) { + std::lock_guard lock_guard(this->_sources_mutex); + if (this->_player_sources != sources) { + this->_warn_if_sources_limited(sources, "sources"); + this->_player_sources = std::move(sources); + } +} + +void MediaPlayerEntity::_set_source_player_sources(std::optional sources) { + std::lock_guard lock_guard(this->_sources_mutex); + if (this->_source_player_sources != sources) { + if (sources.has_value()) { + this->_warn_if_sources_limited(sources.value(), "source player sources"); + } + this->_source_player_sources = std::move(sources); + } +} + +std::string MediaPlayerEntity::_limit_source_name(const std::string &name) { + if (name.size() <= MediaPlayerEntity::max_source_name_length) { + return name; + } + // Step back from the cut while it would land on a UTF-8 continuation byte (10xxxxxx). + size_t length = MediaPlayerEntity::max_source_name_length; + while (length > 0 && (static_cast(name[length]) & 0xC0) == 0x80) { + length--; + } + return name.substr(0, length); +} + +void MediaPlayerEntity::_fill_source_selection(NSPanelEntityState_MediaPlayer_SourceSelection *selection, const MediaPlayerSources &sources) { + for (size_t i = 0; i < sources.sources.size() && i < MediaPlayerEntity::max_sources; i++) { + selection->add_sources(MediaPlayerEntity::_limit_source_name(sources.sources[i])); + } + selection->set_current_source(MediaPlayerEntity::_limit_source_name(sources.current_source)); + selection->set_can_select(sources.can_select); +} + +std::optional MediaPlayerEntity::_find_source(const std::optional &sources, const std::string &name, std::string_view description) { + if (!sources.has_value()) { + SPDLOG_WARN("Received command to select {} '{}' for media player {}::{} but it has no source player.", description, name, this->_id, this->_name); + return std::nullopt; + } + if (!sources->can_select) { + SPDLOG_WARN("Received command to select {} '{}' for media player {}::{} but it can not select one.", description, name, this->_id, this->_name); + return std::nullopt; + } + // Only the sources sent to the NSPanel can be selected, compare with their names as sent. + for (size_t i = 0; i < sources->sources.size() && i < MediaPlayerEntity::max_sources; i++) { + if (MediaPlayerEntity::_limit_source_name(sources->sources[i]).compare(name) == 0) { + return sources->sources[i]; + } + } + SPDLOG_WARN("Received command to select {} '{}' for media player {}::{} but it is not one of its current sources.", description, name, this->_id, this->_name); + return std::nullopt; +} + +void MediaPlayerEntity::_warn_if_sources_limited(const MediaPlayerSources &sources, std::string_view description) { + if (sources.sources.size() > MediaPlayerEntity::max_sources) { + SPDLOG_WARN("Media player {}::{} has {} {}, only the first {} will be sent to the NSPanel.", this->_id, this->_name, sources.sources.size(), description, MediaPlayerEntity::max_sources); + } + for (size_t i = 0; i < sources.sources.size() && i < MediaPlayerEntity::max_sources; i++) { + if (sources.sources[i].size() > MediaPlayerEntity::max_source_name_length) { + SPDLOG_WARN("Media player {}::{} has {} with names longer than {} bytes, they will be shortened on the NSPanel.", this->_id, this->_name, description, MediaPlayerEntity::max_source_name_length); + break; + } + } } void MediaPlayerEntity::_set_album_art_source(const std::string &source) { diff --git a/docker/MQTTManager/include/media_player/media_player.hpp b/docker/MQTTManager/include/media_player/media_player.hpp index 451ce7a6..d278857d 100644 --- a/docker/MQTTManager/include/media_player/media_player.hpp +++ b/docker/MQTTManager/include/media_player/media_player.hpp @@ -10,6 +10,18 @@ #include #include #include +#include + +/** + * Sources a media player (or the source player feeding it) can select, as reported by the controller. + */ +struct MediaPlayerSources { + std::vector sources; + std::string current_source; // Empty if unknown. + bool can_select = false; + + bool operator==(const MediaPlayerSources &other) const = default; +}; class MediaPlayerEntity : public MqttManagerEntity { public: @@ -77,6 +89,23 @@ class MediaPlayerEntity : public MqttManagerEntity { */ virtual void set_muted(bool muted) = 0; + /** + * Select a source (input) of the media player. + * @param source: Name of the source as reported by the controller. + */ + virtual void select_player_source(const std::string &source) = 0; + + /** + * Select a source of the source player currently feeding the media player. + * @param source: Name of the source as reported by the controller. + */ + virtual void select_source_player_source(const std::string &source) = 0; + + // Limits on the source lists sent to the NSPanel, which can only receive 4 KB in one MQTT message. + // The NSPanel pages through longer lists than it can show at once. + static constexpr size_t max_sources = 32; + static constexpr size_t max_source_name_length = 64; // In bytes + /** * Get the current album art as the original image data (for example a JPEG) from the controller. * The image is downloaded on first request and cached until the album art changes. The same pointer is @@ -114,6 +143,17 @@ class MediaPlayerEntity : public MqttManagerEntity { */ virtual bool _download_album_art(const std::string &source, std::string &image_data) = 0; + /** + * Set the sources of the media player. They are sent with the next state update. + */ + void _set_player_sources(MediaPlayerSources sources); + + /** + * Set the sources of the source player feeding the media player, or nothing if there is no source player. + * They are sent with the next state update. + */ + void _set_source_player_sources(std::optional sources); + uint32_t _id; std::string _name; uint16_t _room_id; @@ -145,6 +185,32 @@ class MediaPlayerEntity : public MqttManagerEntity { */ std::string _get_album_art_url(); + /** + * Shorten a source name to what is sent to the NSPanel, without splitting a UTF-8 character. + */ + static std::string _limit_source_name(const std::string &name); + + /** + * Fill in a source list for the NSPanel, limited to max_sources entries of max_source_name_length bytes. + */ + static void _fill_source_selection(NSPanelEntityState_MediaPlayer_SourceSelection *selection, const MediaPlayerSources &sources); + + /** + * Find the source a name sent by the NSPanel refers to. The NSPanel only knows the limited names. + * @return The source as reported by the controller, or nothing if the source can not be selected. + */ + std::optional _find_source(const std::optional &sources, const std::string &name, std::string_view description); + + /** + * Log a warning if sources will be cut short when sent to the NSPanel. + */ + void _warn_if_sources_limited(const MediaPlayerSources &sources, std::string_view description); + + // Guards the source lists. They are updated by the controller and read when the NSPanel selects a source. + std::mutex _sources_mutex; + MediaPlayerSources _player_sources; + std::optional _source_player_sources; + // Guards _album_art_source. Only held briefly, never while downloading. std::mutex _album_art_source_mutex; std::string _album_art_source; From 9913fcbbe7d85271b497748a0124cf6b29a4e9e8 Mon Sep 17 00:00:00 2001 From: James Mulcahy Date: Tue, 13 Oct 2026 12:21:50 -0700 Subject: [PATCH 3/3] Test media player source selection Covers publishing a player's sources from Home Assistant, selecting a source from the panel, ignoring sources that are unknown or can't be selected, and limiting source lists to 32 names of at most 64 bytes without splitting a UTF-8 character (selecting a shortened name sends the full name to Home Assistant). Also covers a source player feeding the media player: its sources are published and selected on the source player, and switching to another source player drops the previous one's sources. Co-Authored-By: Claude Opus 5.5 --- .../MQTTManager/tests/media_player_test.cpp | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/docker/MQTTManager/tests/media_player_test.cpp b/docker/MQTTManager/tests/media_player_test.cpp index 293ee95c..381f46b0 100644 --- a/docker/MQTTManager/tests/media_player_test.cpp +++ b/docker/MQTTManager/tests/media_player_test.cpp @@ -2,8 +2,11 @@ #include #include #include +#include #include #include +#include +#include using nspm_test::django_media_player_data; using nspm_test::home_assistant_service_calls; @@ -166,6 +169,165 @@ TEST_F(HomeAssistantMediaPlayerTest, commands_for_other_media_players_are_ignore EXPECT_TRUE(home_assistant_service_calls().empty()); } +// Unsigned, as nlohmann::json parses it from Home Assistant. A signed int in the attributes is ignored. +constexpr uint32_t SELECT_SOURCE = HomeAssistantSourcePlayer::feature_select_source; + +std::vector sources_of(const NSPanelEntityState_MediaPlayer_SourceSelection &selection) { + return std::vector(selection.sources().begin(), selection.sources().end()); +} + +TEST_F(HomeAssistantMediaPlayerTest, player_sources_are_published_from_home_assistant) { + receive_state("playing", {{"source_list", nlohmann::json::array({"TV", "Radio", "Spotify"})}, {"source", "Radio"}, {"supported_features", SELECT_SOURCE}}); + + auto state = last_published_state(); + ASSERT_TRUE(state.has_value()); + EXPECT_EQ(sources_of(state->player_sources()), std::vector({"TV", "Radio", "Spotify"})); + EXPECT_EQ(state->player_sources().current_source(), "Radio"); + EXPECT_TRUE(state->player_sources().can_select()); + EXPECT_FALSE(state->has_source_player_sources()); +} + +TEST_F(HomeAssistantMediaPlayerTest, sources_can_not_be_selected_without_the_select_source_feature) { + receive_state("playing", {{"source_list", nlohmann::json::array({"TV", "Radio"})}, {"source", "TV"}}); + + auto state = last_published_state(); + ASSERT_TRUE(state.has_value()); + EXPECT_EQ(sources_of(state->player_sources()), std::vector({"TV", "Radio"})); + EXPECT_FALSE(state->player_sources().can_select()); + + send_panel_command([](auto *command) { command->set_select_player_source("Radio"); }); + + EXPECT_TRUE(home_assistant_service_calls().empty()); +} + +TEST_F(HomeAssistantMediaPlayerTest, panel_source_selection_calls_home_assistant) { + receive_state("playing", {{"source_list", nlohmann::json::array({"TV", "Radio"})}, {"source", "TV"}, {"supported_features", SELECT_SOURCE}}); + + send_panel_command([](auto *command) { command->set_select_player_source("Radio"); }); + + auto calls = home_assistant_service_calls(); + ASSERT_EQ(calls.size(), 1); + EXPECT_EQ(calls[0], nlohmann::json({{"type", "call_service"}, {"domain", "media_player"}, {"service", "select_source"}, {"target", {{"entity_id", "media_player.lounge"}}}, {"service_data", {{"source", "Radio"}}}})); +} + +TEST_F(HomeAssistantMediaPlayerTest, selecting_an_unknown_source_is_ignored) { + receive_state("playing", {{"source_list", nlohmann::json::array({"TV", "Radio"})}, {"supported_features", SELECT_SOURCE}}); + + send_panel_command([](auto *command) { command->set_select_player_source("Vinyl"); }); + + EXPECT_TRUE(home_assistant_service_calls().empty()); +} + +TEST_F(HomeAssistantMediaPlayerTest, source_lists_are_limited_for_the_panel) { + nlohmann::json source_list = nlohmann::json::array(); + for (size_t i = 0; i < MediaPlayerEntity::max_sources + 5; i++) { + source_list.push_back("Input " + std::to_string(i)); + } + // 63 bytes then a 2 byte UTF-8 character: cutting at 64 bytes would split it, so the name is cut before it. + const std::string long_name = std::string(MediaPlayerEntity::max_source_name_length - 1, 'a') + "\xC3\xA9"; + const std::string short_name = std::string(MediaPlayerEntity::max_source_name_length - 1, 'a'); + source_list[0] = long_name; + receive_state("playing", {{"source_list", source_list}, {"source", long_name}, {"supported_features", SELECT_SOURCE}}); + + auto state = last_published_state(); + ASSERT_TRUE(state.has_value()); + ASSERT_EQ(state->player_sources().sources_size(), static_cast(MediaPlayerEntity::max_sources)); + EXPECT_EQ(state->player_sources().sources(0), short_name); + EXPECT_EQ(state->player_sources().current_source(), short_name); + EXPECT_EQ(state->player_sources().sources(MediaPlayerEntity::max_sources - 1), "Input " + std::to_string(MediaPlayerEntity::max_sources - 1)); + + // The panel only knows the shortened name, Home Assistant gets the full one. + send_panel_command([&](auto *command) { command->set_select_player_source(short_name); }); + auto calls = home_assistant_service_calls(); + ASSERT_EQ(calls.size(), 1); + EXPECT_EQ(calls[0]["service_data"]["source"], long_name); + + // Sources past the limit were never shown on the panel, so they can not be selected. + send_panel_command([&](auto *command) { command->set_select_player_source("Input " + std::to_string(MediaPlayerEntity::max_sources)); }); + EXPECT_TRUE(home_assistant_service_calls().empty()); +} + +TEST_F(HomeAssistantMediaPlayerTest, removed_entity_has_no_sources) { + receive_state("playing", {{"source_list", nlohmann::json::array({"TV", "Radio"})}, {"supported_features", SELECT_SOURCE}}); + + nlohmann::json removed = home_assistant_state_changed("media_player.lounge", ""); + removed["event"]["data"]["new_state"] = nullptr; + HomeAssistantManager::test_process_event(removed); + + auto state = last_published_state(); + ASSERT_TRUE(state.has_value()); + EXPECT_EQ(state->player_sources().sources_size(), 0); + EXPECT_FALSE(state->player_sources().can_select()); +} + +// A media player fed by a source player, as with a multi-room audio matrix: the player reports the +// entity ID of its current source player in a state attribute. +class HomeAssistantSourcePlayerSourcesTest : public HomeAssistantMediaPlayerTest { +protected: + void SetUp() override { + nspm_test::SendCaptureTest::SetUp(); + nlohmann::json entity_data = django_media_player_data("media_player.lounge"); + entity_data["source_volume_strategy"] = "source_entity"; + entity_data["source_entity_attribute"] = "source_entity"; + row = std::make_unique("media_player", "Lounge zone", entity_data); + player = std::make_unique(row->id); + } + + void receive_source_state(const std::string &entity_id, const nlohmann::json &attributes) { + auto event = home_assistant_state_changed(entity_id, "playing", attributes); + HomeAssistantManager::test_process_event(event); + } +}; + +TEST_F(HomeAssistantSourcePlayerSourcesTest, source_player_sources_are_published) { + receive_state("playing", {{"source_entity", "media_player.streamer"}}); + receive_source_state("media_player.streamer", {{"source_list", nlohmann::json::array({"Spotify", "AirPlay"})}, {"source", "AirPlay"}, {"supported_features", SELECT_SOURCE}}); + + auto state = last_published_state(); + ASSERT_TRUE(state.has_value()); + ASSERT_TRUE(state->has_source_player_sources()); + EXPECT_EQ(sources_of(state->source_player_sources()), std::vector({"Spotify", "AirPlay"})); + EXPECT_EQ(state->source_player_sources().current_source(), "AirPlay"); + EXPECT_TRUE(state->source_player_sources().can_select()); +} + +TEST_F(HomeAssistantSourcePlayerSourcesTest, panel_source_player_selection_calls_the_source_player) { + receive_state("playing", {{"source_entity", "media_player.streamer"}}); + receive_source_state("media_player.streamer", {{"source_list", nlohmann::json::array({"Spotify", "AirPlay"})}, {"supported_features", SELECT_SOURCE}}); + home_assistant_service_calls(); + + send_panel_command([](auto *command) { command->set_select_source_player_source("Spotify"); }); + + auto calls = home_assistant_service_calls(); + ASSERT_EQ(calls.size(), 1); + EXPECT_EQ(calls[0], nlohmann::json({{"type", "call_service"}, {"domain", "media_player"}, {"service", "select_source"}, {"target", {{"entity_id", "media_player.streamer"}}}, {"service_data", {{"source", "Spotify"}}}})); +} + +TEST_F(HomeAssistantSourcePlayerSourcesTest, switching_source_player_drops_the_previous_sources) { + receive_state("playing", {{"source_entity", "media_player.streamer"}}); + receive_source_state("media_player.streamer", {{"source_list", nlohmann::json::array({"Spotify", "AirPlay"})}, {"supported_features", SELECT_SOURCE}}); + last_published_state(); + + receive_state("playing", {{"source_entity", "media_player.turntable"}}); + + auto state = last_published_state(); + ASSERT_TRUE(state.has_value()); + ASSERT_TRUE(state->has_source_player_sources()); + EXPECT_EQ(state->source_player_sources().sources_size(), 0); + + // A late event from the previous source player must not bring its sources back. + receive_source_state("media_player.streamer", {{"source_list", nlohmann::json::array({"Spotify"})}, {"supported_features", SELECT_SOURCE}}); + EXPECT_FALSE(last_published_state().has_value()); +} + +TEST_F(HomeAssistantMediaPlayerTest, source_player_selection_without_a_source_player_is_ignored) { + receive_state("playing", {{"source_list", nlohmann::json::array({"TV"})}, {"supported_features", SELECT_SOURCE}}); + + send_panel_command([](auto *command) { command->set_select_source_player_source("TV"); }); + + EXPECT_TRUE(home_assistant_service_calls().empty()); +} + TEST(MediaPlayerConfig, invalid_volume_step_falls_back_to_five) { for (auto volume_step : {0, 101}) { SCOPED_TRACE(volume_step);