1 /* This file is part of Clementine. 2 Copyright 2010, David Sansome <me@davidsansome.com> 3 4 Clementine is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 Clementine is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with Clementine. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef GSTENGINEPIPELINE_H 19 #define GSTENGINEPIPELINE_H 20 21 #include <memory> 22 23 #include <QBasicTimer> 24 #include <QFuture> 25 #include <QMutex> 26 #include <QObject> 27 #include <QThreadPool> 28 #include <QTimeLine> 29 #include <QUrl> 30 31 #include <gst/gst.h> 32 33 #include "engine_fwd.h" 34 35 class GstElementDeleter; 36 class GstEngine; 37 class BufferConsumer; 38 39 struct GstQueue; 40 struct GstURIDecodeBin; 41 42 class GstEnginePipeline : public QObject { 43 Q_OBJECT 44 45 public: 46 GstEnginePipeline(GstEngine* engine); 47 ~GstEnginePipeline(); 48 49 // Globally unique across all pipelines. id()50 int id() const { return id_; } 51 52 // Call these setters before Init 53 void set_output_device(const QString& sink, const QVariant& device); 54 void set_replaygain(bool enabled, int mode, float preamp, bool compression); 55 void set_buffer_duration_nanosec(qint64 duration_nanosec); 56 void set_buffer_min_fill(int percent); 57 void set_mono_playback(bool enabled); 58 void set_sample_rate(int rate); 59 60 // Creates the pipeline, returns false on error 61 bool InitFromUrl(const QUrl& url, qint64 end_nanosec); 62 bool InitFromString(const QString& pipeline); 63 64 // BufferConsumers get fed audio data. Thread-safe. 65 void AddBufferConsumer(BufferConsumer* consumer); 66 void RemoveBufferConsumer(BufferConsumer* consumer); 67 void RemoveAllBufferConsumers(); 68 69 // Control the music playback 70 QFuture<GstStateChangeReturn> SetState(GstState state); 71 Q_INVOKABLE bool Seek(qint64 nanosec); 72 void SetEqualizerEnabled(bool enabled); 73 void SetEqualizerParams(int preamp, const QList<int>& band_gains); 74 void SetVolume(int percent); 75 void SetStereoBalance(float value); 76 void StartFader(qint64 duration_nanosec, 77 QTimeLine::Direction direction = QTimeLine::Forward, 78 QTimeLine::CurveShape shape = QTimeLine::LinearCurve, 79 bool use_fudge_timer = true); 80 81 // If this is set then it will be loaded automatically when playback finishes 82 // for gapless playback 83 void SetNextUrl(const QUrl& url, qint64 beginning_nanosec, 84 qint64 end_nanosec); has_next_valid_url()85 bool has_next_valid_url() const { return next_url_.isValid(); } 86 87 // Get information about the music playback url()88 QUrl url() const { return url_; } is_valid()89 bool is_valid() const { return valid_; } 90 // Please note that this method (unlike GstEngine's.position()) is 91 // multiple-section media unaware. 92 qint64 position() const; 93 // Please note that this method (unlike GstEngine's.length()) is 94 // multiple-section media unaware. 95 qint64 length() const; 96 // Returns this pipeline's state. May return GST_STATE_NULL if the state check 97 // timed out. The timeout value is a reasonable default. 98 GstState state() const; segment_start()99 qint64 segment_start() const { return segment_start_; } 100 101 // Don't allow the user to change the playback state (playing/paused) while 102 // the pipeline is buffering. is_buffering()103 bool is_buffering() const { return buffering_; } 104 redirect_url()105 QUrl redirect_url() const { return redirect_url_; } 106 source_device()107 QString source_device() const { return source_device_; } 108 109 public slots: 110 void SetVolumeModifier(qreal mod); 111 112 signals: 113 void EndOfStreamReached(int pipeline_id, bool has_next_track); 114 void MetadataFound(int pipeline_id, const Engine::SimpleMetaBundle& bundle); 115 // This indicates an error, delegated from GStreamer, in the pipeline. 116 // The message, domain and error_code are related to GStreamer's GError. 117 void Error(int pipeline_id, const QString& message, int domain, 118 int error_code); 119 void FaderFinished(); 120 121 void BufferingStarted(); 122 void BufferingProgress(int percent); 123 void BufferingFinished(); 124 125 protected: 126 void timerEvent(QTimerEvent*); 127 128 private: 129 // Static callbacks. The GstEnginePipeline instance is passed in the last 130 // argument. 131 static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage*, gpointer); 132 static gboolean BusCallback(GstBus*, GstMessage*, gpointer); 133 static void NewPadCallback(GstElement*, GstPad*, gpointer); 134 static GstPadProbeReturn HandoffCallback(GstPad*, GstPadProbeInfo*, gpointer); 135 static GstPadProbeReturn EventHandoffCallback(GstPad*, GstPadProbeInfo*, 136 gpointer); 137 static GstPadProbeReturn DecodebinProbe(GstPad*, GstPadProbeInfo*, gpointer); 138 static void SourceDrainedCallback(GstURIDecodeBin*, gpointer); 139 static void SourceSetupCallback(GstURIDecodeBin*, GParamSpec* pspec, 140 gpointer); 141 static void TaskEnterCallback(GstTask*, GThread*, gpointer); 142 143 void TagMessageReceived(GstMessage*); 144 void ErrorMessageReceived(GstMessage*); 145 void ElementMessageReceived(GstMessage*); 146 void StateChangedMessageReceived(GstMessage*); 147 void BufferingMessageReceived(GstMessage*); 148 void StreamStatusMessageReceived(GstMessage*); 149 150 QString ParseTag(GstTagList* list, const char* tag) const; 151 152 bool Init(); 153 GstElement* CreateDecodeBinFromString(const char* pipeline); 154 GstElement* CreateDecodeBinFromUrl(const QUrl& url); 155 156 void UpdateVolume(); 157 void UpdateEqualizer(); 158 void UpdateStereoBalance(); 159 bool ReplaceDecodeBin(GstElement* new_bin); 160 bool ReplaceDecodeBin(const QUrl& url); 161 162 void TransitionToNext(); 163 164 // If the decodebin is special (ie. not really a uridecodebin) then it'll have 165 // a src pad immediately and we can link it after everything's created. 166 void MaybeLinkDecodeToAudio(); 167 168 private slots: 169 void FaderTimelineFinished(); 170 171 private: 172 static const int kGstStateTimeoutNanosecs; 173 static const int kFaderFudgeMsec; 174 static const int kEqBandCount; 175 static const int kEqBandFrequencies[]; 176 177 static GstElementDeleter* sElementDeleter; 178 179 GstEngine* engine_; 180 181 // Using == to compare two pipelines is a bad idea, because new ones often 182 // get created in the same address as old ones. This ID will be unique for 183 // each pipeline. 184 // Threading warning: access to the static ID field isn't protected by a 185 // mutex because all pipeline creation is currently done in the main thread. 186 static int sId; 187 int id_; 188 189 // General settings for the pipeline 190 bool valid_; 191 QString sink_; 192 QVariant device_; 193 194 // These get called when there is a new audio buffer available 195 QList<BufferConsumer*> buffer_consumers_; 196 QMutex buffer_consumers_mutex_; 197 qint64 segment_start_; 198 bool segment_start_received_; 199 bool emit_track_ended_on_stream_start_; 200 bool emit_track_ended_on_time_discontinuity_; 201 qint64 last_buffer_offset_; 202 203 // Equalizer 204 bool eq_enabled_; 205 int eq_preamp_; 206 QList<int> eq_band_gains_; 207 208 // Stereo balance. 209 // From -1.0 - 1.0 210 // -1.0 is left, 1.0 is right. 211 float stereo_balance_; 212 213 // ReplayGain 214 bool rg_enabled_; 215 int rg_mode_; 216 float rg_preamp_; 217 bool rg_compression_; 218 219 // Buffering 220 quint64 buffer_duration_nanosec_; 221 int buffer_min_fill_; 222 bool buffering_; 223 224 bool mono_playback_; 225 int sample_rate_; 226 227 // The URL that is currently playing, and the URL that is to be preloaded 228 // when the current track is close to finishing. 229 QUrl url_; 230 QUrl next_url_; 231 232 // If this is > 0 then the pipeline will be forced to stop when playback goes 233 // past this position. 234 qint64 end_offset_nanosec_; 235 236 // We store the beginning and end for the preloading song too, so we can just 237 // carry on without reloading the file if the sections carry on from each 238 // other. 239 qint64 next_beginning_offset_nanosec_; 240 qint64 next_end_offset_nanosec_; 241 242 // Set temporarily when moving to the next contiguous section in a multi-part 243 // file. 244 bool ignore_next_seek_; 245 246 // Set temporarily when switching out the decode bin, so metadata doesn't 247 // get sent while the Player still thinks it's playing the last song 248 bool ignore_tags_; 249 250 // When the gstreamer source requests a redirect we store the URL here and 251 // callers can pick it up after the state change to PLAYING fails. 252 QUrl redirect_url_; 253 254 // When we need to specify the device to use as source (for CD device) 255 QString source_device_; 256 257 // Seeking while the pipeline is in the READY state doesn't work, so we have 258 // to wait until it goes to PAUSED or PLAYING. 259 // Also we have to wait for the decodebin to be connected. 260 bool pipeline_is_initialised_; 261 bool pipeline_is_connected_; 262 qint64 pending_seek_nanosec_; 263 264 // We can only use gst_element_query_position() when the pipeline is in 265 // PAUSED nor PLAYING state. Whenever we get a new position (e.g. after a 266 // correct call to gst_element_query_position() or after a seek), we store 267 // it here so that we can use it when using gst_element_query_position() is 268 // not possible. 269 mutable gint64 last_known_position_ns_; 270 271 int volume_percent_; 272 qreal volume_modifier_; 273 274 std::unique_ptr<QTimeLine> fader_; 275 QBasicTimer fader_fudge_timer_; 276 bool use_fudge_timer_; 277 278 GstElement* pipeline_; 279 280 // Bins 281 // uridecodebin ! audiobin 282 GstElement* uridecodebin_; 283 GstElement* audiobin_; 284 285 // Elements in the audiobin. See comments in Init()'s definition. 286 GstElement* queue_; 287 GstElement* audioconvert_; 288 GstElement* rgvolume_; 289 GstElement* rglimiter_; 290 GstElement* audioconvert2_; 291 GstElement* equalizer_preamp_; 292 GstElement* equalizer_; 293 GstElement* stereo_panorama_; 294 GstElement* volume_; 295 GstElement* audioscale_; 296 GstElement* audiosink_; 297 298 uint bus_cb_id_; 299 300 QThreadPool set_state_threadpool_; 301 302 GstSegment last_decodebin_segment_; 303 }; 304 305 #endif // GSTENGINEPIPELINE_H 306