[Rhythmbox-devel] MPEG-4 metadata loading



Heya,

Here we go, iTunes can encode them, we play them.

We use libmp4v2 from libfaad2 to get the metadata and all. The xine-lib
backend can play them back out of the box, no idea about GStreamer.

About the patch:
- configure checks for mp4.h and mpeg4ip.h
- add the audio/x-m4a mime-type as supported (requires CVS HEAD
gnome-mime-data)
- MP4 stream metadata implementation (new files)
- change the name of the xine backend to "xine-lib"
- parsing fixes for directory loading

Note that the faad2-devel package on freshrpms.net contains a couple of
bugs that might break the build:
- mp4.h and mpeg4ip.h headers missing
- the stock mpeg4ip.h includes a non-existant (and not needed afaics)
systems.h file)
- libmp4v2.so isn't linked against libstdc++ (bit of a bummer, worked
around in the configure.ac patch)
Matthias, I hope you can fix those for us :)

TODO (but not by me):
- be able to load non-local files using gnome-vfs with the file
callbacks (see MP4ReadCb)
- setting the metadata (the API is neato, this is like 30 minutes work,
get_value and set the metadata)

Cheers

---
Bastien Nocera <hadess@hadess.net> 
McMurphy fell 12 stories, hitting the pavement like a paper bag filled
with vegetable soup. 
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/rhythmbox/configure.ac,v
retrieving revision 1.58
diff -u -r1.58 configure.ac
--- configure.ac	12 Nov 2003 19:01:12 -0000	1.58
+++ configure.ac	17 Nov 2003 22:03:22 -0000
@@ -188,6 +188,21 @@
 fi
 AM_CONDITIONAL(HAVE_MP3,test "x$enable_mp3" = "xyes")
 
