/** * gst_format_register: * @nick: The nick of the new format * @description: The description of the new format * * Create a new GstFormat based on the nick or return an * already registered format with that nick. * * Returns: A new GstFormat or an already registered format * with the same nick. * * MT safe. */ GstFormat gst_format_register (const gchar * nick, const gchar * description) { GstFormatDefinition *format; GstFormat query; g_return_val_if_fail (nick != NULL, GST_FORMAT_UNDEFINED); g_return_val_if_fail (description != NULL, GST_FORMAT_UNDEFINED); query = gst_format_get_by_nick (nick); if (query != GST_FORMAT_UNDEFINED) return query; g_mutex_lock (&mutex); format = g_slice_new (GstFormatDefinition); format->value = (GstFormat) _n_values; format->nick = g_strdup (nick); format->description = g_strdup (description); format->quark = g_quark_from_static_string (format->nick); g_hash_table_insert (_nick_to_format, (gpointer) format->nick, format); g_hash_table_insert (_format_to_nick, GINT_TO_POINTER (format->value), format); _gst_formats = g_list_append (_gst_formats, format); _n_values++; g_mutex_unlock (&mutex); return format->value; }
// set the position of the media file void gst_binding_set_track (gstPlay *play, gint64 track_number, float speed) { if (!isValid (play)) return; gst_element_seek (play->element, speed, gst_format_get_by_nick ("track"), GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, track_number - 1, GST_SEEK_TYPE_NONE, -1); }
static void rb_audiocd_plugin_reuse_stream_cb (RBPlayer *player, const char *new_uri, const char *stream_uri, GstElement *element, RBAudioCdPlugin *plugin) { GstFormat track_format = gst_format_get_by_nick ("track"); char *track_str; char *new_device; guint track; guint cdda_len; /* get the new track number */ cdda_len = strlen ("cdda://"); new_device = g_utf8_strrchr (new_uri, -1, '#'); track_str = g_strndup (new_uri + cdda_len, new_device - (new_uri + cdda_len)); track = atoi (track_str); g_free (track_str); rb_debug ("seeking to track %d on CD device %s", track, new_device+1); gst_element_seek (element, 1.0, track_format, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, track-1, GST_SEEK_TYPE_NONE, -1); }
/* * Class method: find(nick) * nick: the nick of an existing format. * * Returns: a reference to the Gst::Format object registered with the * given nick, or nil if this query was not registered. */ static VALUE rg_s_find (VALUE self, VALUE nick) { GstFormat format = gst_format_get_by_nick (RVAL2CSTR (nick)); return format != GST_FORMAT_UNDEFINED ? RGST_FORMAT_NEW (&format) : Qnil; }
P_INVOKE void bp_dvd_go_to_previous_chapter (BansheePlayer *player) { gint64 index; GstFormat format = gst_format_get_by_nick ("chapter"); gst_element_query_position (player->playbin, format, &index); gst_element_seek (player->playbin, 1.0, format, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, index - 1, GST_SEEK_TYPE_NONE, 0); }
static void gst_progress_report_report (GstProgressReport * filter, GTimeVal cur_time, GstBuffer * buf) { GstFormat try_formats[] = { GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_PERCENT, GST_FORMAT_BUFFERS, GST_FORMAT_DEFAULT }; GstMessage *msg; GstFormat format = GST_FORMAT_UNDEFINED; gboolean done = FALSE; glong run_time; gint hh, mm, ss; run_time = cur_time.tv_sec - filter->start_time.tv_sec; hh = (run_time / 3600) % 100; mm = (run_time / 60) % 60; ss = (run_time % 60); GST_OBJECT_LOCK (filter); if (filter->format != NULL && strcmp (filter->format, "auto") != 0) { format = gst_format_get_by_nick (filter->format); } if (format != GST_FORMAT_UNDEFINED) { done = gst_progress_report_do_query (filter, format, hh, mm, ss, buf); } else { gint i; for (i = 0; i < G_N_ELEMENTS (try_formats); ++i) { done = gst_progress_report_do_query (filter, try_formats[i], hh, mm, ss, buf); if (done) break; } } if (!done && !filter->silent) { g_print ("%s (%2d:%2d:%2d): Could not query position and/or duration\n", GST_OBJECT_NAME (filter), hh, mm, ss); } msg = filter->pending_msg; filter->pending_msg = NULL; GST_OBJECT_UNLOCK (filter); if (msg) { gst_element_post_message (GST_ELEMENT_CAST (filter), msg); } }
static gboolean rb_audiocd_get_cd_info (RBAudioCdSource *source, gint64 *num_tracks) { RBAudioCdSourcePrivate *priv = AUDIOCD_SOURCE_GET_PRIVATE (source); GstFormat fmt = gst_format_get_by_nick ("track"); GstFormat out_fmt = fmt; if (!gst_element_query_duration (priv->cdda, &out_fmt, num_tracks) || out_fmt != fmt) { return FALSE; } return TRUE; }
SongLoader::Result SongLoader::LoadAudioCD() { #ifdef HAVE_AUDIOCD // Create gstreamer cdda element GstElement* cdda = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL); if (cdda == NULL) { qLog(Error) << "Error while creating CDDA GstElement"; return Error; } // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { qLog(Error) << "Error while changing CDDA GstElement's state"; gst_element_set_state(cdda, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda)); return Error; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick ("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration (cdda, &out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; gst_object_unref(GST_OBJECT(cdda)); return Error; } for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; guint64 duration = 0; // quint64 == ulonglong and guint64 == ulong, therefore we must cast if (gst_tag_list_get_uint64 (GST_CDDA_BASE_SRC(cdda)->tracks[track_number-1].tags, GST_TAG_DURATION, &duration)) { song.set_length_nanosec((quint64)duration); } song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url(QUrl(QString("cdda://%1").arg(track_number))); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs_ << song; } // Generate MusicBrainz DiscId gst_tag_register_musicbrainz_tags(); GstElement *pipe = gst_pipeline_new ("pipeline"); gst_bin_add (GST_BIN (pipe), cdda); gst_element_set_state (pipe, GST_STATE_READY); gst_element_set_state (pipe, GST_STATE_PAUSED); GstMessage *msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), GST_CLOCK_TIME_NONE, GST_MESSAGE_TAG); GstTagList *tags = NULL; gst_message_parse_tag (msg, &tags); char *string_mb = NULL; if (gst_tag_list_get_string (tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; MusicBrainzClient *musicbrainz_client = new MusicBrainzClient(this); connect(musicbrainz_client, SIGNAL(Finished(const QString&, const QString&, MusicBrainzClient::ResultList)), SLOT(AudioCDTagsLoaded(const QString&, const QString&, MusicBrainzClient::ResultList))); musicbrainz_client->StartDiscIdRequest(musicbrainz_discid); g_free(string_mb); } // Clean all the Gstreamer objects we have used: we don't need them anymore gst_object_unref(GST_OBJECT(cdda)); gst_element_set_state (pipe, GST_STATE_NULL); gst_object_unref(GST_OBJECT(pipe)); gst_object_unref(GST_OBJECT(msg)); gst_object_unref(GST_OBJECT(tags)); return Success; #else // HAVE_AUDIOCD return Error; #endif }
static void gst_file_index_load (GstFileIndex * index) { xmlDocPtr doc; xmlNodePtr root, part; xmlChar *val; g_assert (index->location); g_return_if_fail (!index->is_loaded); { gchar *path = g_strdup_printf ("%s/gstindex.xml", index->location); GError *err = NULL; gchar *buf; gsize len; g_file_get_contents (path, &buf, &len, &err); g_free (path); if (err) { GST_ERROR_OBJECT (index, "%s", err->message); return; } doc = xmlParseMemory (buf, len); g_free (buf); } //xmlDocFormatDump (stderr, doc, TRUE); root = doc->xmlRootNode; if (strcmp ((char *) root->name, "gstfileindex") != 0) { GST_ERROR_OBJECT (index, "root node isn't a gstfileindex"); return; } val = xmlGetProp (root, (xmlChar *) "version"); if (!val || atoi ((char *) val) != 1) { GST_ERROR_OBJECT (index, "version != 1"); return; } free (val); for (part = root->children; part; part = part->next) { if (strcmp ((char *) part->name, "writers") == 0) { xmlNodePtr writer; for (writer = part->children; writer; writer = writer->next) { xmlChar *datafile = xmlGetProp (writer, (xmlChar *) "datafile"); gchar *path = g_strdup_printf ("%s/%s", index->location, datafile); int fd; GstFileIndexId *id_index; xmlNodePtr wpart; xmlChar *entries_str; gpointer array_data; free (datafile); fd = open (path, O_RDONLY); g_free (path); if (fd < 0) { GST_ERROR_OBJECT (index, "Can't open '%s': %s", path, g_strerror (errno)); continue; } id_index = g_slice_new0 (GstFileIndexId); id_index->id_desc = (char *) xmlGetProp (writer, (xmlChar *) "id"); for (wpart = writer->children; wpart; wpart = wpart->next) { if (strcmp ((char *) wpart->name, "formats") == 0) { xmlChar *count_str = xmlGetProp (wpart, (xmlChar *) "count"); gint fx = 0; xmlNodePtr format; id_index->nformats = atoi ((char *) count_str); free (count_str); id_index->format = g_new (GstFormat, id_index->nformats); for (format = wpart->children; format; format = format->next) { xmlChar *nick = xmlGetProp (format, (xmlChar *) "nick"); GstFormat fmt = gst_format_get_by_nick ((gchar *) nick); if (fmt == GST_FORMAT_UNDEFINED) GST_ERROR_OBJECT (index, "format '%s' undefined", nick); g_assert (fx < id_index->nformats); id_index->format[fx++] = fmt; free (nick); } } else GST_INFO_OBJECT (index, "unknown wpart '%s'", wpart->name); } g_assert (id_index->nformats > 0); _fc_alloc_array (id_index); g_assert (id_index->array->data == NULL); /* little bit risky */ entries_str = xmlGetProp (writer, (xmlChar *) "entries"); id_index->array->len = atoi ((char *) entries_str); free (entries_str); array_data = mmap (NULL, ARRAY_TOTAL_SIZE (id_index), PROT_READ, MAP_SHARED, fd, 0); close (fd); if (array_data == MAP_FAILED) { GST_ERROR_OBJECT (index, "mmap %s failed: %s", path, g_strerror (errno)); continue; } id_index->array->data = array_data; index->unresolved = g_slist_prepend (index->unresolved, id_index); } } else GST_INFO_OBJECT (index, "unknown part '%s'", part->name); } xmlFreeDoc (doc); GST_OBJECT_FLAG_UNSET (index, GST_INDEX_WRITABLE); index->is_loaded = TRUE; GST_LOG_OBJECT (index, "index %s loaded OK", index->location); }
static void build_pipeline (SjExtractor *extractor) { SjExtractorPrivate *priv; GstBus *bus; g_return_if_fail (SJ_IS_EXTRACTOR (extractor)); priv = extractor->priv; if (priv->pipeline != NULL) { gst_object_unref (GST_OBJECT (priv->pipeline)); } priv->pipeline = gst_pipeline_new ("pipeline"); bus = gst_element_get_bus (priv->pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (G_OBJECT (bus), "message::error", G_CALLBACK (error_cb), extractor); /* Read from CD */ priv->cdsrc = gst_element_make_from_uri (GST_URI_SRC, "cdda://1", "cd_src", NULL); if (priv->cdsrc == NULL) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not create GStreamer CD reader")); return; } g_object_set (G_OBJECT (priv->cdsrc), "device", priv->device_path, NULL); if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->cdsrc), "paranoia-mode")) { g_object_set (G_OBJECT (priv->cdsrc), "paranoia-mode", priv->paranoia_mode, NULL); } /* Get the track format for seeking later */ priv->track_format = gst_format_get_by_nick ("track"); g_assert (priv->track_format != 0); /* Encode */ priv->encodebin = build_encoder (extractor); if (priv->encodebin == NULL) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not create GStreamer encoders for %s"), gst_encoding_profile_get_name (priv->profile)); return; } /* Connect to the eos so we know when its finished */ g_signal_connect (bus, "message::eos", G_CALLBACK (eos_cb), extractor); /* Write to disk */ priv->filesink = gst_element_factory_make (FILE_SINK, "file_sink"); if (priv->filesink == NULL) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not create GStreamer file output")); return; } #if 0 g_signal_connect (G_OBJECT (priv->filesink), "allow-overwrite", G_CALLBACK (just_say_yes), extractor); #endif /* Add the elements to the pipeline */ gst_bin_add_many (GST_BIN (priv->pipeline), priv->cdsrc, priv->encodebin, priv->filesink, NULL); /* Link it all together */ if (!gst_element_link_many (priv->cdsrc, priv->encodebin, priv->filesink, NULL)) { g_set_error (&priv->construct_error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Could not link pipeline")); return; } priv->rebuild_pipeline = FALSE; }
void CddaDevice::Init() { QMutexLocker locker(&mutex_init_); song_count_ = 0; // Reset song count, in case it was already set cdio_ = cdio_open (url_.path().toLocal8Bit().constData(), DRIVER_DEVICE); if (cdio_ == NULL) { return; } // Create gstreamer cdda element cdda_ = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL); if (cdda_ == NULL) { model_->Reset(); return; } GST_CDDA_BASE_SRC(cdda_)->device = g_strdup (url_.path().toLocal8Bit().constData()); // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { model_->Reset(); gst_element_set_state(cdda_, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda_)); return; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick ("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration (cdda_, &out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; model_->Reset(); gst_object_unref(GST_OBJECT(cdda_)); return; } SongList songs; for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; guint64 duration = 0; // quint64 == ulonglong and guint64 == ulong, therefore we must cast if (gst_tag_list_get_uint64 (GST_CDDA_BASE_SRC(cdda_)->tracks[track_number-1].tags, GST_TAG_DURATION, &duration)) { song.set_length_nanosec((quint64)duration); } song.set_id(track_number); song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url(QUrl(QString("cdda://%1/%2").arg(url_.path()).arg(track_number))); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs << song; } song_count_ = num_tracks; connect(this, SIGNAL(SongsDiscovered(const SongList&)), model_, SLOT(SongsDiscovered(const SongList&))); emit SongsDiscovered(songs); // Generate MusicBrainz DiscId gst_tag_register_musicbrainz_tags(); GstElement *pipe = gst_pipeline_new ("pipeline"); gst_bin_add (GST_BIN (pipe), cdda_); gst_element_set_state (pipe, GST_STATE_READY); gst_element_set_state (pipe, GST_STATE_PAUSED); GstMessage *msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), GST_CLOCK_TIME_NONE, GST_MESSAGE_TAG); GstTagList *tags = NULL; gst_message_parse_tag (msg, &tags); char *string_mb = NULL; if (gst_tag_list_get_string (tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; MusicBrainzClient *musicbrainz_client = new MusicBrainzClient(this); connect(musicbrainz_client, SIGNAL(Finished(const QString&, const QString&, MusicBrainzClient::ResultList)), SLOT(AudioCDTagsLoaded(const QString&, const QString&, MusicBrainzClient::ResultList))); musicbrainz_client->StartDiscIdRequest(musicbrainz_discid); g_free(string_mb); } // Clean all the Gstreamer objects we have used: we don't need them anymore gst_element_set_state (pipe, GST_STATE_NULL); // This will also cause cdda_ to be unref'd. gst_object_unref(GST_OBJECT(pipe)); gst_object_unref(GST_OBJECT(msg)); gst_tag_list_free(tags); }
void CddaSongLoader::LoadSongsFromCdda() { QMutexLocker locker(&mutex_load_); cdio_ = cdio_open(url_.path().toLocal8Bit().constData(), DRIVER_DEVICE); if (cdio_ == nullptr) { return; } // Create gstreamer cdda element GError* error = nullptr; cdda_ = gst_element_make_from_uri(GST_URI_SRC, "cdda://", nullptr, &error); if (error) { qLog(Error) << error->code << QString::fromLocal8Bit(error->message); } if (cdda_ == nullptr) { return; } if (!url_.isEmpty()) { g_object_set(cdda_, "device", g_strdup(url_.path().toLocal8Bit().constData()), nullptr); } if (g_object_class_find_property (G_OBJECT_GET_CLASS (cdda_), "paranoia-mode")) { g_object_set (cdda_, "paranoia-mode", 0, NULL); } // Change the element's state to ready and paused, to be able to query it if (gst_element_set_state(cdda_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || gst_element_set_state(cdda_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { gst_element_set_state(cdda_, GST_STATE_NULL); gst_object_unref(GST_OBJECT(cdda_)); return; } // Get number of tracks GstFormat fmt = gst_format_get_by_nick("track"); GstFormat out_fmt = fmt; gint64 num_tracks = 0; if (!gst_element_query_duration(cdda_, out_fmt, &num_tracks) || out_fmt != fmt) { qLog(Error) << "Error while querying cdda GstElement"; gst_object_unref(GST_OBJECT(cdda_)); return; } SongList songs; for (int track_number = 1; track_number <= num_tracks; track_number++) { // Init song Song song; song.set_id(track_number); song.set_valid(true); song.set_filetype(Song::Type_Cdda); song.set_url( GetUrlFromTrack(track_number)); song.set_title(QString("Track %1").arg(track_number)); song.set_track(track_number); songs << song; } emit SongsLoaded(songs); gst_tag_register_musicbrainz_tags(); GstElement* pipeline = gst_pipeline_new("pipeline"); GstElement* sink = gst_element_factory_make ("fakesink", NULL); gst_bin_add_many (GST_BIN (pipeline), cdda_, sink, NULL); gst_element_link (cdda_, sink); gst_element_set_state(pipeline, GST_STATE_READY); gst_element_set_state(pipeline, GST_STATE_PAUSED); // Get TOC and TAG messages GstMessage* msg = nullptr; GstMessage* msg_toc = nullptr; GstMessage* msg_tag = nullptr; while ((msg = gst_bus_timed_pop_filtered( GST_ELEMENT_BUS(pipeline), 2 * GST_SECOND, (GstMessageType)(GST_MESSAGE_TOC | GST_MESSAGE_TAG)))) { if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TOC) { if (msg_toc) gst_message_unref(msg_toc); // Shouldn't happen, but just in case msg_toc = msg; } else if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_TAG) { if (msg_tag) gst_message_unref(msg_tag); msg_tag = msg; } } // Handle TOC message: get tracks duration if (msg_toc) { GstToc* toc; gst_message_parse_toc (msg_toc, &toc, nullptr); if (toc) { GList* entries = gst_toc_get_entries(toc); if (entries && songs.size() <= g_list_length (entries)) { int i = 0; for (GList* node = entries; node != nullptr; node = node->next) { GstTocEntry *entry = static_cast<GstTocEntry*>(node->data); quint64 duration = 0; gint64 start, stop; if (gst_toc_entry_get_start_stop_times (entry, &start, &stop)) duration = stop - start; songs[i++].set_length_nanosec(duration); } } } gst_message_unref(msg_toc); } emit SongsDurationLoaded(songs); // Handle TAG message: generate MusicBrainz DiscId if (msg_tag) { GstTagList* tags = nullptr; gst_message_parse_tag(msg_tag, &tags); char* string_mb = nullptr; if (gst_tag_list_get_string(tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) { QString musicbrainz_discid(string_mb); qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid; emit MusicBrainzDiscIdLoaded(musicbrainz_discid); g_free(string_mb); gst_message_unref(msg_tag); gst_tag_list_free(tags); } } gst_element_set_state(pipeline, GST_STATE_NULL); // This will also cause cdda_ to be unref'd. gst_object_unref(pipeline); }