1 /*
2  * Strawberry Music Player
3  * This file was part of Amarok / Clementine
4  * Copyright 2003 Mark Kretschmann
5  * Copyright 2004 - 2005 Max Howell, <max.howell@methylblue.com>
6  * Copyright 2010 David Sansome <me@davidsansome.com>
7  * Copyright 2017-2021 Jonas Kvinge <jonas@jkvinge.net>
8  *
9  * Strawberry is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Strawberry is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Strawberry.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 #ifndef ENGINEBASE_H
25 #define ENGINEBASE_H
26 
27 #include "config.h"
28 
29 #include <sys/types.h>
30 #include <cstdint>
31 #include <vector>
32 
33 #include <QtGlobal>
34 #include <QObject>
35 #include <QList>
36 #include <QMetaType>
37 #include <QVariant>
38 #include <QString>
39 #include <QUrl>
40 
41 #include "engine_fwd.h"
42 #include "enginetype.h"
43 #include "devicefinders.h"
44 #include "core/song.h"
45 
46 namespace Engine {
47 
48 struct SimpleMetaBundle;
49 
50 typedef std::vector<int16_t> Scope;
51 
52 class Base : public QObject {
53   Q_OBJECT
54 
55  protected:
56   Base(const EngineType type = EngineType::None, QObject *parent = nullptr);
57 
58  public:
59   ~Base() override;
60 
61   struct OutputDetails {
62     QString name;
63     QString description;
64     QString iconname;
65   };
66   typedef QList<OutputDetails> OutputDetailsList;
67 
68   virtual bool Init() = 0;
69   virtual State state() const = 0;
70   virtual void StartPreloading(const QUrl&, const QUrl&, const bool, const qint64, const qint64) {}
71   virtual bool Load(const QUrl &stream_url, const QUrl &original_url, const TrackChangeFlags change, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec);
72   virtual bool Play(const quint64 offset_nanosec) = 0;
73   virtual void Stop(const bool stop_after = false) = 0;
74   virtual void Pause() = 0;
75   virtual void Unpause() = 0;
76   virtual void Seek(const quint64 offset_nanosec) = 0;
77   virtual void SetVolumeSW(const uint percent) = 0;
78 
79   virtual qint64 position_nanosec() const = 0;
80   virtual qint64 length_nanosec() const = 0;
81 
82   virtual const Scope &scope(const int chunk_length) { Q_UNUSED(chunk_length); return scope_; }
83 
84   // Sets new values for the beginning and end markers of the currently playing song.
85   // This doesn't change the state of engine or the stream's current position.
86   virtual void RefreshMarkers(const quint64 beginning_nanosec, const qint64 end_nanosec) {
87     beginning_nanosec_ = beginning_nanosec;
88     end_nanosec_ = end_nanosec;
89   }
90 
91   virtual OutputDetailsList GetOutputsList() const = 0;
92   virtual bool ValidOutput(const QString &output) = 0;
93   virtual QString DefaultOutput() = 0;
94   virtual bool CustomDeviceSupport(const QString &output) = 0;
95   virtual bool ALSADeviceSupport(const QString &output) = 0;
96 
97   // Plays a media stream represented with the URL 'u' from the given 'beginning' to the given 'end' (usually from 0 to a song's length).
98   // Both markers should be passed in nanoseconds. 'end' can be negative, indicating that the real length of 'u' stream is unknown.
99   bool Play(const QUrl &stream_url, const QUrl &original_url, const TrackChangeFlags flags, const bool force_stop_at_end, const quint64 beginning_nanosec, const qint64 end_nanosec, const quint64 offset_nanosec);
100   void SetVolume(const uint value);
101   static uint MakeVolumeLogarithmic(const uint volume);
102 
103  public slots:
104   virtual void ReloadSettings();
105 
106  protected:
107   void EmitAboutToEnd();
108 
109  public:
110 
111   // Simple accessors
112   EngineType type() const { return type_; }
113   bool volume_control() const { return volume_control_; }
114   inline uint volume() const { return volume_; }
115 
116   bool is_fadeout_enabled() const { return fadeout_enabled_; }
117   bool is_crossfade_enabled() const { return crossfade_enabled_; }
118   bool is_autocrossfade_enabled() const { return autocrossfade_enabled_; }
119   bool crossfade_same_album() const { return crossfade_same_album_; }
120   bool IsEqualizerEnabled() { return equalizer_enabled_; }
121 
122   static const int kScopeSize = 1024;
123 
124   QVariant device() { return device_; }
125 
126  public slots:
127   virtual void SetStereoBalancerEnabled(const bool) {}
128   virtual void SetStereoBalance(const float) {}
129   virtual void SetEqualizerEnabled(const bool) {}
130   virtual void SetEqualizerParameters(const int, const QList<int>&) {}
131 
132  signals:
133   // Emitted when crossfading is enabled and the track is crossfade_duration_ away from finishing
134   void TrackAboutToEnd();
135 
136   void TrackEnded();
137 
138   void FadeoutFinishedSignal();
139 
140   void StatusText(QString text);
141   void Error(QString text);
142 
143   // Emitted when there was a fatal error
144   void FatalError();
145   // Emitted when Engine was unable to play a song with the given QUrl.
146   void InvalidSongRequested(QUrl url);
147   // Emitted when Engine successfully started playing a song with the given QUrl.
148   void ValidSongRequested(QUrl url);
149 
150   void MetaData(Engine::SimpleMetaBundle);
151 
152   // Signals that the engine's state has changed (a stream was stopped for example).
153   // Always use the state from event, because it's not guaranteed that immediate subsequent call to state() won't return a stale value.
154   void StateChanged(Engine::State);
155 
156  protected:
157 
158   struct PluginDetails {
159     QString name;
160     QString description;
161     QString iconname;
162   };
163   typedef QList<PluginDetails> PluginDetailsList;
164 
165   EngineType type_;
166   bool volume_control_;
167   uint volume_;
168   quint64 beginning_nanosec_;
169   qint64 end_nanosec_;
170   QUrl stream_url_;
171   QUrl original_url_;
172   Scope scope_;
173   bool buffering_;
174   bool equalizer_enabled_;
175 
176   // Settings
177   QString output_;
178   QVariant device_;
179 
180   // ReplayGain
181   bool rg_enabled_;
182   int rg_mode_;
183   double rg_preamp_;
184   double rg_fallbackgain_;
185   bool rg_compression_;
186 
187   // Buffering
188   quint64 buffer_duration_nanosec_;
189   double buffer_low_watermark_;
190   double buffer_high_watermark_;
191 
192   // Fadeout
193   bool fadeout_enabled_;
194   bool crossfade_enabled_;
195   bool autocrossfade_enabled_;
196   bool crossfade_same_album_;
197   bool fadeout_pause_enabled_;
198   qint64 fadeout_duration_;
199   qint64 fadeout_duration_nanosec_;
200   qint64 fadeout_pause_duration_;
201   qint64 fadeout_pause_duration_nanosec_;
202 
203   // Proxy
204   QString proxy_address_;
205   bool proxy_authentication_;
206   QString proxy_user_;
207   QString proxy_pass_;
208 
209   // Channels
210   bool channels_enabled_;
211   int channels_;
212 
213  private:
214   bool about_to_end_emitted_;
215   Q_DISABLE_COPY(Base)
216 
217 };
218 
219 struct SimpleMetaBundle {
220   SimpleMetaBundle() : type(Type_Any), length(-1), year(-1), track(-1), filetype(Song::FileType_Unknown), samplerate(-1), bitdepth(-1), bitrate(-1) {}
221   enum Type {
222     Type_Any,
223     Type_Current,
224     Type_Next,
225   };
226   Type type;
227   QUrl url;
228   QUrl stream_url;
229   QString title;
230   QString artist;
231   QString album;
232   QString comment;
233   QString genre;
234   qint64 length;
235   int year;
236   int track;
237   Song::FileType filetype;
238   int samplerate;
239   int bitdepth;
240   qint64 bitrate;
241   QString lyrics;
242 };
243 
244 }  // namespace Engine
245 
246 Q_DECLARE_METATYPE(EngineBase::OutputDetails)
247 
248 #endif  // ENGINEBASE_H
249