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

View File

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

View File

@@ -594,11 +594,11 @@ const MPD::Song *Playlist::NowPlayingSong()
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)
{
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();
for (size_t i = 0; i < Items->size(); ++i)
{
if ((*Items)[i].value().getHash() == hash)
{
Mpd.Delete(i);
Items->deleteItem(i);
i--;
}
}
Mpd.CommitCommandsList();
return false;
}
@@ -692,12 +686,24 @@ void Playlist::SetSelectedItemsPriority(int prio)
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)
if (s.getHash() == (*Items)[i].value().getHash())
return true;
return false;
return itsSongHashes.find(s.getHash()) != itsSongHashes.end();
}
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 {//

View File

@@ -21,6 +21,8 @@
#ifndef _PLAYLIST_H
#define _PLAYLIST_H
#include <map>
#include "interfaces.h"
#include "screen.h"
#include "song.h"
@@ -80,7 +82,7 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
void UpdateTimer() { time(&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);
void PlayNewlyAddedSongs();
@@ -88,6 +90,9 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
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 SongInColumnsToString(const MPD::Song &s);
@@ -106,6 +111,8 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
std::string TotalLength();
std::string itsBufferedStats;
std::map<size_t, int> itsSongHashes;
size_t itsTotalLength;
size_t itsRemainingTime;
size_t itsScrollBegin;

View File

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

View File

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

View File

@@ -234,7 +234,13 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
size_t playlist_length = Mpd.GetPlaylistLength();
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);
}
auto songs = Mpd.GetPlaylistChanges(Mpd.GetOldPlaylistID());
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 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
{
// otherwise just add it to playlist
myPlaylist->Items->addItem(*s);
}
myPlaylist->registerHash(s->getHash());
}
if (is_filtered)
@@ -266,21 +275,13 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
myPlaylist->Items->reset();
if (isVisible(myBrowser))
{
myBrowser->UpdateItemList();
}
else if (isVisible(mySearcher))
{
if (isVisible(mySearcher))
mySearcher->UpdateFoundList();
}
else if (isVisible(myLibrary))
{
if (isVisible(myLibrary))
UpdateSongList(myLibrary->Songs);
}
else if (isVisible(myPlaylistEditor))
{
if (isVisible(myPlaylistEditor))
UpdateSongList(myPlaylistEditor->Content);
}
}
if (changed.Database)
{