1 /*
2    Vimpc
3    Copyright (C) 2010 - 2012 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    mpdclient.hpp - provides interaction with the music player daemon
19    */
20 
21 #ifndef __MPC__CLIENT
22 #define __MPC__CLIENT
23 
24 
25 #include <mpd/client.h>
26 
27 #include "compiler.hpp"
28 #include "output.hpp"
29 #include "screen.hpp"
30 #include "buffers.hpp"
31 #include "buffer/library.hpp"
32 #include "buffer/list.hpp"
33 #include "window/debug.hpp"
34 
35 // The library check in 2.1.0 doesn't seem to work
36 // since we don't support versions older than that anyway, just return false
37 // instead of using the check macro
38 #if ((LIBMPDCLIENT_MAJOR_VERSION <= 2) && (LIBMPDCLIENT_MINOR_VERSION <= 1))
39 #undef LIBMPDCLIENT_CHECK_VERSION
40 #define LIBMPDCLIENT_CHECK_VERSION(major, minor, patch) \
41     ((major) < LIBMPDCLIENT_MAJOR_VERSION || \
42      ((major) == LIBMPDCLIENT_MAJOR_VERSION && \
43       ((minor) < LIBMPDCLIENT_MINOR_VERSION || \
44        ((minor) == LIBMPDCLIENT_MINOR_VERSION && \
45         (patch) <= LIBMPDCLIENT_PATCH_VERSION))))
46 #endif
47 
48 #ifndef LIBMPDCLIENT_MAJOR_VERSION
49 #define LIBMPDCLIENT_MAJOR_VERSION 0
50 #endif
51 #ifndef LIBMPDCLIENT_MINOR_VERSION
52 #define LIBMPDCLIENT_MINOR_VERSION 0
53 #endif
54 #ifndef LIBMPDCLIENT_PATCH_VERSION
55 #define LIBMPDCLIENT_PATCH_VERSION 0
56 #endif
57 
58 namespace Main
59 {
60    class Settings;
61    class Vimpc;
62 }
63 
64 namespace Ui
65 {
66    class Screen;
67 }
68 
69 // \todo cache all the values that we can
70 namespace Mpc
71 {
72    class Client;
73    class Output;
74    class Song;
75 
76    uint32_t SecondsToMinutes(uint32_t duration);
77    uint32_t RemainingSeconds(uint32_t duration);
78 
79    class CommandList
80    {
81       public:
82          CommandList(Mpc::Client & client, bool condition = true);
83          ~CommandList();
84 
85       private:
86          bool          condition_;
87          Mpc::Client & client_;
88    };
89 
90    class Client
91    {
92       friend class Mpc::CommandList;
93 
94    public:
95       Client(Main::Vimpc * vimpc, Main::Settings & settings, Mpc::Lists & lists, Ui::Screen & screen);
96       ~Client();
97 
98    public:
99       void QueueCommand(FUNCTION<void()> const & function);
100       void WaitForCompletion();
101 
102    private:
103       Client(Client & client);
104       Client & operator=(Client & client);
105 
106    public:
107       // Mpd Connections
108       void Connect(std::string const & hostname = "", uint16_t port = 0, uint32_t timeout_ms = 0);
109       void ConnectImpl(std::string const & hostname = "", uint16_t port = 0, uint32_t timeout_ms = 0);
110       void Disconnect();
111       void Reconnect();
112       void Password(std::string const & password);
113 
114    public:
115       // Playback functions
116       void Play(uint32_t playId);
117       void Pause();
118       void Stop();
119       void Next();
120       void Previous();
121       void Seek(int32_t Offset);
122       void SeekTo(uint32_t Time);
123       void SeekToPercent(double Percent);
124 
125    public:
126       // Toggle settings
127       void SetRandom(bool random);
128       void SetSingle(bool single);
129       void SetConsume(bool consume);
130       void SetRepeat(bool repeat);
131       void SetCrossfade(bool crossfade);
132       void SetCrossfade(uint32_t crossfade);
133       void SetVolume(uint32_t volume);
134       void SetMute(bool mute);
135       void DeltaVolume(int32_t Delta);
136 
137       // Toggle settings
138       void ToggleRandom();
139       void ToggleSingle();
140       void ToggleConsume();
141       void ToggleRepeat();
142       void ToggleCrossfade();
143 
144    public:
145       // Playlist editing
146       void Shuffle();
147       void Move(uint32_t position1, uint32_t position2);
148       void Swap(uint32_t position1, uint32_t position2);
149 
150    public:
151       // Playlist management
152       bool HasPlaylist(std::string const & name);
153       bool HasLoadedPlaylist();
154       void SaveLoadedPlaylist();
155       void CreatePlaylist(std::string const & name);
156       void SavePlaylist(std::string const & name);
157       void LoadPlaylist(std::string const & name);
158       void AppendPlaylist(std::string const & name);
159       void RemovePlaylist(std::string const & name);
160       void AddToNamedPlaylist(std::string const & name, Mpc::Song * song);
161 
162       void PlaylistContents(std::string const & name);
163       void PlaylistContentsForRemove(std::string const & name);
164 
165    public:
166       // Outputs
167       void SetOutput(Mpc::Output * output, bool enable);
168       void EnableOutput(Mpc::Output * output);
169       void DisableOutput(Mpc::Output * output);
170 
171    public:
172       // Queue manipulation
173       void Add(Mpc::Song * song);
174       void Add(std::vector<Mpc::Song *> song);
175       void Add(Mpc::Song & song);
176       void Add(Mpc::Song & song, uint32_t position);
177       void AddAllSongs();
178 
179       //! This add is only used by a command when a full uri is specified
180       //! it should not be used to add songs from the library, you should use the
181       //! versions above for that purpose
182       void Add(std::string const & URI);
183 
184       // Call after all songs have been added
185       void AddComplete();
186 
187       void Delete(uint32_t position);
188       void Delete(uint32_t position1, uint32_t position2);
189       void Clear();
190 
191    public:
192       // Searching the database
193       void SearchAny(std::string const & search, bool exact = false);
194       void SearchArtist(std::string const & search, bool exact = false);
195       void SearchAlbum(std::string const & search, bool exact = false);
196       void SearchGenre(std::string const & search, bool exact = false);
197       void SearchSong(std::string const & search, bool exact = false);
198       void AddAllSearchResults();
199       void SearchResults(std::string const & name);
200 
201    public:
202       // Database state
203       void Rescan(std::string const & Path);
204       void Update(std::string const & Path);
205       void StartCommandList();
206       void SendCommandList();
207       void UpdateCurrentSong();
208       void UpdateStatus(bool ExpectUpdate = false);
209       void QueueMetaChanges();
210 
211    public:
212       void GetAllOutputs();
213       void GetAllMetaInformation();
214       void GetAllMetaFromRoot();
215 
216    private:
217       bool Connected() const;
218       void IncrementTime(long time);
219       void StateEvent();
220       void CheckForEvents();
221       void IdleMode();
222       void ExitIdleMode();
223       void ClientQueueExecutor(Mpc::Client * client);
224       void SetStateAndEvent(int, bool & state, bool value);
225 
226    private:
227       void ClearCommand();
228       bool IsPasswordRequired();
229       void Initialise();
230 
231    private:
232       unsigned int QueueVersion();
233       Song * CreateSong(mpd_song const * const) const;
234 
235    private:
236       void GetVersion();
237       bool CheckError();
238       void DeleteConnection();
239 
240    private:
241       Main::Vimpc *           vimpc_;
242       Main::Settings &        settings_;
243       struct mpd_connection * connection_;
244       int                     fd_;
245 
246       std::string             hostname_;
247       uint16_t                port_;
248       uint32_t                versionMajor_;
249       uint32_t                versionMinor_;
250       uint32_t                versionPatch_;
251       long                    timeSinceUpdate_;
252       bool                    retried_;
253       bool                    ready_;
254 
255       uint32_t                volume_;
256       uint32_t                mVolume_;
257       bool                    mute_;
258       bool                    updating_;
259       bool                    random_;
260       bool                    repeat_;
261       bool                    single_;
262       bool                    consume_;
263       bool                    crossfade_;
264       uint32_t                crossfadeTime_;
265       uint32_t                elapsed_;
266       uint32_t                mpdelapsed_;
267       mpd_state               state_;
268       mpd_state               mpdstate_;
269 
270       struct mpd_song *       currentSong_;
271       struct mpd_status *     currentStatus_;
272       int32_t                 currentSongId_;
273       uint32_t                totalNumberOfSongs_;
274       std::string             currentSongURI_;
275       std::string             currentState_;
276 
277       Mpc::Lists *            lists_;
278       std::string             loadedList_;
279 
280       Ui::Screen &            screen_;
281       int                     queueVersion_;
282       int                     oldVersion_;
283       bool                    forceUpdate_;
284       bool                    listMode_;
285       bool                    idleMode_;
286       bool                    queueUpdate_;
287       bool                    autoscroll_;
288       Thread                  clientThread_;
289 
290       bool                    error_;
291    };
292 }
293 
294 #endif
295 /* vim: set sw=3 ts=3: */
296