check if song is in playlist in O(nlogn) instead of O(n^2)

This commit is contained in:
Andrzej Rybczak
2012-09-04 03:12:37 +02:00
parent 8ab8da2a30
commit 60ca9de919
7 changed files with 50 additions and 51 deletions

View File

@@ -148,9 +148,7 @@ void Browser::EnterPressed()
} }
case itSong: case itSong:
{ {
size_t i = w->choice(); myPlaylist->Add(*item.song, 1);
bool res = myPlaylist->Add(*item.song, w->at(i).isBold(), 1);
w->at(i).setBold(res);
break; break;
} }
case itPlaylist: case itPlaylist:
@@ -209,9 +207,7 @@ void Browser::SpacePressed()
} }
case itSong: case itSong:
{ {
i = w->choice(); myPlaylist->Add(*item.song, 0);
bool res = myPlaylist->Add(*item.song, w->at(i).isBold(), 0);
w->at(i).setBold(res);
break; break;
} }
case itPlaylist: case itPlaylist:
@@ -618,10 +614,9 @@ bool Browser::deleteItem(const MPD::Item &item)
void Browser::UpdateItemList() void Browser::UpdateItemList()
{ {
for (size_t i = 0; i < w->size(); ++i) for (auto it = w->begin(); it != w->end(); ++it)
if ((*w)[i].value().type == itSong) if (it->value().type == itSong)
w->at(i).setBold(myPlaylist->checkForSong(*(*w)[i].value().song)); it->setBold(myPlaylist->checkForSong(*it->value().song));
w->refresh();
} }
namespace {// namespace {//

View File

@@ -802,10 +802,7 @@ void MediaLibrary::LocateSong(const MPD::Song &s)
void MediaLibrary::AddToPlaylist(bool add_n_play) void MediaLibrary::AddToPlaylist(bool add_n_play)
{ {
if (w == Songs && !Songs->empty()) if (w == Songs && !Songs->empty())
{ myPlaylist->Add(Songs->current().value(), add_n_play);
bool res = myPlaylist->Add(Songs->current().value(), Songs->current().isBold(), add_n_play);
Songs->current().setBold(res);
}
else else
{ {
auto list = getSelectedSongs(); auto list = getSelectedSongs();

View File

@@ -594,11 +594,11 @@ const MPD::Song *Playlist::NowPlayingSong()
return s; return s;
} }
bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play, int position) bool Playlist::Add(const MPD::Song &s, bool play, int position)
{ {
if (Config.ncmpc_like_songs_adding && in_playlist) if (Config.ncmpc_like_songs_adding && checkForSong(s))
{ {
unsigned hash = s.getHash(); size_t hash = s.getHash();
if (play) if (play)
{ {
for (size_t i = 0; i < Items->size(); ++i) for (size_t i = 0; i < Items->size(); ++i)
@@ -615,14 +615,8 @@ bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play, int position
{ {
Mpd.StartCommandsList(); Mpd.StartCommandsList();
for (size_t i = 0; i < Items->size(); ++i) for (size_t i = 0; i < Items->size(); ++i)
{
if ((*Items)[i].value().getHash() == hash) if ((*Items)[i].value().getHash() == hash)
{
Mpd.Delete(i); Mpd.Delete(i);
Items->deleteItem(i);
i--;
}
}
Mpd.CommitCommandsList(); Mpd.CommitCommandsList();
return false; return false;
} }
@@ -692,12 +686,24 @@ void Playlist::SetSelectedItemsPriority(int prio)
ShowMessage("Priority set"); ShowMessage("Priority set");
} }
bool Playlist::checkForSong (const MPD::Song &s) bool Playlist::checkForSong(const MPD::Song &s)
{ {
for (size_t i = 0; i < Items->size(); ++i) return itsSongHashes.find(s.getHash()) != itsSongHashes.end();
if (s.getHash() == (*Items)[i].value().getHash()) }
return true;
return false; void Playlist::registerHash(size_t hash)
{
itsSongHashes[hash] += 1;
}
void Playlist::unregisterHash(size_t hash)
{
auto it = itsSongHashes.find(hash);
assert(it != itsSongHashes.end());
if (it->second == 1)
itsSongHashes.erase(it);
else
it->second -= 1;
} }
namespace {// namespace {//

View File

@@ -21,6 +21,8 @@
#ifndef _PLAYLIST_H #ifndef _PLAYLIST_H
#define _PLAYLIST_H #define _PLAYLIST_H
#include <map>
#include "interfaces.h" #include "interfaces.h"
#include "screen.h" #include "screen.h"
#include "song.h" #include "song.h"
@@ -80,7 +82,7 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
void UpdateTimer() { time(&itsTimer); } void UpdateTimer() { time(&itsTimer); }
time_t Timer() const { return itsTimer; } time_t Timer() const { return itsTimer; }
bool Add(const MPD::Song &s, bool in_playlist, bool play, int position = -1); bool Add(const MPD::Song &s, bool play, int position = -1);
bool Add(const MPD::SongList &l, bool play, int position = -1); bool Add(const MPD::SongList &l, bool play, int position = -1);
void PlayNewlyAddedSongs(); void PlayNewlyAddedSongs();
@@ -88,6 +90,9 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
bool checkForSong(const MPD::Song &s); bool checkForSong(const MPD::Song &s);
void registerHash(size_t hash);
void unregisterHash(size_t hash);
//static std::string SongToString(const MPD::Song &s); //static std::string SongToString(const MPD::Song &s);
//static std::string SongInColumnsToString(const MPD::Song &s); //static std::string SongInColumnsToString(const MPD::Song &s);
@@ -106,6 +111,8 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
std::string TotalLength(); std::string TotalLength();
std::string itsBufferedStats; std::string itsBufferedStats;
std::map<size_t, int> itsSongHashes;
size_t itsTotalLength; size_t itsTotalLength;
size_t itsRemainingTime; size_t itsRemainingTime;
size_t itsScrollBegin; size_t itsScrollBegin;

View File

@@ -345,10 +345,7 @@ void PlaylistEditor::AddToPlaylist(bool add_n_play)
} }
} }
else if (w == Content && !Content->empty()) else if (w == Content && !Content->empty())
{ myPlaylist->Add(Content->current().value(), add_n_play);
bool res = myPlaylist->Add(Content->current().value(), Content->current().isBold(), add_n_play);
Content->current().setBold(res);
}
if (!add_n_play) if (!add_n_play)
w->scroll(NC::wDown); w->scroll(NC::wDown);

View File

@@ -224,10 +224,7 @@ void SearchEngine::EnterPressed()
reset(); reset();
} }
else else
{ myPlaylist->Add(w->current().value().song(), 1);
bool res = myPlaylist->Add(w->current().value().song(), w->current().isBold(), 1);
w->current().setBold(res);
}
if (option < SearchButton) if (option < SearchButton)
UnlockStatusbar(); UnlockStatusbar();
@@ -245,8 +242,7 @@ void SearchEngine::SpacePressed()
return; return;
} }
bool res = myPlaylist->Add(w->current().value().song(), w->current().isBold(), 0); myPlaylist->Add(w->current().value().song(), 0);
w->current().setBold(res);
w->scroll(NC::wDown); w->scroll(NC::wDown);
} }

