playlist: make kept song count collision resistant
This commit is contained in:
@@ -398,7 +398,7 @@ void Browser::LocateSong(const MPD::Song &s)
|
||||
GetDirectory(s.getDirectory());
|
||||
for (size_t i = 0; i < w.size(); ++i)
|
||||
{
|
||||
if (w[i].value().type == itSong && s.getHash() == w[i].value().song->getHash())
|
||||
if (w[i].value().type == itSong && s == *w[i].value().song)
|
||||
{
|
||||
w.highlight(i);
|
||||
break;
|
||||
@@ -460,16 +460,7 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
|
||||
}
|
||||
case itSong:
|
||||
{
|
||||
bool bold = 0;
|
||||
for (size_t i = 0; i < myPlaylist->main().size(); ++i)
|
||||
{
|
||||
if (myPlaylist->main().at(i).value().getHash() == it->song->getHash())
|
||||
{
|
||||
bold = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
w.addItem(*it, bold);
|
||||
w.addItem(*it, myPlaylist->checkForSong(*it->song));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,11 +980,11 @@ void MediaLibrary::LocateSong(const MPD::Song &s)
|
||||
if (Songs.empty())
|
||||
update();
|
||||
|
||||
if (s.getHash() != Songs.current().value().getHash())
|
||||
if (s != Songs.current().value())
|
||||
{
|
||||
for (size_t i = 0; i < Songs.size(); ++i)
|
||||
{
|
||||
if (s.getHash() == Songs[i].value().getHash())
|
||||
if (s == Songs[i].value())
|
||||
{
|
||||
Songs.highlight(i);
|
||||
break;
|
||||
|
||||
@@ -360,20 +360,20 @@ unsigned Playlist::currentSongLength() const
|
||||
|
||||
bool Playlist::checkForSong(const MPD::Song &s)
|
||||
{
|
||||
return m_song_hashes.find(s.getHash()) != m_song_hashes.end();
|
||||
return m_song_refs.find(s) != m_song_refs.end();
|
||||
}
|
||||
|
||||
void Playlist::registerHash(size_t hash)
|
||||
void Playlist::registerSong(const MPD::Song &s)
|
||||
{
|
||||
++m_song_hashes[hash];
|
||||
++m_song_refs[s];
|
||||
}
|
||||
|
||||
void Playlist::unregisterHash(size_t hash)
|
||||
void Playlist::unregisterSong(const MPD::Song &s)
|
||||
{
|
||||
auto it = m_song_hashes.find(hash);
|
||||
assert(it != m_song_hashes.end());
|
||||
auto it = m_song_refs.find(s);
|
||||
assert(it != m_song_refs.end());
|
||||
if (it->second == 1)
|
||||
m_song_hashes.erase(it);
|
||||
m_song_refs.erase(it);
|
||||
else
|
||||
--it->second;
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ struct Playlist: Screen<NC::Menu<MPD::Song>>, Filterable, HasSongs, Searchable,
|
||||
unsigned currentSongLength() const;
|
||||
|
||||
bool checkForSong(const MPD::Song &s);
|
||||
void registerHash(size_t hash);
|
||||
void unregisterHash(size_t hash);
|
||||
void registerSong(const MPD::Song &s);
|
||||
void unregisterSong(const MPD::Song &s);
|
||||
|
||||
void reloadTotalLength() { m_reload_total_length = true; }
|
||||
void reloadRemaining() { m_reload_remaining = true; }
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
|
||||
std::string m_stats;
|
||||
|
||||
std::unordered_map<size_t, int> m_song_hashes;
|
||||
std::unordered_map<MPD::Song, int, MPD::Song::Hash> m_song_refs;
|
||||
|
||||
size_t m_total_length;;
|
||||
size_t m_remaining_time;
|
||||
|
||||
10
src/song.cpp
10
src/song.cpp
@@ -30,13 +30,13 @@
|
||||
#include "utility/wide_string.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace {//
|
||||
namespace {
|
||||
|
||||
size_t calc_hash(const char* s, unsigned seed = 0)
|
||||
{
|
||||
size_t hash = seed;
|
||||
while (*s)
|
||||
hash = hash * 101 + *s++;
|
||||
hash = hash * 101 + *s++;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -211,12 +211,6 @@ std::string MPD::Song::getTags(GetFunction f, const std::string &tags_separator)
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned Song::getHash() const
|
||||
{
|
||||
assert(m_song);
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
unsigned Song::getDuration() const
|
||||
{
|
||||
assert(m_song);
|
||||
|
||||
20
src/song.h
20
src/song.h
@@ -21,6 +21,7 @@
|
||||
#ifndef NCMPCPP_SONG_H
|
||||
#define NCMPCPP_SONG_H
|
||||
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -32,6 +33,10 @@ namespace MPD {//
|
||||
|
||||
struct Song
|
||||
{
|
||||
struct Hash {
|
||||
size_t operator()(const Song &s) const { return s.m_hash; }
|
||||
};
|
||||
|
||||
typedef std::string (Song::*GetFunction)(unsigned) const;
|
||||
|
||||
Song() { }
|
||||
@@ -61,7 +66,6 @@ struct Song
|
||||
|
||||
virtual std::string getTags(GetFunction f, const std::string &tags_separator) const;
|
||||
|
||||
virtual unsigned getHash() const;
|
||||
virtual unsigned getDuration() const;
|
||||
virtual unsigned getPosition() const;
|
||||
virtual unsigned getID() const;
|
||||
@@ -76,9 +80,19 @@ struct Song
|
||||
virtual std::string toString(const std::string &fmt, const std::string &tags_separator,
|
||||
const std::string &escape_chars = "") const;
|
||||
|
||||
bool operator==(const Song &rhs) const { return m_hash == rhs.m_hash; }
|
||||
bool operator!=(const Song &rhs) const { return m_hash != rhs.m_hash; }
|
||||
bool operator==(const Song &rhs) const {
|
||||
if (m_hash != rhs.m_hash)
|
||||
return false;
|
||||
return strcmp(c_uri(), rhs.c_uri()) == 0;
|
||||
}
|
||||
bool operator!=(const Song &rhs) const {
|
||||
if (m_hash != rhs.m_hash)
|
||||
return true;
|
||||
return strcmp(c_uri(), rhs.c_uri()) != 0;
|
||||
}
|
||||
|
||||
const char *c_uri() const { return m_song ? mpd_song_get_uri(m_song.get()) : ""; }
|
||||
|
||||
static std::string ShowTime(unsigned length);
|
||||
static void validateFormat(const std::string &fmt);
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ void Status::Changes::playlist()
|
||||
auto it = myPlaylist->main().begin()+playlist_length;
|
||||
auto end = myPlaylist->main().end();
|
||||
for (; it != end; ++it)
|
||||
myPlaylist->unregisterHash(it->value().getHash());
|
||||
myPlaylist->unregisterSong(it->value());
|
||||
myPlaylist->main().resizeList(playlist_length);
|
||||
}
|
||||
|
||||
@@ -267,12 +267,12 @@ void Status::Changes::playlist()
|
||||
{
|
||||
// if song's already in playlist, replace it with a new one
|
||||
MPD::Song &old_s = myPlaylist->main()[pos].value();
|
||||
myPlaylist->unregisterHash(old_s.getHash());
|
||||
myPlaylist->unregisterSong(old_s);
|
||||
old_s = s;
|
||||
}
|
||||
else // otherwise just add it to playlist
|
||||
myPlaylist->main().addItem(s);
|
||||
myPlaylist->registerHash(s.getHash());
|
||||
myPlaylist->registerSong(s);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1025,7 +1025,7 @@ void TagEditor::LocateSong(const MPD::Song &s)
|
||||
// highlight our file
|
||||
for (size_t i = 0; i < Tags->size(); ++i)
|
||||
{
|
||||
if ((*Tags)[i].value().getHash() == s.getHash())
|
||||
if ((*Tags)[i].value() == s)
|
||||
{
|
||||
Tags->highlight(i);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user