+dnl Check for libmp4v2
+
+AC_ARG_ENABLE(mp4, AC_HELP_STRING([--disable-mp4],
+			[don't build with MPEG-4 support]))
+if test "x$enable_mp4" != "xno"; then
+  AC_CHECK_HEADER(mp4.h, [
+		  AC_CHECK_HEADER(mpeg4ip.h, [enable_mp4=yes],)],)
+fi
+if test "x$enable_mp4" != "xno"; then
+  LIBS="$LIBS -lmp4v2 -lstdc++"
+  AC_DEFINE(HAVE_MP4,,[Define if we have MPEG-4 support])
+fi
+
+AM_CONDITIONAL(HAVE_MP4, test "x$enable_mp4" = "xyes")
+
 dnl Check for Ogg Vorbis
 
 AC_ARG_ENABLE(vorbis, AC_HELP_STRING([--disable-vorbis],
@@ -417,6 +432,11 @@
 	AC_MSG_NOTICE([   FLAC support is disabled])
 else
 	AC_MSG_NOTICE([** FLAC support is enabled])
+fi
+if test x"$enable_mp4" != "xyes"; then
+	AC_MSG_NOTICE([   MPEG-4 support is disabled])
+else
+	AC_MSG_NOTICE([** MPEG-4 support is enabled])
 fi
 dnl if test x"$enable_musicbrainz" != "xyes"; then
 dnl 	AC_MSG_NOTICE([   MusicBrainz support is disabled])
Index: lib/rb-playlist.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/lib/rb-playlist.c,v
retrieving revision 1.5
diff -u -r1.5 rb-playlist.c
--- lib/rb-playlist.c	5 Nov 2003 17:16:42 -0000	1.5
+++ lib/rb-playlist.c	17 Nov 2003 22:03:25 -0000
@@ -937,7 +937,7 @@
 	info = gnome_vfs_file_info_new ();
 	res = gnome_vfs_directory_read_next (handle, info);
 	while (res == GNOME_VFS_OK) {
-		char *fullpath;
+		char *str, *fullpath;
 
 		if (info->name != NULL && (strcmp (info->name, ".") == 0
 					|| strcmp (info->name, "..") == 0)) {
@@ -945,13 +945,18 @@
 			continue;
 		}
 
-		fullpath = g_build_filename (G_DIR_SEPARATOR_S,
+		str = g_build_filename (G_DIR_SEPARATOR_S,
 					     url, info->name, NULL);
-		if (rb_playlist_parse (playlist, strstr (fullpath, "://")
-				       ? fullpath + 1 : fullpath) != FALSE) {
-			retval = TRUE;
-		}
-		g_free (fullpath);
+		if (strstr (str, "://") != NULL)
+			fullpath = str + 1;
+		else
+			fullpath = str;
+
+		if (rb_playlist_parse (playlist, fullpath) == FALSE)
+			rb_playlist_add_one_url (playlist, fullpath, NULL);
+
+		retval = TRUE;
+		g_free (str);
 		res = gnome_vfs_directory_read_next (handle, info);
 	}
 
Index: monkey-media/monkey-media.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/monkey-media/monkey-media.c,v
retrieving revision 1.5
diff -u -r1.5 monkey-media.c
--- monkey-media/monkey-media.c	16 Nov 2003 17:59:08 -0000	1.5
+++ monkey-media/monkey-media.c	17 Nov 2003 22:03:26 -0000
@@ -55,6 +55,9 @@
 #ifdef HAVE_FLAC
 #include "flac-stream-info-impl.h"
 #endif
+#ifdef HAVE_MP4
+#include "mp4-stream-info-impl.h"
+#endif
 
 static void monkey_media_init_internal (void);
 static void monkey_media_audio_driver_changed (GConfClient *client, guint cnxn_id,
@@ -197,6 +200,10 @@
 		       TYPE_MP3_STREAM_INFO_IMPL);
 	register_type ("audio/x-wav",
 		       TYPE_MP3_STREAM_INFO_IMPL);
+#endif
+#ifdef HAVE_MP4
+	register_type ("audio/x-m4a",
+		       TYPE_MP4_STREAM_INFO_IMPL);
 #endif
 #ifdef HAVE_AUDIOCD
 	register_type ("audiocd",
Index: monkey-media/stream-info-impl/Makefile.am
===================================================================
RCS file: /cvs/gnome/rhythmbox/monkey-media/stream-info-impl/Makefile.am,v
retrieving revision 1.4
diff -u -r1.4 Makefile.am
--- monkey-media/stream-info-impl/Makefile.am	16 Nov 2003 16:56:43 -0000	1.4
+++ monkey-media/stream-info-impl/Makefile.am	17 Nov 2003 22:03:26 -0000
@@ -28,6 +28,10 @@
 libstream_info_impl_la_SOURCES += mp3-stream-info-impl.c mp3-stream-info-impl.h 
 endif
 
+if HAVE_MP4
+libstream_info_impl_la_SOURCES += mp4-stream-info-impl.c mp4-stream-info-impl.h
+endif
+
 INCLUDES = 						\
         -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
 	-DG_LOG_DOMAIN=\"MonkeyMedia\"			\
Index: monkey-media/stream-info-impl/mp4-stream-info-impl.c
===================================================================
RCS file: monkey-media/stream-info-impl/mp4-stream-info-impl.c
diff -N monkey-media/stream-info-impl/mp4-stream-info-impl.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ monkey-media/stream-info-impl/mp4-stream-info-impl.c	17 Nov 2003 22:03:27 -0000
@@ -0,0 +1,511 @@
+/*  monkey-sound
+ *
+ *  arch-tag: Implementation of MP4 metadata loading
+ *
+ *  Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <mp4.h>
+
+#include "rb-string-helpers.h"
+
+#include "monkey-media-stream-info.h"
+#include "monkey-media-private.h"
+
+#include "mp4-stream-info-impl.h"
+
+/* MP4 audio type */
+#define MP4_MPEG4_AUDIO_TYPE 0x40
+
+static void MP4_stream_info_impl_class_init (MP4StreamInfoImplClass *klass);
+static void MP4_stream_info_impl_init (MP4StreamInfoImpl *ma);
+static void MP4_stream_info_impl_finalize (GObject *object);
+static void MP4_stream_info_impl_open_stream (MonkeyMediaStreamInfo *info);
+static gboolean MP4_stream_info_impl_get_value (MonkeyMediaStreamInfo *info,
+					        MonkeyMediaStreamInfoField field,
+					        int index,
+					        GValue *value);
+static gboolean MP4_stream_info_impl_set_value (MonkeyMediaStreamInfo *info,
+					        MonkeyMediaStreamInfoField field,
+					        int index,
+					        const GValue *value);
+static int MP4_stream_info_impl_get_n_values (MonkeyMediaStreamInfo *info,
+				              MonkeyMediaStreamInfoField field);
+
+struct MP4StreamInfoImplPrivate
+{
+	MP4FileHandle file;
+	int track_id;
+};
+
+static GObjectClass *parent_class = NULL;
+
+GType
+MP4_stream_info_impl_get_type (void)
+{
+	static GType MP4_stream_info_impl_type = 0;
+
+	if (MP4_stream_info_impl_type == 0)
+	{
+		static const GTypeInfo our_info =
+		{
+			sizeof (MP4StreamInfoImplClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) MP4_stream_info_impl_class_init,
+			NULL,
+			NULL,
+			sizeof (MP4StreamInfoImpl),
+			0,
+			(GInstanceInitFunc) MP4_stream_info_impl_init
+		};
+
+		MP4_stream_info_impl_type = g_type_register_static (MONKEY_MEDIA_TYPE_STREAM_INFO,
+								       "MP4StreamInfoImpl",
+								       &our_info, 0);
+	}
+
+	return MP4_stream_info_impl_type;
+}
+
+static void
+MP4_stream_info_impl_class_init (MP4StreamInfoImplClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	MonkeyMediaStreamInfoClass *info_class = MONKEY_MEDIA_STREAM_INFO_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = MP4_stream_info_impl_finalize;
+
+	info_class->open_stream  = MP4_stream_info_impl_open_stream;
+	info_class->get_n_values = MP4_stream_info_impl_get_n_values;
+	info_class->get_value    = MP4_stream_info_impl_get_value;
+	info_class->set_value    = MP4_stream_info_impl_set_value;
+}
+
+static void
+MP4_stream_info_impl_init (MP4StreamInfoImpl *impl)
+{
+	impl->priv = g_new0 (MP4StreamInfoImplPrivate, 1);
+}
+
+static void
+MP4_stream_info_impl_finalize (GObject *object)
+{
+	MP4StreamInfoImpl *impl;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (IS_MP4_STREAM_INFO_IMPL (object));
+
+	impl = MP4_STREAM_INFO_IMPL (object);
+
+	g_return_if_fail (impl->priv != NULL);
+
+	if (impl->priv->file != 0)
+		MP4Close (impl->priv->file);
+
+	g_free (impl->priv);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+MP4_stream_info_impl_open_stream (MonkeyMediaStreamInfo *info)
+{
+	MP4StreamInfoImpl *impl = MP4_STREAM_INFO_IMPL (info);
+	char *uri, *path;
+	GError *error;
+	int num_tracks, i;
+	gboolean found;
+
+	g_object_get (G_OBJECT (info),
+		      "error", &error,
+		      "location", &uri,
+		      NULL);
+
+	path = g_filename_from_uri (uri, NULL, NULL);
+
+	if (path == NULL)
+	{
+		impl->priv->file = MP4Read (uri, 0);
+	} else {
+		impl->priv->file = MP4Read (path, 0);
+	}
+
+	g_free (path);
+	g_free (uri);
+
+	if (impl->priv->file == 0)
+	{
+		error = g_error_new (MONKEY_MEDIA_STREAM_INFO_ERROR,
+				     MONKEY_MEDIA_STREAM_INFO_ERROR_OPEN_FAILED,
+				     _("Failed to recognise filetype"));
+		g_object_set (G_OBJECT (info), "error", error, NULL);
+		return;
+	}
+
+	/* Find a sound track */
+	num_tracks = MP4GetNumberOfTracks (impl->priv->file, NULL, 0);
+	found = FALSE;
+	for (i = 0; i < num_tracks; i++)
+	{
+		MP4TrackId track_id;
+		const char *track_type;
+
+		track_id = MP4FindTrackId (impl->priv->file, i, NULL, 0);
+		track_type = MP4GetTrackType (impl->priv->file, track_id);
+
+		/* Did we find an audio track ? */
+		if (strcmp (track_type, MP4_AUDIO_TRACK_TYPE) == 0)
+		{
+			int j;
+			guint8 audio_type;
+
+			j = 0;
+			audio_type = MP4GetTrackAudioType (impl->priv->file,
+					track_id);
+			if (audio_type == MP4_MPEG4_AUDIO_TYPE)
+			{
+				impl->priv->track_id = track_id;
+				found = TRUE;
+				break;
+			}
+		}
+	}
+
+	if (found == FALSE)
+	{
+		error = g_error_new (MONKEY_MEDIA_STREAM_INFO_ERROR,
+				     MONKEY_MEDIA_STREAM_INFO_ERROR_OPEN_FAILED,
+				     _("Failed to find an audio track"));
+		g_object_set (G_OBJECT (info), "error", error, NULL);
+		return;
+	}
+}
+
+static int
+MP4_stream_info_impl_get_n_values (MonkeyMediaStreamInfo *info,
+				   MonkeyMediaStreamInfoField field)
+{
+	MP4StreamInfoImpl *impl;
+	char *tmp;
+	gboolean ret = FALSE;
+	
+	g_return_val_if_fail (IS_MP4_STREAM_INFO_IMPL (info), 0);
+
+	impl = MP4_STREAM_INFO_IMPL (info);
+
+	tmp = NULL;
+
+	switch (field)
+	{
+	/* tags */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_TITLE:
+		MP4GetMetadataName (impl->priv->file, &tmp);
+		ret = (tmp != NULL);
+		g_free (tmp);
+		return ret;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ARTIST:
+		MP4GetMetadataArtist (impl->priv->file, &tmp);
+		ret = (tmp != NULL);
+		g_free (tmp);
+		return ret;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ALBUM:
+		MP4GetMetadataAlbum (impl->priv->file, &tmp);
+		ret = (tmp != NULL);
+		g_free (tmp);
+		return ret;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_DATE:
+		MP4GetMetadataYear (impl->priv->file, &tmp);
+		ret = (tmp != NULL);
+		g_free (tmp);
+		return ret;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_GENRE:
+		MP4GetMetadataGenre (impl->priv->file, &tmp);
+		ret = (tmp != NULL);
+		g_free (tmp);
+		return ret;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_COMMENT:
+		MP4GetMetadataComment (impl->priv->file, &tmp);
+		ret = (tmp != NULL);
+		g_free (tmp);
+		return ret;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_TRACK_NUMBER:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_MAX_TRACK_NUMBER:
+		{
+			guint16 track, total_tracks;
+
+			return MP4GetMetadataTrack (impl->priv->file, &track,
+						    &total_tracks);
+		}
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_LOCATION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_DESCRIPTION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_VERSION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ISRC:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ORGANIZATION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_COPYRIGHT:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_CONTACT:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_LICENSE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_PERFORMER:
+		return 0;
+
+	/* generic bits */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_FILE_SIZE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_DURATION:
+		return 1;
+
+	/* audio bits */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_AUDIO:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CODEC_INFO:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_BIT_RATE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_AVERAGE_BIT_RATE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VARIABLE_BIT_RATE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_QUALITY:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SAMPLE_RATE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CHANNELS:
+		return 1;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SERIAL_NUMBER:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VENDOR:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_GAIN:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_GAIN:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_PEAK:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_PEAK:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRM_ID:
+		return 0;
+
+	/* video bits */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_VIDEO:
+		return 1;
+
+	/* default */
+	default:
+		return 0;
+	}
+}
+
+static gboolean
+MP4_stream_info_impl_get_value (MonkeyMediaStreamInfo *info,
+			        MonkeyMediaStreamInfoField field,
+				int index,
+				GValue *value)
+{
+	MP4StreamInfoImpl *impl;
+	char *tmp;
+	
+	g_return_val_if_fail (IS_MP4_STREAM_INFO_IMPL (info), FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	impl = MP4_STREAM_INFO_IMPL (info);
+	
+	if (MP4_stream_info_impl_get_n_values (info, field) <= 0)
+		return FALSE;
+
+	tmp = NULL;
+
+	switch (field)
+	{
+	/* tags */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_TITLE:
+		g_value_init (value, G_TYPE_STRING);
+		MP4GetMetadataName (impl->priv->file, &tmp);
+		g_value_set_string (value, tmp);
+		g_free (tmp);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ARTIST:
+		g_value_init (value, G_TYPE_STRING);
+		MP4GetMetadataArtist (impl->priv->file, &tmp);
+		g_value_set_string (value, tmp);
+		g_free (tmp);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ALBUM:
+		g_value_init (value, G_TYPE_STRING);
+		MP4GetMetadataAlbum (impl->priv->file, &tmp);
+		g_value_set_string (value, tmp);
+		g_free (tmp);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_DATE:
+		g_value_init (value, G_TYPE_STRING);
+		MP4GetMetadataYear (impl->priv->file, &tmp);
+		g_value_set_string (value, tmp);
+		g_free (tmp);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_GENRE:
+		g_value_init (value, G_TYPE_STRING);
+		MP4GetMetadataGenre (impl->priv->file, &tmp);
+		g_value_set_string (value, tmp);
+		g_free (tmp);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_COMMENT:
+		g_value_init (value, G_TYPE_STRING);
+		MP4GetMetadataComment (impl->priv->file, &tmp);
+		g_value_set_string (value, tmp);
+		g_free (tmp);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_TRACK_NUMBER:
+		{
+			guint16 track, total_tracks;
+
+			g_value_init (value, G_TYPE_INT);
+
+			MP4GetMetadataTrack (impl->priv->file, &track,
+					     &total_tracks);
+			g_value_set_int (value, track);
+		}
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_MAX_TRACK_NUMBER:
+		{
+			guint16 track, total_tracks;
+
+			g_value_init (value, G_TYPE_INT);
+
+			MP4GetMetadataTrack (impl->priv->file, &track,
+					     &total_tracks);
+			g_value_set_int (value, total_tracks);
+		}
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_LOCATION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_DESCRIPTION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_VERSION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ISRC:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_ORGANIZATION:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_COPYRIGHT:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_CONTACT:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_LICENSE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_PERFORMER:
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, "");
+		break;
+
+	/* generic bits */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_FILE_SIZE:
+		{
+			GnomeVFSFileInfo *i;
+			GnomeVFSResult res;
+			char *uri;
+
+			g_object_get (G_OBJECT (info), "location", &uri, NULL);
+
+			g_value_init (value, G_TYPE_LONG);
+			
+			i = gnome_vfs_file_info_new ();
+			res = gnome_vfs_get_file_info (uri, i,
+						       GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
+			if (res == GNOME_VFS_OK)
+				g_value_set_long (value, i->size);
+			else
+				g_value_set_long (value, 0);
+
+			gnome_vfs_file_info_unref (i);
+		}
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_DURATION:
+		g_value_init (value, G_TYPE_LONG);
+		g_value_set_long (value, MP4ConvertFromTrackDuration
+				  (impl->priv->file, impl->priv->track_id,
+				   MP4GetTrackDuration (impl->priv->file,
+						        impl->priv->track_id),
+				   MP4_MSECS_TIME_SCALE) / 1000);
+		break;
+
+	/* audio bits */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_AUDIO:
+		g_value_init (value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (value, TRUE);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CODEC_INFO:
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, _("MPEG-4 audio (MPEG-4 AAC)"));
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_BIT_RATE:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_AVERAGE_BIT_RATE:
+		g_value_init (value, G_TYPE_INT);
+		g_value_set_int (value, MP4GetTrackBitRate (impl->priv->file,
+							    impl->priv->track_id) / 1000);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_QUALITY:
+		g_value_init (value, MONKEY_MEDIA_TYPE_AUDIO_QUALITY);
+		g_value_set_enum (value, monkey_media_audio_quality_from_bit_rate (MP4GetTrackBitRate (impl->priv->file, impl->priv->track_id)));
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRM_ID:
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, NULL);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VARIABLE_BIT_RATE:
+		g_value_init (value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (value, (MP4GetTrackFixedSampleDuration
+				(impl->priv->file, impl->priv->track_id) != MP4_INVALID_DURATION));
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SAMPLE_RATE:
+		/* FIXME we're lying, we can't possibly use the decoder here */
+		g_value_init (value, G_TYPE_LONG);
+		g_value_set_long (value, 44100);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CHANNELS:
+		/* Lying again */
+		g_value_init (value, G_TYPE_INT);
+		g_value_set_int (value, 2);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SERIAL_NUMBER:
+		g_value_init (value, G_TYPE_LONG);
+		g_value_set_long (value, 0);
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VENDOR:
+		g_value_init (value, G_TYPE_STRING);
+		g_value_set_string (value, "");
+		break;
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_GAIN:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_GAIN:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_PEAK:
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_PEAK:
+		g_value_init (value, G_TYPE_DOUBLE);
+		g_value_set_double (value, 0.0);
+		break;
+
+	/* video bits */
+	case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_VIDEO:
+		g_value_init (value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (value, FALSE);
+		break;
+
+	/* default */
+	default:
+		g_warning ("Invalid field!");
+		g_value_init (value, G_TYPE_NONE);
+		break;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+MP4_stream_info_impl_set_value (MonkeyMediaStreamInfo *info,
+				MonkeyMediaStreamInfoField field,
+				int index,
+				const GValue *value)
+{
+	/* FIXME */
+	return FALSE;
+}
+
Index: monkey-media/stream-info-impl/mp4-stream-info-impl.h
===================================================================
RCS file: monkey-media/stream-info-impl/mp4-stream-info-impl.h
diff -N monkey-media/stream-info-impl/mp4-stream-info-impl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ monkey-media/stream-info-impl/mp4-stream-info-impl.h	17 Nov 2003 22:03:27 -0000
@@ -0,0 +1,57 @@
+/*  monkey-sound
+ *
+ *  arch-tag: Header for MP4 metadata loading
+ *
+ *  Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
+ *
+ *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __MP4_STREAM_INFO_IMPL_H
+#define __MP4_STREAM_INFO_IMPL_H
+
+#include <glib-object.h>
+
+#include "monkey-media-stream-info.h"
+
+G_BEGIN_DECLS
+
+#define TYPE_MP4_STREAM_INFO_IMPL         (MP4_stream_info_impl_get_type ())
+#define MP4_STREAM_INFO_IMPL(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_MP4_STREAM_INFO_IMPL, MP4StreamInfoImpl))
+#define MP4_STREAM_INFO_IMPL_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TYPE_MP4_STREAM_INFO_IMPL, MP4StreamInfoImplClass))
+#define IS_MP4_STREAM_INFO_IMPL(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_MP4_STREAM_INFO_IMPL))
+#define IS_MP4_STREAM_INFO_IMPL_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_MP4_STREAM_INFO_IMPL))
+#define MP4_STREAM_INFO_IMPL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_MP4_STREAM_INFO_IMPL, MP4StreamInfoImplClass))
+
+typedef struct MP4StreamInfoImplPrivate MP4StreamInfoImplPrivate;
+
+typedef struct
+{
+	MonkeyMediaStreamInfo parent;
+
+	MP4StreamInfoImplPrivate *priv;
+} MP4StreamInfoImpl;
+
+typedef struct
+{
+	MonkeyMediaStreamInfoClass parent_class;
+} MP4StreamInfoImplClass;
+
+GType MP4_stream_info_impl_get_type (void);
+
+G_END_DECLS
+
+#endif /* __MP4_STREAM_INFO_IMPL_H */
Index: shell/rb-shell.c
===================================================================
RCS file: /cvs/gnome/rhythmbox/shell/rb-shell.c,v
retrieving revision 1.218
diff -u -r1.218 rb-shell.c
--- shell/rb-shell.c	15 Nov 2003 05:49:19 -0000	1.218
+++ shell/rb-shell.c	17 Nov 2003 22:03:31 -0000
@@ -1599,7 +1599,7 @@
 #ifdef HAVE_GSTREAMER
 		backend = "GStreamer";
 #else
-		backend = "Xine";
+		backend = "xine-lib";
 #endif		
 #ifdef HAVE_MP3
 		g_string_append (formats, "MP3 ");
@@ -1610,7 +1610,7 @@
 #ifdef HAVE_FLAC
 		g_string_append (formats, "FLAC ");
 #endif
-		
+
 		comment = g_strdup_printf (_("Music management and playback software for GNOME.\nAudio backend: %s\nAudio formats: %s\n"), backend, formats->str);
 
 		g_string_free (formats, TRUE);


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