/* * Method: children(interface=nil) * interface: an interface (Ruby class). * * Returns: If interface is nil, an array of all * Gst::Element objects in the container. Otherwise, an * array of Gst::Element objects in the container that * implements the interface. */ static VALUE rb_gst_bin_get_children(int argc, VALUE *argv, VALUE self) { VALUE children, iface; rb_scan_args(argc, argv, "01", &iface); if (NIL_P(iface)) { const GList *node; children = rb_ary_new(); for (node = GST_BIN_CHILDREN(SELF(self)); node; node = g_list_next(node)) { rb_ary_push(children, GST_ELEMENT2RVAL(node->data)); } } else { GstIterator *iter; iter = gst_bin_iterate_all_by_interface(SELF(self), CLASS2GTYPE(iface)); children = _rbgst_collect_elements(iter); } return children; }
void sj_extractor_extract_track (SjExtractor *extractor, const TrackDetails *track, GFile *file, GError **error) { GParamSpec *spec; GstStateChangeReturn state_ret; SjExtractorPrivate *priv; GstIterator *iter; GValue item = {0, }; GstTagSetter *tagger; gboolean done; char *uri; g_return_if_fail (SJ_IS_EXTRACTOR (extractor)); g_return_if_fail (file != NULL); g_return_if_fail (track != NULL); priv = extractor->priv; /* See if we need to rebuild the pipeline */ if (priv->rebuild_pipeline != FALSE) { build_pipeline (extractor); if (priv->construct_error != NULL) { g_propagate_error (error, priv->construct_error); priv->construct_error = NULL; return; } } /* Need to do this, as playback will have locked the read speed to 2x previously */ spec = g_object_class_find_property (G_OBJECT_GET_CLASS (priv->cdsrc), "read-speed"); if (spec && spec->value_type == G_TYPE_INT) { g_object_set (G_OBJECT (priv->cdsrc), "read-speed", ((GParamSpecInt*)spec)->maximum, NULL); } /* Set the output filename */ gst_element_set_state (priv->filesink, GST_STATE_NULL); uri = g_file_get_uri (file); g_object_set (G_OBJECT (priv->filesink), "location", uri, NULL); g_free (uri); /* Set the metadata */ iter = gst_bin_iterate_all_by_interface (GST_BIN (priv->pipeline), GST_TYPE_TAG_SETTER); done = FALSE; while (!done) { switch (gst_iterator_next (iter, &item)) { case GST_ITERATOR_OK: /* TODO: generate this as a taglist once, and apply it to all elements */ tagger = g_value_get_object (&item); gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_REPLACE_ALL, GST_TAG_TITLE, track->title, GST_TAG_ARTIST, track->artist, GST_TAG_TRACK_NUMBER, track->number, GST_TAG_TRACK_COUNT, track->album->number, GST_TAG_ALBUM, track->album->title, GST_TAG_DURATION, track->duration * GST_SECOND, NULL); if (track->composer != NULL && strcmp (track->composer, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_COMPOSER, track->composer, NULL); } if (track->composer_sortname != NULL && strcmp (track->composer_sortname, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_COMPOSER_SORTNAME, track->composer_sortname, NULL); } if (track->album->album_id != NULL && strcmp (track->album->album_id, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_MUSICBRAINZ_ALBUMID, track->album->album_id, NULL); } if (track->album->artist_id != NULL && strcmp (track->album->artist_id, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_MUSICBRAINZ_ALBUMARTISTID, track->album->artist_id, NULL); } if (track->album->artist != NULL && strcmp (track->album->artist, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_ALBUM_ARTIST, track->album->artist, NULL); } if (track->album->artist_sortname != NULL && strcmp (track->album->artist_sortname, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_ALBUM_ARTIST_SORTNAME, track->album->artist_sortname, NULL); } if (track->artist_id != NULL && strcmp (track->artist_id, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_MUSICBRAINZ_ARTISTID, track->artist_id, NULL); } if (track->track_id != NULL && strcmp (track->track_id, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_MUSICBRAINZ_TRACKID, track->track_id, NULL); } if (track->artist_sortname != NULL && strcmp (track->artist_sortname, "") != 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST_SORTNAME, track->artist_sortname, NULL); } if (track->album->genre != NULL && strcmp (track->album->genre, "") != 0) { char **values, **l; values = g_strsplit (track->album->genre, ",", 0); for (l = values; *l; l++) { g_strstrip (*l); gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_GENRE, *l, NULL); } g_strfreev (values); } if (track->album->release_date) { GDate *date; guint year = 1; guint month = 1; guint day = 1; if (gst_date_time_has_year (track->album->release_date)) { year = gst_date_time_get_year (track->album->release_date); } if (gst_date_time_has_month (track->album->release_date)) { month = gst_date_time_get_month (track->album->release_date); } if (gst_date_time_has_day (track->album->release_date)) { day = gst_date_time_get_day (track->album->release_date); } date = g_date_new_dmy (day, month, year); /* We set both GST_TAG_DATE_TIME and GST_TAG_DATE as most taggers * use GST_TAG__DATE_TIME, but a few (id3v2mux/apemux) are still using * GST_TAG_DATE */ gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_DATE_TIME, track->album->release_date, GST_TAG_DATE, date, NULL); g_date_free (date); } if (track->album->disc_number > 0) { gst_tag_setter_add_tags (tagger, GST_TAG_MERGE_APPEND, GST_TAG_ALBUM_VOLUME_NUMBER, track->album->disc_number, NULL); } g_value_unset (&item); break; case GST_ITERATOR_RESYNC: /* TODO? */ g_warning ("Got GST_ITERATOR_RESYNC, not sure what to do"); gst_iterator_resync (iter); break; case GST_ITERATOR_ERROR: done = TRUE; break; case GST_ITERATOR_DONE: done = TRUE; break; } } g_value_unset (&item); gst_iterator_free (iter); /* Seek to the right track */ g_object_set (G_OBJECT (priv->cdsrc), "track", track->number, NULL); /* Let's get ready to rumble! */ state_ret = gst_element_set_state (priv->pipeline, GST_STATE_PLAYING); if (state_ret == GST_STATE_CHANGE_ASYNC) { /* Wait for state change to either complete or fail, but not for too long, * just to catch immediate errors. The rest we'll handle asynchronously */ state_ret = gst_element_get_state (priv->pipeline, NULL, NULL, GST_SECOND / 2); } if (state_ret == GST_STATE_CHANGE_FAILURE) { GstMessage *msg; msg = gst_bus_poll (GST_ELEMENT_BUS (priv->pipeline), GST_MESSAGE_ERROR, 0); if (msg) { gst_message_parse_error (msg, error, NULL); gst_message_unref (msg); } else if (error) { /* this should never happen, create generic error just in case */ *error = g_error_new (SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, "Error starting ripping pipeline"); } gst_element_set_state (priv->pipeline, GST_STATE_NULL); priv->rebuild_pipeline = TRUE; return; } priv->tick_id = g_timeout_add (250, (GSourceFunc)tick_timeout_cb, extractor); g_source_set_name_by_id (priv->tick_id, "[sound-juicer] tick_timeout_cb"); }
static void set_tags (GstElement *pipeline, track_info_t *track) { GstIterator *iter; GstTagSetter *tagger; gboolean done = FALSE; iter = gst_bin_iterate_all_by_interface( GST_BIN(pipeline), GST_TYPE_TAG_SETTER ); while (!done) { switch (gst_iterator_next(iter, (gpointer)&tagger)) { case GST_ITERATOR_OK: gst_tag_setter_add_tags( tagger, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, track->title, GST_TAG_ARTIST, track->artist, GST_TAG_TRACK_NUMBER, track->track_num, GST_TAG_ALBUM, track->album->title, GST_TAG_DURATION, track->duration *GST_SECOND, GST_TAG_MUSICBRAINZ_ALBUMID, track->album->album_id, GST_TAG_MUSICBRAINZ_ALBUMARTISTID, track->album->artist_id, GST_TAG_MUSICBRAINZ_ARTISTID, track->artist_id, GST_TAG_MUSICBRAINZ_TRACKID, track->track_id, GST_TAG_MUSICBRAINZ_SORTNAME, track->artist_sortname, NULL ); if (track->album->disc_number > 0) { gst_tag_setter_add_tags( tagger, GST_TAG_MERGE_APPEND, GST_TAG_ALBUM_VOLUME_NUMBER, track->album->disc_number, NULL ); } if (track->album->release_date) { gst_tag_setter_add_tags( tagger, GST_TAG_MERGE_APPEND, GST_TAG_DATE, track->album->release_date, NULL ); } break; case GST_ITERATOR_RESYNC: fprintf(stderr, "got iterator resync. wtf\n"); gst_iterator_resync(iter); break; case GST_ITERATOR_ERROR: fprintf(stderr, "iterator error. wtf\n"); /* falling */ case GST_ITERATOR_DONE: done = TRUE; break; } } gst_iterator_free(iter); }
static GstElement *find_color_balance_element() { GstIterator *iterator = gst_bin_iterate_all_by_interface( GST_BIN(pipeline), GST_TYPE_COLOR_BALANCE); GstElement *color_balance_element = NULL; gboolean done = FALSE, hardware = FALSE; #if GST_CHECK_VERSION(1, 0, 0) GValue item = G_VALUE_INIT; #else gpointer item; #endif while (!done) { switch (gst_iterator_next(iterator, &item)) { case GST_ITERATOR_OK : { #if GST_CHECK_VERSION(1, 0, 0) GstElement *element = g_value_get_object(&item); #else GstElement *element = GST_ELEMENT(item); #endif if (is_valid_color_balance_element(element)) { if (!color_balance_element) { color_balance_element = GST_ELEMENT_CAST( gst_object_ref(element)); hardware = (gst_color_balance_get_balance_type(GST_COLOR_BALANCE (element)) == GST_COLOR_BALANCE_HARDWARE); } else if (!hardware) { gboolean tmp = (gst_color_balance_get_balance_type(GST_COLOR_BALANCE (element)) == GST_COLOR_BALANCE_HARDWARE); if (tmp) { if (color_balance_element) gst_object_unref(color_balance_element); color_balance_element = GST_ELEMENT_CAST(gst_object_ref(element)); hardware = TRUE; } } } #if GST_CHECK_VERSION(1, 0, 0) g_value_reset(&item); #endif if (hardware && color_balance_element) done = TRUE; break; } case GST_ITERATOR_RESYNC : gst_iterator_resync(iterator); done = FALSE; hardware = FALSE; if (color_balance_element) gst_object_unref(color_balance_element); color_balance_element = NULL; break; case GST_ITERATOR_DONE: case GST_ITERATOR_ERROR: default: done = TRUE; } } #if GST_CHECK_VERSION(1, 0, 0) g_value_unset(&item); #endif gst_iterator_free(iterator); return color_balance_element; }