View File

@@ -234,7 +234,13 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
size_t playlist_length = Mpd.GetPlaylistLength(); size_t playlist_length = Mpd.GetPlaylistLength();
if (playlist_length < myPlaylist->Items->size()) if (playlist_length < myPlaylist->Items->size())
{
auto it = myPlaylist->Items->begin()+playlist_length;
auto end = myPlaylist->Items->end();
for (; it != end; ++it)
myPlaylist->unregisterHash(it->value().getHash());
myPlaylist->Items->resizeList(playlist_length); myPlaylist->Items->resizeList(playlist_length);
}
auto songs = Mpd.GetPlaylistChanges(Mpd.GetOldPlaylistID()); auto songs = Mpd.GetPlaylistChanges(Mpd.GetOldPlaylistID());
for (auto s = songs.begin(); s != songs.end(); ++s) for (auto s = songs.begin(); s != songs.end(); ++s)
@@ -243,13 +249,16 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
if (pos < myPlaylist->Items->size()) if (pos < myPlaylist->Items->size())
{ {
// if song's already in playlist, replace it with a new one // if song's already in playlist, replace it with a new one
myPlaylist->Items->at(pos).value() = *s; MPD::Song &old_s = myPlaylist->Items->at(pos).value();
myPlaylist->unregisterHash(old_s.getHash());
old_s = *s;
} }
else else
{ {
// otherwise just add it to playlist // otherwise just add it to playlist
myPlaylist->Items->addItem(*s); myPlaylist->Items->addItem(*s);
} }
myPlaylist->registerHash(s->getHash());
} }
if (is_filtered) if (is_filtered)
@@ -266,21 +275,13 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
myPlaylist->Items->reset(); myPlaylist->Items->reset();
if (isVisible(myBrowser)) if (isVisible(myBrowser))
{
myBrowser->UpdateItemList(); myBrowser->UpdateItemList();
} if (isVisible(mySearcher))
else if (isVisible(mySearcher))
{
mySearcher->UpdateFoundList(); mySearcher->UpdateFoundList();
} if (isVisible(myLibrary))
else if (isVisible(myLibrary))
{
UpdateSongList(myLibrary->Songs); UpdateSongList(myLibrary->Songs);
} if (isVisible(myPlaylistEditor))
else if (isVisible(myPlaylistEditor))
{
UpdateSongList(myPlaylistEditor->Content); UpdateSongList(myPlaylistEditor->Content);
}
} }
if (changed.Database) if (changed.Database)
{ {