[rygel] core: Revert "Remove MetadataExtractor class."
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: svn-commits-list gnome org
- Subject: [rygel] core: Revert "Remove MetadataExtractor class."
- Date: Thu, 25 Jun 2009 15:44:34 +0000 (UTC)
commit 96135fc8f918ac1137c1042a244f93fcaf2f3d0e
Author: Jens Georg <mail jensge org>
Date: Fri May 22 14:33:05 2009 +0200
core: Revert "Remove MetadataExtractor class."
This reverts commit 4d530bd0347c69a95110c7d399372e19cdf83793.
libowl would drag in a hard dependency to GTK+ which is not desired
Conflicts:
src/rygel/Makefile.am
src/rygel/rygel-metadata-extractor.vala | 286 +++++++++++++++++++++++++++++++
1 files changed, 286 insertions(+), 0 deletions(-)
---
diff --git a/src/rygel/rygel-metadata-extractor.vala b/src/rygel/rygel-metadata-extractor.vala
new file mode 100644
index 0000000..57f39f3
--- /dev/null
+++ b/src/rygel/rygel-metadata-extractor.vala
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
+ *
+ * Author: Zeeshan Ali <zeenix gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+using Gst;
+using GUPnP;
+
+private enum Gst.StreamType {
+ UNKNOWN = 0,
+ AUDIO = 1, /* an audio stream */
+ VIDEO = 2, /* a video stream */
+ TEXT = 3, /* a subtitle/text stream */
+ SUBPICTURE = 4, /* a subtitle in picture-form */
+ ELEMENT = 5 /* stream handled by an element */
+}
+
+/**
+ * Metadata extractor based on Gstreamer. Just set the URI of the media on the
+ * uri property, it will extact the metadata for you and emit signal
+ * metadata_available for each key/value pair extracted.
+ */
+public class Rygel.MetadataExtractor: GLib.Object {
+
+ /* TODO: Use tagbin instead once it's ready */
+ private dynamic Gst.Element playbin;
+
+ /* Signals */
+ public signal void metadata_available (string uri,
+ string key,
+ ref Gst.Value value);
+ public signal void extraction_done (string uri);
+
+ /* Properties */
+ public string uri {
+ get {
+ return this.playbin.uri;
+ }
+
+ set {
+ this.playbin.uri = value;
+
+ if (this.playbin.uri != null) {
+ extract_mime ();
+ /* Start the extaction when we get a new URI */
+ this.playbin.set_state (State.PAUSED);
+ }
+ }
+ }
+
+ /* A list of URIs to extract metadata from */
+ public List <string> _uris = null;
+ public List <string> uris {
+ get {
+ return this._uris;
+ }
+
+ set {
+ this._uris = value.copy ();
+
+ if (this._uris != null) {
+ this.extraction_done += this.goto_next_uri;
+ this.uri = this._uris.data;
+ } else {
+ this.extraction_done -= this.goto_next_uri;
+ }
+ }
+ }
+
+ public MetadataExtractor () {
+ this.playbin = ElementFactory.make ("playbin", null);
+
+ var bus = this.playbin.get_bus ();
+
+ bus.add_signal_watch ();
+
+ bus.message["tag"] += this.tag_cb;
+ bus.message["state-changed"] += this.state_changed_cb;
+ bus.message["error"] += this.error_cb;
+ }
+
+ /* Callback for tags found by playbin */
+ private void tag_cb (Gst.Bus bus,
+ Gst.Message message) {
+ TagList tag_list;
+
+ message.parse_tag (out tag_list);
+
+ tag_list.foreach (this.foreach_tag);
+ }
+
+ /* Callback for state-change in playbin */
+ private void state_changed_cb (Gst.Bus bus,
+ Gst.Message message) {
+ if (message.src != this.playbin)
+ return;
+
+ State new_state;
+ State old_state;
+
+ message.parse_state_changed (out old_state, out new_state, null);
+ if (new_state == State.PAUSED && old_state == State.READY) {
+ this.extract_duration ();
+ this.extract_stream_info ();
+
+ /* No hopes of getting any tags after this point */
+ this.playbin.set_state (State.NULL);
+ this.extraction_done (this.playbin.uri);
+ }
+ }
+
+ /* Callback for errors in playbin */
+ private void error_cb (Gst.Bus bus,
+ Gst.Message message) {
+
+ return_if_fail (this.uri != null);
+
+ Error error = null;
+ string debug;
+
+ message.parse_error (out error, out debug);
+ if (error != null) {
+ debug = error.message;
+ }
+
+ critical ("Failed to extract metadata from %s: %s\n", this.uri, debug);
+
+ if (this._uris != null) {
+ /* We have a list of URIs to harvest, so lets jump to next one */
+ this.goto_next_uri (this, this.uri);
+ }
+ }
+
+ /* Fetch value of each tag in the @tag_list and signal it's availability */
+ private void foreach_tag (TagList tag_list, string tag) {
+ Gst.Value value = Gst.Value ();
+
+ if (tag_list.copy_value (out value, tag_list, tag)) {
+ this.metadata_available (this.playbin.uri, tag, ref value);
+ }
+ }
+
+ private void goto_next_uri (MetadataExtractor extractor,
+ string uri) {
+ return_if_fail (this._uris != null);
+
+ weak List <string> link = this._uris.find_custom (uri, strcmp);
+ this._uris.remove_link (link);
+
+ if (this._uris != null) {
+ this.uri = this._uris.data;
+ } else {
+ this.extraction_done -= this.goto_next_uri;
+ }
+ }
+
+ private void extract_mime () {
+ File file = File.new_for_uri (this.uri);
+
+ FileInfo file_info;
+
+ try {
+ file_info = file.query_info (FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ FileQueryInfoFlags.NONE,
+ null);
+ } catch (Error error) {
+ critical ("Failed to query content type for '%s'\n", this.uri);
+
+ return;
+ }
+
+ weak string content_type = file_info.get_content_type ();
+ weak string mime = g_content_type_get_mime_type (content_type);
+ if (mime != null) {
+ Gst.Value value = Gst.Value ();
+
+ value.init (typeof (string));
+ value.set_string (mime);
+
+ /* signal the availability of new tag */
+ this.metadata_available (this.playbin.uri, "mime-type", ref value);
+ }
+ }
+
+ private void extract_duration () {
+ int64 duration;
+
+ Format format = Format.TIME;
+ if (this.playbin.query_duration (ref format, out duration)) {
+ Gst.Value duration_val = Gst.Value ();
+
+ duration_val.init (typeof (int64));
+ duration_val.set_int64 (duration);
+
+ /* signal the availability of duration tag */
+ this.metadata_available (this.playbin.uri,
+ TAG_DURATION,
+ ref duration_val);
+ }
+ }
+
+ private void extract_stream_info () {
+ weak List <dynamic GLib.Object> stream_info = null;
+
+ stream_info = this.playbin.stream_info;
+ return_if_fail (stream_info != null);
+
+ for (var i = 0; i < stream_info.length (); i++) {
+ dynamic GLib.Object info = stream_info.nth_data (i);
+
+ if (info == null) {
+ continue;
+ }
+
+ extract_av_info (info);
+ }
+ }
+
+ private void extract_av_info (dynamic GLib.Object info) {
+ Pad pad = (Pad) info.object;
+ if (pad == null) {
+ return;
+ }
+
+ Gst.Caps caps = pad.get_negotiated_caps ();
+ if (caps == null) {
+ return;
+ }
+
+ weak Structure structure = caps.get_structure (0);
+ if (structure == null) {
+ return;
+ }
+
+ StreamType type = info.type;
+ if (type == StreamType.AUDIO) {
+ this.extract_audio_info (structure);
+ } else if (type == StreamType.VIDEO) {
+ this.extract_video_info (structure);
+ }
+ }
+
+ private void extract_audio_info (Structure structure) {
+ this.extract_int_value (structure, "channels");
+ this.extract_int_value (structure, "rate");
+ }
+
+ private void extract_video_info (Structure structure) {
+ this.extract_int_value (structure, "width");
+ this.extract_int_value (structure, "height");
+ }
+
+ private void extract_int_value (Structure structure, string key) {
+ int val;
+
+ if (structure.get_int (key, out val)) {
+ Gst.Value value = Gst.Value ();
+
+ value.init (typeof (int));
+ value.set_int (val);
+
+ /* signal the availability of new tag */
+ this.metadata_available (this.playbin.uri, key, ref value);
+ }
+ }
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]