banshee r4898 - in trunk/banshee: . libbanshee src/Backends/Banshee.GStreamer/Banshee.GStreamer
- From: abock svn gnome org
- To: svn-commits-list gnome org
- Subject: banshee r4898 - in trunk/banshee: . libbanshee src/Backends/Banshee.GStreamer/Banshee.GStreamer
- Date: Sat, 10 Jan 2009 05:08:47 +0000 (UTC)
Author: abock
Date: Sat Jan 10 05:08:47 2009
New Revision: 4898
URL: http://svn.gnome.org/viewvc/banshee?rev=4898&view=rev
Log:
2009-01-09 Aaron Bockover <abock gnome org>
* src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs:
Handle the new mimetype callback and set it on the track (BGO #558526,
BNC #464889)
* libbanshee/banshee-ripper.c: Implemented support for the typefind
element in the pipeline after the encoder to query a proper mime type
for the encoded and muxed content
* libbanshee/banshee-gst.h:
* libbanshee/banshee-gst.c: Factored out a generic callback invoking
version of gst_bin_iterate_recurse and gst_bin_iterate_all_by_interface
to avoid duplicating a lot of iterator boilerplate code
Modified:
trunk/banshee/ChangeLog
trunk/banshee/libbanshee/banshee-gst.c
trunk/banshee/libbanshee/banshee-gst.h
trunk/banshee/libbanshee/banshee-ripper.c
trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs
Modified: trunk/banshee/libbanshee/banshee-gst.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-gst.c (original)
+++ trunk/banshee/libbanshee/banshee-gst.c Sat Jan 10 05:08:47 2009
@@ -152,3 +152,47 @@
g_free (message);
}
+
+gboolean
+banshee_gst_bin_iterate_all_by_interface (GstBin *bin, GType type, BansheeGstBinIterateCallback callback, gpointer data)
+{
+ GstIterator *bin_iterator;
+ gpointer bin_element;
+ gboolean iterate_done = FALSE;
+ gboolean success = TRUE;
+
+ bin_iterator = type == G_TYPE_NONE
+ ? gst_bin_iterate_recurse (bin)
+ : gst_bin_iterate_all_by_interface (bin, type);
+
+ while (!iterate_done) {
+ switch (gst_iterator_next (bin_iterator, (gpointer)&bin_element)) {
+ case GST_ITERATOR_OK:
+ if (callback != NULL && !callback (bin, type, bin_element, data)) {
+ iterate_done = TRUE;
+ }
+
+ gst_object_unref (bin_element);
+ break;
+ case GST_ITERATOR_RESYNC:
+ gst_iterator_resync (bin_iterator);
+ break;
+ case GST_ITERATOR_ERROR:
+ success = FALSE;
+ iterate_done = TRUE;
+ break;
+ default:
+ iterate_done = TRUE;
+ break;
+ }
+ }
+
+ gst_iterator_free (bin_iterator);
+ return success;
+}
+
+gboolean
+banshee_gst_bin_iterate_recurse (GstBin *bin, BansheeGstBinIterateCallback callback, gpointer data)
+{
+ return banshee_gst_bin_iterate_all_by_interface (bin, G_TYPE_NONE, callback, data);
+}
Modified: trunk/banshee/libbanshee/banshee-gst.h
==============================================================================
--- trunk/banshee/libbanshee/banshee-gst.h (original)
+++ trunk/banshee/libbanshee/banshee-gst.h Sat Jan 10 05:08:47 2009
@@ -29,11 +29,15 @@
#ifndef _BANSHEE_GST_H
#define _BANSHEE_GST_H
-#include <glib.h>
+#include <gst/gst.h>
gboolean banshee_is_debugging ();
guint banshee_get_version_number ();
void banshee_log_debug (const gchar *component, const gchar *format, ...);
+typedef gboolean (* BansheeGstBinIterateCallback) (GstBin *bin, GType type, gpointer bin_element, gpointer data);
+gboolean banshee_gst_bin_iterate_all_by_interface (GstBin *bin, GType type, BansheeGstBinIterateCallback callback, gpointer data);
+gboolean banshee_gst_bin_iterate_recurse (GstBin *bin, BansheeGstBinIterateCallback callback, gpointer data);
+
#endif /* _BANSHEE_GST_H */
Modified: trunk/banshee/libbanshee/banshee-ripper.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-ripper.c (original)
+++ trunk/banshee/libbanshee/banshee-ripper.c Sat Jan 10 05:08:47 2009
@@ -32,6 +32,7 @@
#include <string.h>
#include <glib/gi18n.h>
+#include <glib/gstdio.h>
#include "banshee-gst.h"
#include "banshee-tagger.h"
@@ -39,6 +40,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);
@@ -54,11 +56,13 @@
GstElement *pipeline;
GstElement *cddasrc;
GstElement *encoder;
+ GstElement *typefind;
GstElement *filesink;
GstFormat track_format;
BansheeRipperProgressCallback progress_cb;
+ BansheeRipperMimeTypeCallback mimetype_cb;
BansheeRipperFinishedCallback finished_cb;
BansheeRipperErrorCallback error_cb;
};
@@ -170,6 +174,83 @@
return TRUE;
}
+static gboolean
+br_check_for_aac (GstBin *bin, GType type, gpointer bin_element, gpointer data)
+{
+ gboolean *override = (gboolean *)data;
+ *override = g_str_has_suffix (G_OBJECT_TYPE_NAME (bin_element), "AacEnc");
+ return !(*override);
+}
+
+
+static void
+br_have_type (GstElement *typefind, guint probability, GstCaps *caps, gpointer data)
+{
+ BansheeRipper *ripper = (BansheeRipper *)data;
+ const GstStructure *str;
+ const gchar *gst_mimetype;
+ const gchar *mimetype;
+
+ str = gst_caps_get_structure (caps, 0);
+ if ((gst_mimetype = str != NULL ? gst_structure_get_name (str) : NULL) == NULL) {
+ return;
+ }
+
+ mimetype = gst_mimetype;
+
+ // Certain AAC plugins report the type as video/quicktime, so if
+ // we encounter this mimetype, iterate the encoder pipeline segment
+ // for an offending element and override the type
+ if (g_str_has_prefix (mimetype, "video/quicktime")) {
+ gboolean override = FALSE;
+ banshee_gst_bin_iterate_recurse (GST_BIN (ripper->encoder), br_check_for_aac, &override);
+ if (override) {
+ mimetype = "audio/mp4";
+ }
+ }
+
+ if (banshee_is_debugging ()) {
+ g_printf ("Found Mime Type for encoded content: %s (probability = %d)\n",
+ mimetype, probability);
+ }
+
+ if (ripper->mimetype_cb != NULL) {
+ ripper->mimetype_cb (ripper, mimetype);
+ }
+}
+
+static gboolean
+br_set_tags (GstBin *bin, GType type, gpointer bin_element, gpointer data)
+{
+ struct iterator_data_t {
+ GstTagList *tags;
+ gboolean can_tag;
+ } *iterator_data = (struct iterator_data_t *)data;
+
+ GstTagSetter *tag_setter = GST_TAG_SETTER (bin_element);
+ if (tag_setter == NULL) {
+ return TRUE;
+ }
+
+ 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 (iterator_data->tags != NULL) {
+ gst_tag_setter_merge_tags (tag_setter, iterator_data->tags, GST_TAG_MERGE_APPEND);
+ }
+
+ if (banshee_is_debugging ()) {
+ bt_tag_list_dump (gst_tag_setter_get_tag_list (tag_setter));
+ }
+
+ iterator_data->can_tag = TRUE;
+
+ return TRUE;
+}
+
+
static GstElement *
br_pipeline_build_encoder (const gchar *pipeline, GError **error_out)
{
@@ -230,15 +311,26 @@
g_object_set (G_OBJECT (queue), "max-size-time", 120 * GST_SECOND, NULL);
+ ripper->typefind = gst_element_factory_make ("typefind", "typefind");
+ if (ripper->typefind == NULL) {
+ br_raise_error (ripper, _("Could not create typefind plugin"), NULL);
+ return FALSE;
+ }
+
+ g_signal_connect (G_OBJECT (ripper->typefind), "have-type",
+ G_CALLBACK (br_have_type), ripper);
+
ripper->filesink = gst_element_factory_make ("filesink", "filesink");
if (ripper->filesink == NULL) {
br_raise_error (ripper, _("Could not create filesink plugin"), NULL);
return FALSE;
}
- gst_bin_add_many (GST_BIN (ripper->pipeline), ripper->cddasrc, queue, ripper->encoder, ripper->filesink, NULL);
+ gst_bin_add_many (GST_BIN (ripper->pipeline), ripper->cddasrc, queue,
+ ripper->encoder, ripper->typefind, ripper->filesink, NULL);
- if (!gst_element_link_many (ripper->cddasrc, queue, ripper->encoder, ripper->filesink, NULL)) {
+ if (!gst_element_link_many (ripper->cddasrc, queue, ripper->encoder,
+ ripper->typefind, ripper->filesink, NULL)) {
br_raise_error (ripper, _("Could not link pipeline elements"), NULL);
}
@@ -295,7 +387,7 @@
if (ripper->encoder_pipeline != NULL) {
g_free (ripper->encoder_pipeline);
}
-
+
g_free (ripper);
ripper = NULL;
}
@@ -304,10 +396,10 @@
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;
+ struct {
+ GstTagList *tags;
+ gboolean can_tag;
+ } iterator_data = { tags, FALSE };
g_return_val_if_fail (ripper != NULL, FALSE);
@@ -320,49 +412,11 @@
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;
- }
-
- case GST_ITERATOR_RESYNC: {
- gst_iterator_resync (bin_iterator);
- break;
- }
-
- default: {
- iterate_done = TRUE;
- break;
- }
- }
- }
-
- gst_iterator_free (bin_iterator);
-
+ banshee_gst_bin_iterate_all_by_interface (GST_BIN (ripper->encoder), GST_TYPE_TAG_SETTER,
+ br_set_tags, &iterator_data);
+
// We'll warn the user in the UI if we can't tag the encoded audio files
- *tagging_supported = can_tag;
+ *tagging_supported = iterator_data.can_tag;
// Begin the rip
g_object_set (G_OBJECT (ripper->cddasrc), "track", track_number, NULL);
@@ -380,6 +434,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);
Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs (original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/AudioCdRipper.cs Sat Jan 10 05:08:47 2009
@@ -50,6 +50,7 @@
private TrackInfo current_track;
private RipperProgressHandler progress_handler;
+ private RipperMimeTypeHandler mimetype_handler;
private RipperFinishedHandler finished_handler;
private RipperErrorHandler error_handler;
@@ -95,6 +96,9 @@
progress_handler = new RipperProgressHandler (OnNativeProgress);
br_set_progress_callback (handle, progress_handler);
+ mimetype_handler = new RipperMimeTypeHandler (OnNativeMimeType);
+ br_set_mimetype_callback (handle, mimetype_handler);
+
finished_handler = new RipperFinishedHandler (OnNativeFinished);
br_set_finished_callback (handle, finished_handler);
@@ -173,6 +177,21 @@
OnProgress (current_track, TimeSpan.FromMilliseconds (mseconds));
}
+ private void OnNativeMimeType (IntPtr ripper, IntPtr mimetype)
+ {
+ if (mimetype != IntPtr.Zero && current_track != null) {
+ string type = GLib.Marshaller.Utf8PtrToString (mimetype);
+ if (type != null) {
+ string [] split = type.Split (';', '.', ' ', '\t');
+ if (split != null && split.Length > 0) {
+ current_track.MimeType = split[0].Trim ();
+ } else {
+ current_track.MimeType = type.Trim ();
+ }
+ }
+ }
+ }
+
private void OnNativeFinished (IntPtr ripper)
{
SafeUri uri = new SafeUri (output_path);
@@ -198,6 +217,7 @@
}
private delegate void RipperProgressHandler (IntPtr ripper, int mseconds);
+ private delegate void RipperMimeTypeHandler (IntPtr ripper, IntPtr mimetype);
private delegate void RipperFinishedHandler (IntPtr ripper);
private delegate void RipperErrorHandler (IntPtr ripper, IntPtr error, IntPtr debug);
@@ -215,6 +235,9 @@
private static extern void br_set_progress_callback (HandleRef handle, RipperProgressHandler callback);
[DllImport ("libbanshee")]
+ private static extern void br_set_mimetype_callback (HandleRef handle, RipperMimeTypeHandler callback);
+
+ [DllImport ("libbanshee")]
private static extern void br_set_finished_callback (HandleRef handle, RipperFinishedHandler callback);
[DllImport ("libbanshee")]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]