marlin r1309 - trunk/marlin



Author: iain
Date: Sat Oct 11 23:44:07 2008
New Revision: 1309
URL: http://svn.gnome.org/viewvc/marlin?rev=1309&view=rev

Log:
Make metadata extraction work
Neaten up preview layout


Modified:
   trunk/marlin/ChangeLog
   trunk/marlin/marlin-file-chooser.c

Modified: trunk/marlin/marlin-file-chooser.c
==============================================================================
--- trunk/marlin/marlin-file-chooser.c	(original)
+++ trunk/marlin/marlin-file-chooser.c	Sat Oct 11 23:44:07 2008
@@ -63,7 +63,10 @@
 	/* Preview */
 	GstElement *player;
 	GstElement *md_pipeline;
+	GstElement *sink;
 	GstPad *decode_pad;
+	gboolean md_eos;
+	gboolean can_decode;
 };
 
 static void
@@ -173,37 +176,6 @@
 	}
 }
 
-static gboolean
-md_message_cb (GstBus     *bus,
-	       GstMessage *message,
-	       gpointer    data)
-{
-	struct _ChooserOpenData *od = data;
-	GstTagList *tags;
-
-	switch (GST_MESSAGE_TYPE (message)) {
-	case GST_MESSAGE_EOS:
-		clear_info (od);
-		break;
-
-	case GST_MESSAGE_ERROR:
-		clear_info (od);
-		break;
-
-	case GST_MESSAGE_TAG:
-		gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (od->chooser), TRUE);
-		gst_message_parse_tag (message, &tags);
-		set_info (od, tags);
-		gst_tag_list_free (tags);
-		break;
-
-	default:
-		break;
-	}
-
-	return TRUE;
-}
-
 static void
 unknown_type_cb (GstElement              *decodebin,
 		 GstPad                  *pad,
@@ -214,32 +186,37 @@
 }
 
 static void
-have_type_cb (GstElement              *typefind,
-	      guint                    probability,
-	      GstCaps                 *caps,
-	      struct _ChooserOpenData *od)
-{
-	char *type;
-	const char *name;
-
-	type = gst_caps_to_string (caps);
-
-	name = g_content_type_get_description (type);
-	if (name) {
-		gtk_label_set_text (GTK_LABEL (od->mimetype), name);
-	} else {
-		gtk_label_set_text (GTK_LABEL (od->mimetype), type);
-	}
-	g_free (type);
-}
-
-static void
 new_pad (GstElement              *decodebin,
 	 GstPad                  *pad,
 	 gboolean                 final,
 	 struct _ChooserOpenData *od)
 {
+	GstCaps *caps;
+	GstStructure *structure;
+	const char *mimetype;
+
 	od->decode_pad = pad;
+
+	caps = gst_pad_get_caps (pad);
+
+	/* We get "ANY" caps for text/plain files etc */
+	if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
+		od->can_decode = FALSE;
+	} else {
+		/* is this pad audio? */
+		structure = gst_caps_get_structure (caps, 0);
+		mimetype = gst_structure_get_name (structure);
+		if (g_str_has_prefix (mimetype, "audio/x-raw")) {
+			GstPad *sink_pad;
+
+			/* Link this to the fakesink */
+			sink_pad = gst_element_get_pad (od->sink, "sink");
+			gst_pad_link (pad, sink_pad);
+			od->can_decode = TRUE;
+		}
+	}
+
+	gst_caps_unref (caps);
 }
 
 static void
@@ -285,18 +262,87 @@
 	gst_query_unref (query);
 }
 
