コード例 #1
0
ファイル: gstenginepipeline.cpp プロジェクト: Gu1/Clementine
void GstEnginePipeline::TransitionToNext() {
  GstElement* old_decode_bin = uridecodebin_;

  ignore_tags_ = true;

  ReplaceDecodeBin(next_url_);
  gst_element_set_state(uridecodebin_, GST_STATE_PLAYING);
  MaybeLinkDecodeToAudio();

  url_ = next_url_;
  end_offset_nanosec_ = next_end_offset_nanosec_;
  next_url_ = QUrl();
  next_beginning_offset_nanosec_ = 0;
  next_end_offset_nanosec_ = 0;

  // This function gets called when the source has been drained, even if the
  // song hasn't finished playing yet.  We'll get a new segment when it really
  // does finish, so emit TrackEnded then.
  emit_track_ended_on_segment_start_ = true;

  // This has to happen *after* the gst_element_set_state on the new bin to
  // fix an occasional race condition deadlock.
  sElementDeleter->DeleteElementLater(old_decode_bin);

  ignore_tags_ = false;
}
コード例 #2
0
bool GstEnginePipeline::InitFromString(const QString& pipeline) {
    pipeline_ = gst_pipeline_new("pipeline");

    GstElement* new_bin = CreateDecodeBinFromString(pipeline.toAscii().constData());
    if (!new_bin) {
        return false;
    }

    if (!ReplaceDecodeBin(new_bin)) return false;

    if (!Init()) return false;
    return gst_element_link(new_bin, audiobin_);
}
コード例 #3
0
bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) {
  GstElement* new_bin = nullptr;

#ifdef HAVE_SPOTIFY
  if (url.scheme() == "spotify") {
    new_bin = gst_bin_new("spotify_bin");

    // Create elements
    GstElement* src = engine_->CreateElement("tcpserversrc", new_bin);
    if (!src) return false;
    GstElement* gdp = engine_->CreateElement("gdpdepay", new_bin);
    if (!gdp) return false;

    // Pick a port number
    const int port = Utilities::PickUnusedPort();
    g_object_set(G_OBJECT(src), "host", "127.0.0.1", nullptr);
    g_object_set(G_OBJECT(src), "port", port, nullptr);

    // Link the elements
    gst_element_link(src, gdp);

    // Add a ghost pad
    GstPad* pad = gst_element_get_static_pad(gdp, "src");
    gst_element_add_pad(GST_ELEMENT(new_bin), gst_ghost_pad_new("src", pad));
    gst_object_unref(GST_OBJECT(pad));

    // Tell spotify to start sending data to us.
    SpotifyServer* spotify_server =
        InternetModel::Service<SpotifyService>()->server();
    // Need to schedule this in the spotify server's thread
    QMetaObject::invokeMethod(
        spotify_server, "StartPlayback", Qt::QueuedConnection,
        Q_ARG(QString, url.toString()), Q_ARG(quint16, port));
  } else {
#endif
    new_bin = engine_->CreateElement("uridecodebin");
    if (!new_bin) return false;
    g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(),
                 nullptr);
    CHECKED_GCONNECT(G_OBJECT(new_bin), "drained", &SourceDrainedCallback,
                     this);
    CHECKED_GCONNECT(G_OBJECT(new_bin), "pad-added", &NewPadCallback, this);
    CHECKED_GCONNECT(G_OBJECT(new_bin), "notify::source", &SourceSetupCallback,
                     this);
#ifdef HAVE_SPOTIFY
  }
#endif

  return ReplaceDecodeBin(new_bin);
}
コード例 #4
0
bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) {
    GstElement* new_bin = NULL;

    if (url.scheme() == "spotify") {
#ifdef HAVE_SPOTIFY
        new_bin = gst_bin_new("spotify_bin");

        // Create elements
        GstElement* src = engine_->CreateElement("tcpserversrc", new_bin);
        GstElement* gdp = engine_->CreateElement("gdpdepay", new_bin);
        if (!src || !gdp)
            return false;

        // Pick a port number
        const int port = Utilities::PickUnusedPort();
        g_object_set(G_OBJECT(src), "host", "127.0.0.1", NULL);
        g_object_set(G_OBJECT(src), "port", port, NULL);

        // Link the elements
        gst_element_link(src, gdp);

        // Add a ghost pad
        GstPad* pad = gst_element_get_static_pad(gdp, "src");
        gst_element_add_pad(GST_ELEMENT(new_bin), gst_ghost_pad_new("src", pad));
        gst_object_unref(GST_OBJECT(pad));

        // Tell spotify to start sending data to us.
        InternetModel::Service<SpotifyService>()->server()->StartPlaybackLater(url.toString(), port);
#else // HAVE_SPOTIFY
        qLog(Error) << "Tried to play a spotify:// url, but spotify support is not compiled in";
        return false;
#endif
    } else {
        new_bin = engine_->CreateElement("uridecodebin");
        g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(), NULL);
        CHECKED_GCONNECT(G_OBJECT(new_bin), "drained", &SourceDrainedCallback, this);
        CHECKED_GCONNECT(G_OBJECT(new_bin), "pad-added", &NewPadCallback, this);
        CHECKED_GCONNECT(G_OBJECT(new_bin), "notify::source", &SourceSetupCallback, this);
    }

    return ReplaceDecodeBin(new_bin);
}
コード例 #5
0
ファイル: gstenginepipeline.cpp プロジェクト: Gu1/Clementine
bool GstEnginePipeline::InitFromUrl(const QUrl& url, qint64 end_nanosec) {
  pipeline_ = gst_pipeline_new("pipeline");

  if (url.scheme() == "cdda" && !url.path().isEmpty()) {
    // Currently, Gstreamer can't handle input CD devices inside cdda URL. So
    // we handle them ourselve: we extract the track number and re-create an
    // URL with only cdda:// + the track number (which can be handled by
    // Gstreamer). We keep the device in mind, and we will set it later using
    // SourceSetupCallback
    QStringList path = url.path().split('/');
    url_ = QUrl(QString("cdda://%1").arg(path.takeLast()));
    source_device_ = path.join("/");
  } else {
    url_ = url;
  }
  end_offset_nanosec_ = end_nanosec;

  // Decode bin
  if (!ReplaceDecodeBin(url_)) return false;

  return Init();
}