banshee r4903 - in trunk/banshee: . libbanshee
- From: abock svn gnome org
- To: svn-commits-list gnome org
- Subject: banshee r4903 - in trunk/banshee: . libbanshee
- Date: Sun, 11 Jan 2009 03:58:05 +0000 (UTC)
Author: abock
Date: Sun Jan 11 03:58:05 2009
New Revision: 4903
URL: http://svn.gnome.org/viewvc/banshee?rev=4903&view=rev
Log:
2009-01-10 Aaron Bockover <abock gnome org>
* libbanshee/banshee-ripper.c: Second pass at the mime type detection
without typefind, better mime type prioritization, and use the new
BANSHEE_GST_ITERATOR_ITERATE macro instead of the bulky functions I
wrote last night (BGO #558526, BNC #464889)
* libbanshee/banshee-gst.h: Implement BANSHEE_GST_ITERATOR_ITERATE,
a macro that handles the typical implementation of walking a GstIterator
Modified:
trunk/banshee/ChangeLog
trunk/banshee/libbanshee/banshee-gst.h
trunk/banshee/libbanshee/banshee-ripper.c
Modified: trunk/banshee/libbanshee/banshee-gst.h
==============================================================================
--- trunk/banshee/libbanshee/banshee-gst.h (original)
+++ trunk/banshee/libbanshee/banshee-gst.h Sun Jan 11 03:58:05 2009
@@ -31,6 +31,21 @@
#include <glib.h>
+#define BANSHEE_GST_ITERATOR_ITERATE(iter,child_type,child_name,free,block) { \
+ gboolean iter##_done = FALSE; \
+ while (!iter##_done) { \
+ child_type child_name; \
+ switch (gst_iterator_next (iter, (gpointer)&child_name)) { \
+ case GST_ITERATOR_OK: { \
+ { block; } \
+ break; \
+ } \
+ default: iter##_done = TRUE; break; \
+ } \
+ } \
+ if (free) gst_iterator_free (iter); \
+}
+
gboolean banshee_is_debugging ();
guint banshee_get_version_number ();
Modified: trunk/banshee/libbanshee/banshee-ripper.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-ripper.c (original)
+++ trunk/banshee/libbanshee/banshee-ripper.c Sun Jan 11 03:58:05 2009
@@ -39,6 +39,7 @@
typedef struct BansheeRipper BansheeRipper;
typedef void (* BansheeRipperFinishedCallback) (BansheeRipper *ripper);
+typedef void (* BansheeRipperMimeTypeCallback) (BansheeRipper *ripper, const gchar *mimetype);
typedef void (* BansheeRipperProgressCallback) (BansheeRipper *ripper, gint msec, gpointer user_info);
typedef void (* BansheeRipperErrorCallback) (BansheeRipper *ripper, const gchar *error, const gchar *debug);
@@ -59,6 +60,7 @@
GstFormat track_format;
BansheeRipperProgressCallback progress_cb;
+ BansheeRipperMimeTypeCallback mimetype_cb;
BansheeRipperFinishedCallback finished_cb;
BansheeRipperErrorCallback error_cb;
};
@@ -128,6 +130,55 @@
ripper->iterate_timeout_id = 0;
}
+static const gchar const *
+br_encoder_probe_mime_type (GstBin *bin)
+{
+ GstIterator *elem_iter = gst_bin_iterate_recurse (bin);
+ const gchar *preferred_mimetype = NULL;
+
+ BANSHEE_GST_ITERATOR_ITERATE (elem_iter, GstElement *, element, TRUE, {
+ GstIterator *pad_iter = gst_element_iterate_src_pads (element);
+
+ BANSHEE_GST_ITERATOR_ITERATE (pad_iter, GstPad *, pad, TRUE, {
+ GstStructure *str = GST_PAD_CAPS (pad) != NULL
+ ? gst_caps_get_structure (GST_PAD_CAPS (pad), 0)
+ : NULL;
+
+ if (str != NULL) {
+ const gchar *mimetype = gst_structure_get_name (str);
+ gint mpeg_layer;
+
+ // Prefer and adjust audio/mpeg, leaving MP3 as audio/mpeg
+ if (g_str_has_prefix (mimetype, "audio/mpeg") &&
+ gst_structure_get_int (str, "mpegversion", &mpeg_layer)) {
+ switch (mpeg_layer) {
+ case 2: mimetype = "audio/mp2"; break;
+ case 4: mimetype = "audio/mp4"; break;
+ default: break;
+ }
+
+ preferred_mimetype = mimetype;
+
+ // If no preferred type set and it's not RAW, prefer it
+ } else if (preferred_mimetype == NULL &&
+ !g_str_has_prefix (mimetype, "audio/x-raw")) {
+ preferred_mimetype = mimetype;
+
+ // Always prefer application containers
+ } else if (g_str_has_prefix (mimetype, "application/")) {
+ preferred_mimetype = mimetype;
+ }
+ }
+
+ gst_object_unref (pad);
+ });
+
+ gst_object_unref (element);
+ });
+
+ return preferred_mimetype;
+}
+
static gboolean
br_pipeline_bus_callback (GstBus *bus, GstMessage *message, gpointer data)
{
@@ -136,6 +187,22 @@
g_return_val_if_fail (ripper != NULL, FALSE);
switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_STATE_CHANGED: {
+ GstState old, new, pending;
+ gst_message_parse_state_changed (message, &old, &new, &pending);
+
+ if (old == GST_STATE_READY && new == GST_STATE_PAUSED && pending == GST_STATE_PLAYING) {
+ const gchar *mimetype = br_encoder_probe_mime_type (GST_BIN (ripper->encoder));
+ if (mimetype != NULL) {
+ banshee_log_debug ("ripper", "Found Mime Type for encoded content: %s", mimetype);
+ if (ripper->mimetype_cb != NULL) {
+ ripper->mimetype_cb (ripper, mimetype);
+ }
+ }
+ }
+ break;
+ }
+
case GST_MESSAGE_ERROR: {
GError *error;
gchar *debug;
@@ -304,10 +371,7 @@
br_rip_track (BansheeRipper *ripper, gint track_number, gchar *output_path,
GstTagList *tags, gboolean *tagging_supported)
{
- GstIterator *bin_iterator;
- GstElement *bin_element;
- gboolean can_tag = FALSE;
- gboolean iterate_done = FALSE;
+ GstIterator *iter;
g_return_val_if_fail (ripper != NULL, FALSE);
@@ -320,49 +384,28 @@
g_object_set (G_OBJECT (ripper->filesink), "location", output_path, NULL);
// find an element to do the tagging and set tag data
- bin_iterator = gst_bin_iterate_all_by_interface (GST_BIN (ripper->encoder), GST_TYPE_TAG_SETTER);
- while (!iterate_done) {
- switch (gst_iterator_next (bin_iterator, (gpointer)&bin_element)) {
- case GST_ITERATOR_OK: {
- GstTagSetter *tag_setter = GST_TAG_SETTER (bin_element);
- if (tag_setter == NULL) {
- break;
- }
-
- gst_tag_setter_add_tags (tag_setter, GST_TAG_MERGE_REPLACE_ALL,
- GST_TAG_ENCODER, "Banshee " VERSION,
- GST_TAG_ENCODER_VERSION, banshee_get_version_number (),
- NULL);
-
- if (tags != NULL) {
- gst_tag_setter_merge_tags (tag_setter, tags, GST_TAG_MERGE_APPEND);
- }
-
- if (banshee_is_debugging ()) {
- bt_tag_list_dump (gst_tag_setter_get_tag_list (tag_setter));
- }
-
- can_tag = TRUE;
- gst_object_unref (bin_element);
- break;
- }
+ iter = gst_bin_iterate_all_by_interface (GST_BIN (ripper->encoder), GST_TYPE_TAG_SETTER);
+ BANSHEE_GST_ITERATOR_ITERATE (iter, GstElement *, element, TRUE, {
+ GstTagSetter *tag_setter = GST_TAG_SETTER (element);
+ if (tag_setter != NULL) {
+ gst_tag_setter_add_tags (tag_setter, GST_TAG_MERGE_REPLACE_ALL,
+ GST_TAG_ENCODER, "Banshee " VERSION,
+ GST_TAG_ENCODER_VERSION, banshee_get_version_number (),
+ NULL);
- case GST_ITERATOR_RESYNC: {
- gst_iterator_resync (bin_iterator);
- break;
+ if (tags != NULL) {
+ gst_tag_setter_merge_tags (tag_setter, tags, GST_TAG_MERGE_APPEND);
}
- default: {
- iterate_done = TRUE;
- break;
+ if (banshee_is_debugging ()) {
+ bt_tag_list_dump (gst_tag_setter_get_tag_list (tag_setter));
}
+
+ // We'll warn the user in the UI if we can't tag the encoded audio files
+ *tagging_supported = TRUE;
+ gst_object_unref (element);
}
- }
-
- gst_iterator_free (bin_iterator);
-
- // We'll warn the user in the UI if we can't tag the encoded audio files
- *tagging_supported = can_tag;
+ });
// Begin the rip
g_object_set (G_OBJECT (ripper->cddasrc), "track", track_number, NULL);
@@ -380,6 +423,13 @@
}
void
+br_set_mimetype_callback (BansheeRipper *ripper, BansheeRipperMimeTypeCallback cb)
+{
+ g_return_if_fail (ripper != NULL);
+ ripper->mimetype_cb = cb;
+}
+
+void
br_set_finished_callback (BansheeRipper *ripper, BansheeRipperFinishedCallback cb)
{
g_return_if_fail (ripper != NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]