122
131
bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) {
123
GstElement* new_bin = engine_->CreateElement("uridecodebin");
124
g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(), NULL);
125
g_object_set(G_OBJECT(new_bin), "buffer-duration", buffer_duration_nanosec_, NULL);
126
g_object_set(G_OBJECT(new_bin), "download", true, NULL);
127
g_object_set(G_OBJECT(new_bin), "use-buffering", true, NULL);
128
g_signal_connect(G_OBJECT(new_bin), "drained", G_CALLBACK(SourceDrainedCallback), this);
129
g_signal_connect(G_OBJECT(new_bin), "pad-added", G_CALLBACK(NewPadCallback), this);
132
GstElement* new_bin = NULL;
134
if (url.scheme() == "spotify") {
136
new_bin = gst_bin_new("spotify_bin");
139
GstElement* src = engine_->CreateElement("tcpserversrc", new_bin);
140
GstElement* gdp = engine_->CreateElement("gdpdepay", new_bin);
144
// Pick a port number
145
const int port = Utilities::PickUnusedPort();
146
g_object_set(G_OBJECT(src), "host", "127.0.0.1", NULL);
147
g_object_set(G_OBJECT(src), "port", port, NULL);
150
gst_element_link(src, gdp);
153
GstPad* pad = gst_element_get_static_pad(gdp, "src");
154
gst_element_add_pad(GST_ELEMENT(new_bin), gst_ghost_pad_new("src", pad));
155
gst_object_unref(GST_OBJECT(pad));
157
// Tell spotify to start sending data to us.
158
InternetModel::Service<SpotifyService>()->server()->StartPlaybackLater(url.toString(), port);
159
#else // HAVE_SPOTIFY
160
qLog(Error) << "Tried to play a spotify:// url, but spotify support is not compiled in";
164
new_bin = engine_->CreateElement("uridecodebin");
165
g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(), NULL);
166
g_object_set(G_OBJECT(new_bin), "buffer-duration", buffer_duration_nanosec_, NULL);
167
g_object_set(G_OBJECT(new_bin), "download", true, NULL);
168
g_object_set(G_OBJECT(new_bin), "use-buffering", true, NULL);
169
g_signal_connect(G_OBJECT(new_bin), "drained", G_CALLBACK(SourceDrainedCallback), this);
170
g_signal_connect(G_OBJECT(new_bin), "pad-added", G_CALLBACK(NewPadCallback), this);
171
g_signal_connect(G_OBJECT(new_bin), "notify::source", G_CALLBACK(SourceSetupCallback), this);
130
174
return ReplaceDecodeBin(new_bin);
155
199
// uri decode bin -> audio bin
156
200
// The uri decode bin is a gstreamer builtin that automatically picks the
157
201
// right type of source and decoder for the URI.
158
203
// The audio bin gets created here and contains:
159
// audioconvert -> rgvolume -> rglimiter -> equalizer_preamp -> equalizer ->
160
// volume -> audioscale -> audioconvert -> audiosink
204
// queue ! audioconvert ! <caps32>
205
// ! ( rgvolume ! rglimiter ! audioconvert2 ) ! tee
206
// rgvolume and rglimiter are only created when replaygain is enabled.
208
// After the tee the pipeline splits. One split is converted to 16-bit int
209
// samples for the scope, the other is kept as float32 and sent to the
211
// tee1 ! probe_queue ! probe_converter ! <caps16> ! probe_sink
212
// tee2 ! audio_queue ! equalizer_preamp ! equalizer ! volume ! audioscale
213
// ! convert ! audiosink
163
216
audiobin_ = gst_bin_new("audiobin");
164
217
gst_bin_add(GST_BIN(pipeline_), audiobin_);
166
220
if (!(audiosink_ = engine_->CreateElement(sink_, audiobin_)))
169
223
if (GstEngine::DoesThisSinkSupportChangingTheOutputDeviceToAUserEditableString(sink_) && !device_.isEmpty())
170
224
g_object_set(G_OBJECT(audiosink_), "device", device_.toUtf8().constData(), NULL);
172
if (!(equalizer_preamp_ = engine_->CreateElement("volume", audiobin_))) { return false; }
173
if (!(equalizer_ = engine_->CreateElement("equalizer-nbands", audiobin_))) { return false; }
174
if (!(audioconvert_ = engine_->CreateElement("audioconvert", audiobin_))) { return false; }
175
if (!(volume_ = engine_->CreateElement("volume", audiobin_))) { return false; }
176
if (!(audioscale_ = engine_->CreateElement("audioresample", audiobin_))) { return false; }
177
GstElement* scope_element = audioconvert_;
226
// Create all the other elements
227
GstElement *tee, *probe_queue, *probe_converter, *probe_sink, *audio_queue,
230
queue_ = engine_->CreateElement("queue", audiobin_);
231
audioconvert_ = engine_->CreateElement("audioconvert", audiobin_);
232
tee = engine_->CreateElement("tee", audiobin_);
234
probe_queue = engine_->CreateElement("queue", audiobin_);
235
probe_converter = engine_->CreateElement("audioconvert", audiobin_);
236
probe_sink = engine_->CreateElement("fakesink", audiobin_);
238
audio_queue = engine_->CreateElement("queue", audiobin_);
239
equalizer_preamp_ = engine_->CreateElement("volume", audiobin_);
240
equalizer_ = engine_->CreateElement("equalizer-nbands", audiobin_);
241
volume_ = engine_->CreateElement("volume", audiobin_);
242
audioscale_ = engine_->CreateElement("audioresample", audiobin_);
243
convert = engine_->CreateElement("audioconvert", audiobin_);
245
if (!queue_ || !audioconvert_ || !tee || !probe_queue || !probe_converter ||
246
!probe_sink || !audio_queue || !equalizer_preamp_ || !equalizer_ ||
247
!volume_ || !audioscale_ || !convert) {
251
// Create the replaygain elements if it's enabled. event_probe is the
252
// audioconvert element we attach the probe to, which will change depending
253
// on whether replaygain is enabled. convert_sink is the element after the
254
// first audioconvert, which again will change.
255
GstElement* event_probe = audioconvert_;
256
GstElement* convert_sink = tee;
179
258
if (rg_enabled_) {
180
if (!(rgvolume_ = engine_->CreateElement("rgvolume", audiobin_))) { return false; }
181
if (!(rglimiter_ = engine_->CreateElement("rglimiter", audiobin_))) { return false; }
182
if (!(audioconvert2_ = engine_->CreateElement("audioconvert", audiobin_))) { return false; }
183
scope_element = audioconvert2_;
259
rgvolume_ = engine_->CreateElement("rgvolume", audiobin_);
260
rglimiter_ = engine_->CreateElement("rglimiter", audiobin_);
261
audioconvert2_ = engine_->CreateElement("audioconvert", audiobin_);
262
event_probe = audioconvert2_;
263
convert_sink = rgvolume_;
265
if (!rgvolume_ || !rglimiter_ || !audioconvert2_) {
185
269
// Set replaygain settings
186
270
g_object_set(G_OBJECT(rgvolume_), "album-mode", rg_mode_, NULL);
188
272
g_object_set(G_OBJECT(rglimiter_), "enabled", int(rg_compression_), NULL);
191
GstPad* pad = gst_element_get_pad(audioconvert_, "sink");
275
// Create a pad on the outside of the audiobin and connect it to the pad of
276
// the first element.
277
GstPad* pad = gst_element_get_pad(queue_, "sink");
192
278
gst_element_add_pad(audiobin_, gst_ghost_pad_new("sink", pad));
193
279
gst_object_unref(pad);
195
281
// Add a data probe on the src pad of the audioconvert element for our scope.
196
282
// We do it here because we want pre-equalized and pre-volume samples
197
// so that our visualization are not affected by them
198
pad = gst_element_get_pad(scope_element, "src");
199
gst_pad_add_buffer_probe(pad, G_CALLBACK(HandoffCallback), this);
283
// so that our visualization are not be affected by them.
284
pad = gst_element_get_pad(event_probe, "src");
200
285
gst_pad_add_event_probe(pad, G_CALLBACK(EventHandoffCallback), this);
201
gst_object_unref (pad);
286
gst_object_unref(pad);
288
// Configure the fakesink properly
289
g_object_set(G_OBJECT(probe_sink), "sync", TRUE, NULL);
203
291
// Set the equalizer bands
204
292
g_object_set(G_OBJECT(equalizer_), "num-bands", 10, NULL);
217
305
g_object_unref(G_OBJECT(band));
220
// Ensure we get the right type out of audioconvert for our scope
221
GstCaps* caps = gst_caps_new_simple ("audio/x-raw-int",
308
// Set the buffer duration. We set this on the queue as well as on the
309
// decode bin (in ReplaceDecodeBin()) because setting it on the decode bin
310
// only affects network sources.
311
g_object_set(G_OBJECT(queue_), "max-size-time", buffer_duration_nanosec_, NULL);
313
gst_element_link(queue_, audioconvert_);
315
// Create the caps to put in each path in the tee. The scope path gets 16-bit
316
// ints and the audiosink path gets float32.
317
GstCaps* caps16 = gst_caps_new_simple ("audio/x-raw-int",
222
318
"width", G_TYPE_INT, 16,
223
319
"signed", G_TYPE_BOOLEAN, true,
225
gst_element_link_filtered(scope_element, equalizer_preamp_, caps);
226
gst_caps_unref(caps);
228
// Add an extra audioconvert at the end as osxaudiosink supports only one format.
229
GstElement* convert = engine_->CreateElement("audioconvert", audiobin_);
230
if (!convert) { return false; }
232
gst_element_link_many(audioconvert_, rgvolume_, rglimiter_, audioconvert2_, NULL);
233
gst_element_link_many(equalizer_preamp_, equalizer_, volume_, audioscale_, convert, audiosink_, NULL);
321
GstCaps* caps32 = gst_caps_new_simple ("audio/x-raw-float",
322
"width", G_TYPE_INT, 32,
325
// Link the elements with special caps
326
gst_element_link_filtered(probe_converter, probe_sink, caps16);
327
gst_element_link_filtered(audioconvert_, convert_sink, caps32);
328
gst_caps_unref(caps16);
329
gst_caps_unref(caps32);
331
// Link the outputs of tee to the queues on each path.
332
gst_pad_link(gst_element_get_request_pad(tee, "src%d"), gst_element_get_pad(probe_queue, "sink"));
333
gst_pad_link(gst_element_get_request_pad(tee, "src%d"), gst_element_get_pad(audio_queue, "sink"));
335
// Link replaygain elements if enabled.
337
gst_element_link_many(rgvolume_, rglimiter_, audioconvert2_, tee, NULL);
340
// Link everything else.
341
gst_element_link(probe_queue, probe_converter);
342
gst_element_link_many(audio_queue, equalizer_preamp_, equalizer_, volume_,
343
audioscale_, convert, audiosink_, NULL);
345
// Add probes and handlers.
346
gst_pad_add_buffer_probe(gst_element_get_pad(probe_converter, "src"), G_CALLBACK(HandoffCallback), this);
235
347
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), BusCallbackSync, this);
236
348
bus_cb_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), BusCallback, this);
350
MaybeLinkDecodeToAudio();
355
void GstEnginePipeline::MaybeLinkDecodeToAudio() {
356
if (!uridecodebin_ || !audiobin_)
359
GstPad* pad = gst_element_get_static_pad(uridecodebin_, "src");
363
gst_object_unref(pad);
364
gst_element_link(uridecodebin_, audiobin_);
240
367
bool GstEnginePipeline::InitFromString(const QString& pipeline) {
241
368
pipeline_ = gst_pipeline_new("pipeline");
254
381
bool GstEnginePipeline::InitFromUrl(const QUrl &url, qint64 end_nanosec) {
255
382
pipeline_ = gst_pipeline_new("pipeline");
384
if (url.scheme() == "cdda" && !url.path().isEmpty()) {
385
// Currently, Gstreamer can't handle input CD devices inside cdda URL. So
386
// we handle them ourselve: we extract the track number and re-create an
387
// URL with only cdda:// + the track number (which can be handled by
388
// Gstreamer). We keep the device in mind, and we will set it later using
389
// SourceSetupCallback
390
QStringList path = url.path().split('/');
391
url_ = QUrl(QString("cdda://%1").arg(path.takeLast()));
392
source_device_ = path.join("/");
258
396
end_offset_nanosec_ = end_nanosec;
261
if (!ReplaceDecodeBin(url)) return false;
399
if (!ReplaceDecodeBin(url_)) return false;
666
void GstEnginePipeline::SourceSetupCallback(GstURIDecodeBin* bin, GParamSpec *pspec, gpointer self) {
667
GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
669
g_object_get(bin, "source", &element, NULL);
671
g_object_class_find_property(G_OBJECT_GET_CLASS(element), "device") &&
672
!instance->source_device().isEmpty()) {
673
// Gstreamer is not able to handle device in URL (refering to Gstreamer
674
// documentation, this might be added in the future). Despite that, for now
675
// we include device inside URL: we decompose it during Init and set device
676
// here, when this callback is called.
677
g_object_set(element, "device", instance->source_device().toLocal8Bit().constData(), NULL);
680
g_object_class_find_property(G_OBJECT_GET_CLASS(element), "extra-headers") &&
681
instance->url().host().contains("grooveshark")) {
682
// Grooveshark streaming servers will answer with a 400 error 'Bad request'
683
// if we don't specify 'Range' field in HTTP header.
684
// Maybe it could be usefull in some other cases, but for now, I prefer to
685
// keep this grooveshark specific.
686
GstStructure* headers;
687
headers = gst_structure_new("extra-headers", "Range", G_TYPE_STRING, "bytes=0-", NULL);
688
g_object_set(element, "extra-headers", headers, NULL);
689
gst_structure_free(headers);
516
693
void GstEnginePipeline::TransitionToNext() {
517
694
GstElement* old_decode_bin = uridecodebin_;