check if song is in playlist in O(nlogn) instead of O(n^2)
This commit is contained in:
@@ -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 {//
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {//
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user