diff --git a/src/decoder/Bridge.cxx b/src/decoder/Bridge.cxx index 78a222e70..0eec4a1d1 100644 --- a/src/decoder/Bridge.cxx +++ b/src/decoder/Bridge.cxx @@ -239,6 +239,10 @@ DecoderBridge::UpdateStreamTag(InputStream *is) noexcept /* discard the song tag; we don't need it */ song_tag.reset(); + if (stream_tag && tag && *stream_tag == *tag) + /* not changed */ + return false; + stream_tag = std::move(tag); return true; } diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx index 1a9de7235..5980f4748 100644 --- a/src/player/Thread.cxx +++ b/src/player/Thread.cxx @@ -904,13 +904,15 @@ PlayerControl::LockUpdateSongTag(DetachedSong &song, streams may change tags dynamically */ return; - song.SetTag(new_tag); + if (new_tag != song.GetTag()) { + song.SetTag(new_tag); - LockSetTaggedSong(song); + LockSetTaggedSong(song); - /* the main thread will update the playlist version when he - receives this event */ - listener.OnPlayerTagModified(); + /* the main thread will update the playlist version when he + receives this event */ + listener.OnPlayerTagModified(); + } } inline void diff --git a/src/tag/Item.hxx b/src/tag/Item.hxx index 84bf6ae49..b67eac469 100644 --- a/src/tag/Item.hxx +++ b/src/tag/Item.hxx @@ -5,6 +5,7 @@ #define MPD_TAG_ITEM_HXX #include +#include enum TagType : uint8_t; @@ -22,6 +23,15 @@ struct TagItem { */ char value[1]; + bool operator==(const TagItem &other) const noexcept { + return (this == &other) ? true : + type == other.type && std::strcmp(value, other.value) == 0; + } + +private: + /* making the constructor private + to only allow construction by TagPoolItem. */ + friend struct TagPoolItem; TagItem() = default; TagItem(const TagItem &other) = delete; TagItem &operator=(const TagItem &other) = delete; diff --git a/src/tag/Tag.cxx b/src/tag/Tag.cxx index 585862c36..4ca50b878 100644 --- a/src/tag/Tag.cxx +++ b/src/tag/Tag.cxx @@ -7,6 +7,15 @@ #include +bool +Tag::operator==(const Tag &other) const noexcept { + return (this == &other) ? true : + duration == other.duration + && has_playlist == other.has_playlist + && num_items == other.num_items + && std::equal(begin(), end(), other.begin(), other.end()); +} + void Tag::Clear() noexcept { diff --git a/src/tag/Tag.hxx b/src/tag/Tag.hxx index 6d6c368af..dbfdb49f1 100644 --- a/src/tag/Tag.hxx +++ b/src/tag/Tag.hxx @@ -65,6 +65,8 @@ struct Tag { return *this; } + bool operator==(const Tag &other) const noexcept; + /** * Similar to the move operator, but move only the #TagItem * array. diff --git a/src/util/DereferenceIterator.hxx b/src/util/DereferenceIterator.hxx index 4d21cd998..c40ea55fe 100644 --- a/src/util/DereferenceIterator.hxx +++ b/src/util/DereferenceIterator.hxx @@ -82,6 +82,10 @@ public: return DereferenceIterator{original - n}; } + constexpr auto operator-(const DereferenceIterator& other) const noexcept { + return std::distance(other.original, original); + } + /* this is a template to allow comparisons with sentinel end iterators */ template diff --git a/src/util/TerminatedArray.hxx b/src/util/TerminatedArray.hxx index b0d361f66..38d40c9ee 100644 --- a/src/util/TerminatedArray.hxx +++ b/src/util/TerminatedArray.hxx @@ -101,6 +101,10 @@ public: return iterator{cursor - n}; } + constexpr auto operator-(const iterator& other) const noexcept { + return std::distance(other.cursor, cursor); + } + reference operator*() const noexcept { return *cursor; }