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