+static gboolean
+metadata_bus_handler (GstBus                  *bus,
+		      GstMessage              *message,
+		      struct _ChooserOpenData *od)
+{
+	switch (GST_MESSAGE_TYPE (message)) {
+	case GST_MESSAGE_EOS:
+		od->md_eos = TRUE;
+		clear_info (od);
+		return TRUE;
+
+	case GST_MESSAGE_ERROR:
+	{
+		GError *error;
+		char *debug, *src;
+
+		gst_message_parse_error (message, &error, &debug);
+		src = gst_element_get_name (GST_MESSAGE_SRC (message));
+		g_warning ("Error from %s: %s\n%s", src, error->message, debug);
+		g_error_free (error);
+		g_free (src);
+		g_free (debug);
+
+		clear_info (od);
+		od->md_eos = TRUE;
+		return TRUE;
+	}
+
+	case GST_MESSAGE_TAG:
+	{
+		GstTagList *tags;
+
+		gst_message_parse_tag (message, &tags);
+		if (!tags) {
+			g_warning ("Could not retrieve tag list");
+			od->md_eos = TRUE;
+			return TRUE;
+		}
+
+		set_info (od, tags);
+		gst_tag_list_free (tags);
+		break;
+	}
+
+	default:
+		break;
+	}
+
+	return FALSE;
+}
+
+static void
+metadata_event_loop (struct _ChooserOpenData *od,
+		     GstBus                  *bus)
+{
+	gboolean done = FALSE;
+
+	while (!done && !od->md_eos) {
+		GstMessage *message;
+
+		message = gst_bus_pop (bus);
+		if (message == NULL) {
+			return;
+		}
+
+		done = metadata_bus_handler (bus, message, od);
+		gst_message_unref (message);
+	}
+}
+
 static void
 get_metadata (struct _ChooserOpenData *od,
-	      const char              *filename)
+	      const char              *uri)
 {
 	GstElement *decodebin, *source;
-	GstObject *typefind;
 	GstStateChangeReturn sret;
-	GstState state;
+	int change_timeout;
+	GstBus *bus;
 
 	od->md_pipeline = gst_pipeline_new (NULL);
-	gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (od->md_pipeline)),
-			   md_message_cb, od);
+	od->md_eos = FALSE;
 
 	source = marlin_make_gst_source ("source");
 	decodebin = gst_element_factory_make ("decodebin", "decodebin");
@@ -305,32 +351,63 @@
 	g_signal_connect (G_OBJECT (decodebin), "new-decoded-pad",
 			  G_CALLBACK (new_pad), od);
 
-	typefind = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (decodebin),
-						      "typefind");
-	g_signal_connect (G_OBJECT (typefind), "have-type",
-			  G_CALLBACK (have_type_cb), od);
-
-	gst_bin_add_many (GST_BIN (od->md_pipeline), source, decodebin, NULL);
+	od->sink = gst_element_factory_make ("fakesink", "fakesink");
+	gst_bin_add_many (GST_BIN (od->md_pipeline), source,
+			  decodebin, od->sink, NULL);
 	gst_element_link (source, decodebin);
 
 	g_object_set (G_OBJECT (source),
-		      "location", filename,
+		      "location", uri,
 		      NULL);
 
+	bus = gst_element_get_bus (GST_ELEMENT (od->md_pipeline));
 	sret = gst_element_set_state (od->md_pipeline, GST_STATE_PAUSED);
-
-	if (sret == GST_STATE_CHANGE_ASYNC) {
-		if (gst_element_get_state (od->md_pipeline, &state, NULL,
-					   5 * GST_SECOND) != GST_STATE_CHANGE_SUCCESS) {
-			clear_info (od);
+	change_timeout = 0;
+	while (sret == GST_STATE_CHANGE_ASYNC &&
+	       !od->md_eos && change_timeout < 5) {
+		GstMessage *msg;
+
+		msg = gst_bus_timed_pop (bus, 1 * GST_SECOND);
+		if (msg) {
+			metadata_bus_handler (bus, msg, od);
+			gst_message_unref (msg);
+			change_timeout = 0;
 		} else {
-			/* Need to wait til the state has gone to PAUSED
-			   before we get the stream info */
-			get_stream_info (od);
+			change_timeout++;
 		}
-	} else if (sret != GST_STATE_CHANGE_SUCCESS) {
-		clear_info (od);
+
+		sret = gst_element_get_state (od->md_pipeline, NULL, NULL, 1);
 	}
+
+	metadata_event_loop (od, bus);
+	gst_object_unref (bus);
+
+	get_stream_info (od);
+	if (od->can_decode) {
+		GFile *file;
+		GFileInfo *info;
+
+		file = g_file_new_for_uri (uri);
+		info = g_file_query_info (file,
+					  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+					  G_FILE_QUERY_INFO_NONE, NULL, NULL);
+		if (info) {
+			char *desc;
+			const char *content_type;
+
+			content_type = g_file_info_get_content_type (info);
+			desc = g_content_type_get_description (content_type);
+
+			gtk_label_set_text (GTK_LABEL (od->mimetype), desc);
+			g_free (desc);
+			g_object_unref (info);
+		}
+		g_object_unref (file);
+	}
+
+	gst_element_set_state (od->md_pipeline, GST_STATE_NULL);
+	gst_object_unref (GST_OBJECT (od->md_pipeline));
+	od->md_pipeline = NULL;
 }
 
 static void
@@ -353,10 +430,14 @@
 	}
 
 	if (filename != NULL) {
+		char *uri;
+
 		gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (od->chooser), TRUE);
+		uri = gtk_file_chooser_get_preview_uri (GTK_FILE_CHOOSER (od->chooser));
 		gtk_widget_set_sensitive (od->play, TRUE);
-		get_metadata (od, filename);
+		get_metadata (od, uri);
 		g_free (filename);
