1 /* 2 Vimpc 3 Copyright (C) 2010 Nathan Sweetman 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 library.hpp - handling of the mpd music library 19 */ 20 21 #ifndef __UI__LIBRARY 22 #define __UI__LIBRARY 23 24 #include "algorithm.hpp" 25 #include "buffer.hpp" 26 #include "settings.hpp" 27 #include "song.hpp" 28 29 #include <vector> 30 31 namespace Ui { class LibraryWindow; } 32 33 namespace Mpc 34 { 35 class Client; 36 class ClientState; 37 class Library; 38 class LibraryEntry; 39 40 typedef std::vector<LibraryEntry *> LibraryEntryVector; 41 42 class LibraryEntry 43 { 44 public: 45 friend class Library; 46 LibraryEntry()47 LibraryEntry() : 48 type_ (SongType), 49 artist_ (""), 50 album_ (""), 51 song_ (NULL), 52 expanded_(false), 53 children_(), 54 parent_ (NULL), 55 childrenInPlaylist_(0), 56 partial_(0) 57 { } 58 59 public: operator ==(LibraryEntry const & rhs) const60 bool operator==(LibraryEntry const & rhs) const 61 { 62 return (!((*this) < rhs) && !(rhs < (*this))); 63 } 64 operator !=(LibraryEntry const & rhs) const65 bool operator!=(LibraryEntry const & rhs) const 66 { 67 return (((*this) < rhs) || (rhs < (*this))); 68 } 69 operator <(LibraryEntry const & rhs) const70 bool operator<(LibraryEntry const & rhs) const 71 { 72 bool comparison = false; 73 74 Main::Settings const & settings = Main::Settings::Instance(); 75 76 if (type_ == ArtistType) 77 { 78 comparison = Algorithm::icompare(artist_, rhs.artist_, settings.Get(Setting::IgnoreTheSort), settings.Get(Setting::IgnoreCaseSort)); 79 } 80 else if (type_ == AlbumType) 81 { 82 comparison = Algorithm::icompare(album_, rhs.album_, settings.Get(Setting::IgnoreTheSort), settings.Get(Setting::IgnoreCaseSort)); 83 } 84 else if ((song_ != NULL) && (rhs.song_ != NULL)) 85 { 86 uint32_t track = atoi(song_->Track().c_str()); 87 uint32_t rhsTrack = atoi(rhs.song_->Track().c_str()); 88 uint32_t disc = atoi(song_->Disc().c_str()); 89 uint32_t rhsDisc = atoi(rhs.song_->Disc().c_str()); 90 comparison = ((track < rhsTrack) && (disc <= rhsDisc)); 91 } 92 93 return comparison; 94 } 95 96 public: ~LibraryEntry()97 ~LibraryEntry() 98 { 99 if (song_ != NULL) 100 { 101 song_->SetEntry(NULL); 102 delete song_; 103 } 104 105 song_ = NULL; 106 107 FOREACH(auto child, children_) 108 { 109 if ((child) && (child->Parent() == this)) 110 { 111 delete child; 112 } 113 } 114 115 children_.clear(); 116 } 117 AddedToPlaylist()118 void AddedToPlaylist() 119 { 120 ++childrenInPlaylist_; 121 122 if ((parent_ != NULL) && (childrenInPlaylist_ == 1)) 123 { 124 parent_->AddPartial(); 125 } 126 127 if ((parent_ != NULL) && ((childrenInPlaylist_ == static_cast<int32_t>(children_.size())) || (type_ == Mpc::SongType))) 128 { 129 parent_->AddedToPlaylist(); 130 } 131 } 132 RemovedFromPlaylist()133 void RemovedFromPlaylist() 134 { 135 if ((parent_ != NULL) && ((childrenInPlaylist_ == static_cast<int32_t>(children_.size())) || (type_ == Mpc::SongType))) 136 { 137 parent_->RemovedFromPlaylist(); 138 } 139 140 if (childrenInPlaylist_ > 0) 141 { 142 --childrenInPlaylist_; 143 } 144 145 if ((parent_ != NULL) && (childrenInPlaylist_ == 0)) 146 { 147 parent_->RemovePartial(); 148 } 149 } 150 AddPartial()151 void AddPartial() 152 { 153 ++partial_; 154 155 if (parent_ != NULL) 156 { 157 parent_->AddPartial(); 158 } 159 } 160 RemovePartial()161 void RemovePartial() 162 { 163 if (partial_ > 0) 164 { 165 --partial_; 166 } 167 168 if (parent_ != NULL) 169 { 170 parent_->RemovePartial(); 171 } 172 } 173 174 public: Parent()175 LibraryEntry * Parent() 176 { 177 return parent_; 178 } 179 InPlaylistCount()180 uint32_t InPlaylistCount() 181 { 182 return childrenInPlaylist_; 183 } 184 185 private: 186 LibraryEntry(LibraryEntry & entry); 187 LibraryEntry & operator=(LibraryEntry & entry); 188 189 private: 190 class LibraryComparator 191 { 192 public: operator ()(LibraryEntry * i,LibraryEntry * j)193 bool operator() (LibraryEntry * i, LibraryEntry * j) { return (*i<*j); }; 194 }; 195 196 public: 197 EntryType type_; 198 std::string artist_; 199 std::string album_; 200 Mpc::Song * song_; 201 bool expanded_; 202 LibraryEntryVector children_; 203 LibraryEntry * parent_; 204 int32_t childrenInPlaylist_; 205 int32_t partial_; 206 }; 207 208 209 // Library class 210 class Library : public Main::Buffer<LibraryEntry *> 211 { 212 public: 213 using Main::Buffer<LibraryEntry *>::Sort; 214 using Main::Buffer<LibraryEntry *>::Add; 215 216 Library(); 217 ~Library(); 218 219 public: 220 Mpc::Song * Song(std::string uri) const; 221 222 void Clear(bool Delete = true); 223 void Sort(); 224 void Sort(LibraryEntry * entry); 225 void Add(Mpc::Song * song); 226 void AddToPlaylist(Mpc::Song::SongCollection Collection, Mpc::Client & client, Mpc::ClientState & clientState, uint32_t position); 227 void RemoveFromPlaylist(Mpc::Song::SongCollection Collection, Mpc::Client & client, Mpc::ClientState & clientState, uint32_t position); 228 229 void CreateVariousArtist(); 230 Mpc::LibraryEntry * CreateArtistEntry(std::string artist); 231 Mpc::LibraryEntry * CreateAlbumEntry(Mpc::Song * song); 232 233 void ForEachChild(uint32_t index, FUNCTION<void (Mpc::Song *)> callback) const; 234 void ForEachChild(uint32_t index, FUNCTION<void (Mpc::LibraryEntry *)> callback) const; 235 void ForEachSong(FUNCTION<void (Mpc::Song *)> callback) const; 236 void ForEachParent(FUNCTION<void (Mpc::LibraryEntry *)> callback) const; 237 238 public: 239 void Expand(uint32_t line); 240 void Collapse(uint32_t line); 241 242 std::string String(uint32_t position) const; 243 std::string PrintString(uint32_t position) const; 244 245 private: 246 void RecreateLibraryFromURIs(); 247 248 void AddToPlaylist(Mpc::Client & client, Mpc::ClientState & clientState, Mpc::LibraryEntry const * const entry, int32_t position = -1); 249 void RemoveFromPlaylist(Mpc::Client & client, Mpc::LibraryEntry const * const entry); 250 void DeleteEntry(LibraryEntry * const entry); 251 void CheckIfVariousRemoved(LibraryEntry * const entry); 252 void RemoveAndUnexpand(LibraryEntry * const entry); 253 254 private: 255 Main::Settings & settings_; 256 std::map<std::string, Mpc::Song *> uriMap_; 257 Mpc::LibraryEntry * variousArtist_; 258 Mpc::LibraryEntry * lastAlbumEntry_; 259 Mpc::LibraryEntry * lastArtistEntry_; 260 }; 261 262 //Flag a library entry as not expanded, this does not actually collapse it however 263 void MarkUnexpanded(LibraryEntry * const entry); 264 } 265 266 #endif 267 /* vim: set sw=3 ts=3: */ 268