1 /* This file is part of Clementine.
2    Copyright 2009-2012, David Sansome <me@davidsansome.com>
3    Copyright 2010, 2012, 2014, John Maguire <john.maguire@gmail.com>
4    Copyright 2011, Paweł Bara <keirangtp@gmail.com>
5    Copyright 2011, Andrea Decorte <adecorte@gmail.com>
6    Copyright 2012, Anand <anandtp@live.in>
7    Copyright 2013, Andreas <asfa194@gmail.com>
8    Copyright 2013, Kevin Cox <kevincox.ca@gmail.com>
9    Copyright 2014, Arnaud Bienner <arnaud.bienner@gmail.com>
10    Copyright 2014, Mark Furneaux <mark@romaco.ca>
11    Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
12 
13    Clementine is free software: you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation, either version 3 of the License, or
16    (at your option) any later version.
17 
18    Clementine is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21    GNU General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
25 */
26 
27 #ifndef CORE_PLAYER_H_
28 #define CORE_PLAYER_H_
29 
30 #include <memory>
31 
32 #include <QDateTime>
33 #include <QObject>
34 #include <QSettings>
35 
36 #include "config.h"
37 #include "core/song.h"
38 #include "core/urlhandler.h"
39 #include "covers/albumcoverloader.h"
40 #include "engines/engine_fwd.h"
41 #include "playlist/playlistitem.h"
42 
43 class Application;
44 class Scrobbler;
45 
46 class PlayerInterface : public QObject {
47   Q_OBJECT
48 
49  public:
QObject(parent)50   explicit PlayerInterface(QObject* parent = nullptr) : QObject(parent) {}
51 
52   virtual EngineBase* engine() const = 0;
53   virtual Engine::State GetState() const = 0;
54   virtual int GetVolume() const = 0;
55 
56   virtual PlaylistItemPtr GetCurrentItem() const = 0;
57   virtual PlaylistItemPtr GetItemAt(int pos) const = 0;
58 
59   virtual void RegisterUrlHandler(UrlHandler* handler) = 0;
60   virtual void UnregisterUrlHandler(UrlHandler* handler) = 0;
61 
62  public slots:
63   virtual void ReloadSettings() = 0;
64 
65   // Manual track change to the specified track
66   virtual void PlayAt(int i, Engine::TrackChangeFlags change,
67                       bool reshuffle) = 0;
68 
69   // If there's currently a song playing, pause it, otherwise play the track
70   // that was playing last, or the first one on the playlist
71   virtual void PlayPause() = 0;
72   virtual void RestartOrPrevious() = 0;
73 
74   // Skips this track.  Might load more of the current radio station.
75   virtual void Next() = 0;
76 
77   virtual void Previous() = 0;
78   virtual void SetVolume(int value) = 0;
79   virtual void VolumeUp() = 0;
80   virtual void VolumeDown() = 0;
81   virtual void SeekTo(int seconds) = 0;
82   // Moves the position of the currently playing song five seconds forward.
83   virtual void SeekForward() = 0;
84   // Moves the position of the currently playing song five seconds backwards.
85   virtual void SeekBackward() = 0;
86 
87   virtual void CurrentMetadataChanged(const Song& metadata) = 0;
88 
89   virtual void Mute() = 0;
90   virtual void Pause() = 0;
91   virtual void Stop(bool stop_after = false) = 0;
92   virtual void Play() = 0;
93   virtual void ShowOSD() = 0;
94 
95 signals:
96   void Playing();
97   void Paused();
98   void Stopped();
99   void PlaylistFinished();
100   void VolumeChanged(int volume);
101   void Error(const QString& message);
102   void TrackSkipped(PlaylistItemPtr old_track);
103   // Emitted when there's a manual change to the current's track position.
104   void Seeked(qlonglong microseconds);
105 
106   // Emitted when Player has processed a request to play another song. This
107   // contains
108   // the URL of the song and a flag saying whether it was able to play the song.
109   void SongChangeRequestProcessed(const QUrl& url, bool valid);
110 
111   // The toggle parameter is true when user requests to toggle visibility for
112   // Pretty OSD
113   void ForceShowOSD(Song, bool toggle);
114 };
115 
116 class Player : public PlayerInterface {
117   Q_OBJECT
118 
119  public:
120   explicit Player(Application* app, QObject* parent = nullptr);
121   ~Player();
122 
123   static const char* kSettingsGroup;
124 
125   // Don't change the values: they are saved in preferences
126   enum PreviousBehaviour {
127     PreviousBehaviour_DontRestart = 1,
128     PreviousBehaviour_Restart = 2
129   };
130 
131   void Init();
132 
engine()133   EngineBase* engine() const { return engine_.get(); }
GetState()134   Engine::State GetState() const { return last_state_; }
135   int GetVolume() const;
136 
GetCurrentItem()137   PlaylistItemPtr GetCurrentItem() const { return current_item_; }
138   PlaylistItemPtr GetItemAt(int pos) const;
139 
140   void RegisterUrlHandler(UrlHandler* handler);
141   void UnregisterUrlHandler(UrlHandler* handler);
142 
143   const UrlHandler* HandlerForUrl(const QUrl& url) const;
144 
145   bool PreviousWouldRestartTrack() const;
146 
147  public slots:
148   void ReloadSettings();
149 
150   void PlayAt(int i, Engine::TrackChangeFlags change, bool reshuffle);
151   void PlayPause();
152   void RestartOrPrevious();
153   void Next();
154   void Previous();
155   void SetVolume(int value);
VolumeUp()156   void VolumeUp() { SetVolume(GetVolume() + 5); }
VolumeDown()157   void VolumeDown() { SetVolume(GetVolume() - 5); }
158   void SeekTo(int seconds);
159   void SeekForward();
160   void SeekBackward();
161 
162   void CurrentMetadataChanged(const Song& metadata);
163 
164   void Mute();
165   void Pause();
166   void Stop(bool stop_after = false);
167   void StopAfterCurrent();
168   void IntroPointReached();
169   void Play();
170   void ShowOSD();
171   void TogglePrettyOSD();
172 
173  private slots:
174   void EngineStateChanged(Engine::State);
175   void EngineMetadataReceived(const Engine::SimpleMetaBundle& bundle);
176   void TrackAboutToEnd();
177   void TrackEnded();
178   // Play the next item on the playlist - disregarding radio stations like
179   // last.fm that might have more tracks.
180   void NextItem(Engine::TrackChangeFlags change);
181   void PreviousItem(Engine::TrackChangeFlags change);
182 
183   void NextInternal(Engine::TrackChangeFlags);
184 
185   void ValidSongRequested(const QUrl&);
186   void InvalidSongRequested(const QUrl&);
187 
188   void UrlHandlerDestroyed(QObject* object);
189   void HandleLoadResult(const UrlHandler::LoadResult& result);
190 
191  private:
192   // Returns true if we were supposed to stop after this track.
193   bool HandleStopAfter();
194 
195  private:
196   Application* app_;
197   Scrobbler* lastfm_;
198   QSettings settings_;
199 
200   PlaylistItemPtr current_item_;
201 
202   std::unique_ptr<EngineBase> engine_;
203   Engine::TrackChangeFlags stream_change_type_;
204   Engine::State last_state_;
205   int nb_errors_received_;
206 
207   QMap<QString, UrlHandler*> url_handlers_;
208 
209   QUrl loading_async_;
210 
211   int volume_before_mute_;
212 
213   QDateTime last_pressed_previous_;
214   PreviousBehaviour menu_previousmode_;
215   int seek_step_sec_;
216 };
217 
218 #endif  // CORE_PLAYER_H_
219