+		g_free (uri);
 	} else {
 		gtk_file_chooser_set_preview_widget_active (GTK_FILE_CHOOSER (od->chooser), FALSE);
 		gtk_widget_set_sensitive (od->play, FALSE);
@@ -407,7 +488,7 @@
 	g_object_set (G_OBJECT (od->player),
 		      "uri", uri,
 		      NULL);
-	
+
 	gst_element_set_state (od->player, GST_STATE_PLAYING);
 
 	gtk_widget_hide (od->play);
@@ -419,7 +500,7 @@
 	      struct _ChooserOpenData *od)
 {
 	gst_element_set_state (od->player, GST_STATE_READY);
-	
+
 	gtk_widget_hide (od->stop);
 	gtk_widget_show (od->play);
 }
@@ -434,28 +515,12 @@
 	gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (od->chooser), vbox);
 
 	od->name = marlin_make_title_label (_("Untitled"));
+	gtk_misc_set_alignment (GTK_MISC (od->name), 0.5, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (od->name), TRUE);
 	gtk_box_pack_start (GTK_BOX (vbox), od->name, FALSE, FALSE, 0);
 
-	hbox = gtk_hbox_new (FALSE, 6);
-	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
-
-	spacer = gtk_label_new ("    ");
-	gtk_box_pack_start (GTK_BOX (hbox), spacer, FALSE, FALSE, 0);
-	
 	table = marlin_make_table (4, 2, FALSE);
-	gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
-
-#if 0
-	label = marlin_make_title_label (_("Name:"));
-	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
-	PACK (table, label, 0, 0, GTK_FILL);
-
-	gtk_label_set_line_wrap (GTK_LABEL (od->name), TRUE);
-	PACK (table, od->name, 1, 0, GTK_FILL);
-
-	marlin_add_paired_relations (label, ATK_RELATION_LABEL_FOR,
-				     od->name, ATK_RELATION_LABELLED_BY);
-#endif
+	gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
 
 	label = marlin_make_title_label (_("Mime Type:"));
 	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
@@ -466,7 +531,7 @@
 
 	marlin_add_paired_relations (label, ATK_RELATION_LABEL_FOR,
 				     od->mimetype, ATK_RELATION_LABELLED_BY);
-	
+
 	label = marlin_make_title_label (_("Length:"));
 	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
 	PACK (table, label, 0, 1, GTK_FILL);
@@ -476,7 +541,7 @@
 
 	marlin_add_paired_relations (label, ATK_RELATION_LABEL_FOR,
 				     od->length, ATK_RELATION_LABELLED_BY);
-	
+
 	label = marlin_make_title_label (_("Sample Rate:"));
 	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
 	PACK (table, label, 0, 2, GTK_FILL);
@@ -486,7 +551,7 @@
 
 	marlin_add_paired_relations (label, ATK_RELATION_LABEL_FOR,
 				     od->sample_rate, ATK_RELATION_LABELLED_BY);
-	
+
 	label = marlin_make_title_label (_("Channels:"));
 	gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
 	PACK (table, label, 0, 3, GTK_FILL);
@@ -496,7 +561,7 @@
 
 	marlin_add_paired_relations (label, ATK_RELATION_LABEL_FOR,
 				     od->channels, ATK_RELATION_LABELLED_BY);
-	
+
 	hbox = gtk_hbox_new (FALSE, 6);
 	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
@@ -510,7 +575,7 @@
 	g_signal_connect (G_OBJECT (od->stop), "clicked",
 			  G_CALLBACK (stop_playing), od);
 	gtk_box_pack_start (GTK_BOX (hbox), od->stop, FALSE, FALSE, 0);
-	
+
 	gtk_widget_show_all (vbox);
 	gtk_widget_hide (od->stop);
 }
@@ -524,7 +589,7 @@
 	char *filename;
 
 	od = g_new0 (struct _ChooserOpenData, 1);
-	
+
 	widget = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
 			       "action", GTK_FILE_CHOOSER_ACTION_OPEN,
 			       "title", _("Open File"),
@@ -535,16 +600,11 @@
 
 	build_info_contents (od);
 
-	/* Check if we can display the first selected file */
-	filename = gtk_file_chooser_get_preview_filename (GTK_FILE_CHOOSER (widget));
- 	get_metadata (od, filename);
-	g_free (filename);
-	
 	g_signal_connect (G_OBJECT (od->chooser), "destroy",
 			  G_CALLBACK (free_open_data), od);
 	g_signal_connect (G_OBJECT (od->chooser), "update-preview",
 			  G_CALLBACK (selection_changed), od);
-	
+
 	gtk_dialog_add_buttons (GTK_DIALOG (widget),
 				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 				GTK_STOCK_OPEN, GTK_RESPONSE_OK,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]