[patch] new cdda module



Greetings, everyone.
Beeing rather unhappy with the current cdda module (and I have the
feeling I'm not alone with this) I wrote a complete replacement. This
one is gstreamer-based (is this a problem, concerning dependencies?) and
has the following features:

- extracts not only wave, but also mp3/ogg/flac files (if supported by
your gstreamer installation)
- metadata lookup via musicbrainz
- thread safe, usable with several drives at the same time
- temporary renaming of files

I know there's currently a freeze, so I don't expect it to go into the
next release, but I'd like to have some feedback on it. Is it worth
including, and is the gstreamer dependency a problem? Any comments on
the implementation? (And could someone verify my changes to the
configure.in/Makefile.am files? I'm not very familiar with this).

Bye
Martin



? modules/cdda-data.h
? modules/cdda-utils.c
? modules/cdda-utils.h
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-vfs/configure.in,v
retrieving revision 1.384
diff -u -p -r1.384 configure.in
--- configure.in	25 Jul 2005 21:20:20 -0000	1.384
+++ configure.in	3 Aug 2005 00:20:57 -0000
@@ -73,6 +73,7 @@ GCONF_REQUIRED=1.1.1
 GLIB_REQUIRED=2.6.0
 ORBIT_REQUIRED=2.9.0
 XML_REQUIRED=2.6.0
+GSTREAMER_REQUIRED=0.8
 
 AC_SUBST(BONOBO_ACTIVATION_REQUIRED)
 AC_SUBST(BONOBO_REQUIRED)
@@ -81,6 +82,7 @@ AC_SUBST(GLIB_REQUIRED)
 AC_SUBST(LIBIDL_REQUIRED)
 AC_SUBST(ORBIT_REQUIRED)
 AC_SUBST(XML_REQUIRED)
+AC_SUBST(GSTREAMER_REQUIRED)
 
 PKG_CHECK_MODULES(MODULES_XML, glib-2.0 >= $GLIB_REQUIRED
gmodule-no-export-2.0 >= $GLIB_REQUIRED gthread-2.0 >= $GLIB_REQUIRED
libxml-2.0 >= $XML_REQUIRED)
 AC_SUBST(MODULES_XML_CFLAGS)
@@ -110,6 +112,14 @@ PKG_CHECK_MODULES(TEST, bonobo-activatio
 AC_SUBST(TEST_LIBS)
 AC_SUBST(TEST_CFLAGS)
 
+PKG_CHECK_MODULES(MODULES_GST, glib-2.0 >= $GLIB_REQUIRED gmodule-2.0
>= $GLIB_REQUIRED gthread-2.0 >= $GLIB_REQUIRED gstreamer-0.8 >=
$GSTREAMER_REQUIRED)
+AC_SUBST(MODULES_GST_CFLAGS)
+AC_SUBST(MODULES_GST_LIBS)
+
+PKG_CHECK_MODULES(MODULES_MB, libmusicbrainz >= 2.0.0)
+AC_SUBST(MODULES_MB_CFLAGS)
+AC_SUBST(MODULES_MB_LIBS)
+
 ORBIT_IDL="`$PKG_CONFIG --variable=orbit_idl ORBit-2.0`"
 AC_SUBST(ORBIT_IDL)
 
Index: modules/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/Makefile.am,v
retrieving revision 1.112
diff -u -p -r1.112 Makefile.am
--- modules/Makefile.am	14 Apr 2005 18:48:29 -0000	1.112
+++ modules/Makefile.am	3 Aug 2005 00:21:01 -0000
@@ -6,6 +6,8 @@ INCLUDES =					\
 	-I$(top_srcdir)/imported/neon		\
 	$(MODULES_XML_GCONF_CFLAGS)		\
 	$(MODULES_FILE_CFLAGS) 			\
+	$(MODULES_GST_CFLAGS) 			\
+	$(MODULES_MB_CLFLAGS)			\
 	$(HOWL_CFLAGS)				\
 	$(LIBEFS_CFLAGS)			\
 	$(SAMBA_CFLAGS)				\
@@ -86,12 +88,12 @@ modulesconf_DATA = default-modules.conf 
 
 libcdda_la_SOURCES = \
 	cdda-method.c 				\
-	cdda-cddb.c 				\
-	cdda-cddb.h				\
-	cdda-cdrom-extensions.h
+	cdda-utils.c 				\
+	cdda-utils.h				\
+	cdda-data.h
 
 libcdda_la_LDFLAGS = $(module_flags)
-libcdda_la_LIBADD = $(MODULES_LIBS)
$(CDDA_LIBS) ../libgnomevfs/libgnomevfs-2.la
+libcdda_la_LIBADD = $(MODULES_LIBS) $(MODULES_GST_LIBS)
$(MODULES_MB_LIBS) ../libgnomevfs/libgnomevfs-2.la
 
 ###  `computer' method
 
Index: modules/cdda-method.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/cdda-method.c,v
retrieving revision 1.24
diff -u -p -r1.24 cdda-method.c
--- modules/cdda-method.c	8 May 2005 13:40:13 -0000	1.24
+++ modules/cdda-method.c	3 Aug 2005 00:21:03 -0000
@@ -2,7 +2,7 @@
 
 /* cdda-method.c
 
-   Copyright (C) 2000, Eazel Inc.
+   Copyright (C) 2005, Martin Schoen
 
    The Gnome Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License
as
@@ -18,881 +18,379 @@
    License along with the Gnome Library; see the file COPYING.LIB.  If
not,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite
330,
    Boston, MA 02111-1307, USA.
-
-   Author: Gene Z. Ragan <gzr eazel com> 
 */
 
 #include <config.h>
 
-#include "cdda-cddb.h"
-#include <errno.h>
-#include <gconf/gconf-client.h>
-#include <gconf/gconf.h>
-#include <libgnomevfs/gnome-vfs-cancellation.h>
-#include <libgnomevfs/gnome-vfs-context.h>
 #include <libgnomevfs/gnome-vfs-method.h>
-#include <libgnomevfs/gnome-vfs-mime.h>
 #include <libgnomevfs/gnome-vfs-module-shared.h>
 #include <libgnomevfs/gnome-vfs-module.h>
-#include <libgnomevfs/gnome-vfs-utils.h>
-#include <pwd.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <cdda_paranoia.h>
-
-typedef struct {
-	GnomeVFSURI *uri;
-	GnomeVFSFileInfo *file_info;
-	cdrom_drive *drive;	
-	int access_count;
-	unsigned int cddb_discid;
-	gboolean use_cddb;
-	DiscData disc_data;
-} CDDAContext;
-
-typedef struct {
-	GnomeVFSURI *uri;
-	gboolean inited;
-	gboolean wrote_header;
-	cdrom_paranoia *paranoia;
-	long cursor;
-	long first_sector, last_sector;
-} ReadHandle;
-
-CDDAContext *global_context = NULL;
-
-/* This is here to work around a broken header file.
- * cdda_interface.h has a statically defined array of
- * chars that is unused. This will break our build
- * due to our strict error checking.
- */
-char **broken_header_fix = strerror_tr;
+#include <musicbrainz/queries.h>
+#include "cdda-utils.h"
 
-static GnomeVFSResult do_open	         	(GnomeVFSMethod
*method,
-						 GnomeVFSMethodHandle         	**method_handle,
-						 GnomeVFSURI                   	*uri,
-					  	 GnomeVFSOpenMode               mode,
-					  	 GnomeVFSContext               	*context);
-static gboolean       do_is_local        	(GnomeVFSMethod
*method,
-					  	 const GnomeVFSURI             	*uri);
-static GnomeVFSResult do_open_directory  	(GnomeVFSMethod
*method,
-					  	 GnomeVFSMethodHandle         	**method_handle,
-					  	 GnomeVFSURI                   	*uri,
-					  	 GnomeVFSFileInfoOptions        options,
-					  	 GnomeVFSContext               	*context);
-static GnomeVFSResult do_close_directory 	(GnomeVFSMethod
*method,
-					  	 GnomeVFSMethodHandle          	*method_handle,
-					  	 GnomeVFSContext               	*context);
-static GnomeVFSResult do_read_directory  	(GnomeVFSMethod
*method,
-                          			 GnomeVFSMethodHandle
*method_handle,
-                          			 GnomeVFSFileInfo
*file_info,
-                          			 GnomeVFSContext               	*context);
-static int		get_data_size 		(cdrom_drive 			*drive, 
-						 int 				track);
-static gboolean	is_file_is_on_disc 		(CDDAContext 			*context, 
-						 const GnomeVFSURI 		*uri);
-static int 		write_wav_header 	(gpointer 			buffer, 
-						 long 				bytes);
-
-
-static const char PROXY_HOST_KEY[] = "/system/http_proxy/host";
-static const char PROXY_PORT_KEY[] = "/system/http_proxy/port";
-static const char USE_PROXY_KEY[] =
"/system/http_proxy/use_http_proxy";
-
-static CDDAContext *
-cdda_context_new (cdrom_drive *drive, GnomeVFSURI *uri)
-{
-	CDDAContext *context;
-	GConfClient *gconf_client;
-	char *proxy_host;
-	gboolean use_proxy;
-	ProxyServer proxy_server;
-	CDDBServer cddb_server;
-				
-	context = g_new0 (CDDAContext, 1);
-	context->drive = drive;
-	context->file_info = gnome_vfs_file_info_new ();
-	context->uri = gnome_vfs_uri_ref (uri);
-	context->access_count = 0;
-	context->cddb_discid = CDDBDiscid (drive);
+gboolean gst_supports_mp3, gst_supports_ogg, gst_supports_flac;
+GList *disclist;
 
-	/* Look up CDDB info */
-	gconf_client = gconf_client_get_default ();
-		
-	use_proxy = gconf_client_get_bool (gconf_client, USE_PROXY_KEY, NULL);
-	if (use_proxy) {
-		proxy_host = gconf_client_get_string (gconf_client, PROXY_HOST_KEY,
NULL);
-
-		proxy_server.port = gconf_client_get_int (gconf_client,
PROXY_PORT_KEY, NULL);
-
-		if (proxy_host != NULL) {	
-			strcpy (proxy_server.name, proxy_host);
-			g_free (proxy_host);
-		} else {
-			use_proxy = FALSE;
-		}
+static GnomeVFSResult
+do_open (GnomeVFSMethod *method, 
+			GnomeVFSMethodHandle **method_handle,
+			GnomeVFSURI *uri, 
+			GnomeVFSOpenMode mode, 
+			GnomeVFSContext *context) {
+	FileHandle *handle;
+	GstPad *src;
+	GstEvent *event;
+	gchar *tmp;
 
-		if (proxy_server.port == 0) {
-			proxy_server.port = 8080;
-		}
+	if (mode != GNOME_VFS_OPEN_READ) {
+		return GNOME_VFS_ERROR_NOT_SUPPORTED;
 	}
-
-	strcpy (cddb_server.name, "freedb.freedb.org");
-	strcpy (cddb_server.cgi_prog, "~cddb/cddb.cgi");
-	cddb_server.port = 80;
-	cddb_server.use_proxy = use_proxy;
-	cddb_server.proxy = &proxy_server;
-
-	context->use_cddb = CDDBLookupDisc (&cddb_server, drive,
&context->disc_data);
-
-	return context;
-}
-
-static void
-cdda_context_free (CDDAContext *context)
-{
-	if (context == NULL) {
-		return;
+	
+	handle = g_new0 (FileHandle, 1);
+	if ((handle->cdda = get_cdda_from_uri (uri)) == NULL) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_NOT_FOUND;
 	}
-
-	cdda_close (context->drive);
-	gnome_vfs_file_info_unref (context->file_info);
-	gnome_vfs_uri_unref (context->uri);
 	
-	g_free (context);
-	context = NULL;
-}
-
-static void
-cdda_set_file_info_for_root (CDDAContext *context, GnomeVFSURI *uri)
-{
-	g_assert (context);
-
-	/* We don't know the io_block size */
-	context->file_info->io_block_size = 0;
-	context->file_info->valid_fields -=
GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;		
-	context->file_info->name = gnome_vfs_uri_extract_short_path_name
(uri);
-	/*context->file_info->name = g_strdup
(context->disc_data.data_title);*/
-	context->file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
-	context->file_info->mime_type = g_strdup ("x-directory/normal");
-	context->file_info->atime = time (NULL);
-	context->file_info->ctime = time (NULL);
-	context->file_info->mtime = time (NULL);
-	context->file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_TYPE |
-										GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
-										GNOME_VFS_FILE_INFO_FIELDS_ATIME | 
-										GNOME_VFS_FILE_INFO_FIELDS_MTIME |
-										GNOME_VFS_FILE_INFO_FIELDS_CTIME;
-};
-
-static ReadHandle *
-read_handle_new (GnomeVFSURI *uri)
-{
-	ReadHandle *result;
-	result = g_new (ReadHandle, 1);
-
-	result->uri = gnome_vfs_uri_ref (uri);
-	result->inited = FALSE;
-	result->wrote_header = FALSE;
-	result->paranoia = NULL;
-	result->cursor = 0;
-	result->first_sector = 0;
-	result->last_sector = 0;
+	/* lock the cdda structure and therefore the disc, so that only one
thread can extract data at a given time */
+	g_mutex_lock (handle->cdda->mutex);
 	
-	return result;
-}
-
-static void
-read_handle_destroy (ReadHandle *handle)
-{
-	gnome_vfs_uri_unref (handle->uri);
-
-	if (handle->paranoia == NULL) {
-		paranoia_free (handle->paranoia);
+	handle->uri = gnome_vfs_uri_dup (uri);
+	if ((handle->tracknumber = get_tracknumber_from_uri (handle->uri)) ==
0) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_NOT_FOUND;
 	}
 	
-	g_free (handle);
-}
-
-static int
-get_track_index_from_uri (CDDAContext *context, GnomeVFSURI *uri) {
-	char *base_name;
-	int index;
-	char *escaped_name;
-	
-	base_name = gnome_vfs_uri_extract_short_path_name (uri);
-	escaped_name = gnome_vfs_unescape_string_for_display (base_name);
-	g_free (base_name);
-
-	/* Check and see if filename is in cddb data list */
-	for (index = 0; index < context->drive->tracks; index++) {
-		if (strcmp (escaped_name,
context->disc_data.data_track[index].track_name) == 0) {
-			g_free (escaped_name);
-			return index + 1;
-		}
+	/* create the necessary pipeline */
+	if ((tmp = g_strrstr (gnome_vfs_uri_extract_short_name (uri), ".")) ==
NULL) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_NOT_FOUND;
 	}
-
-	g_free (escaped_name);
-	return -1;
-}
-
-static GnomeVFSResult 
-do_open (GnomeVFSMethod *method, GnomeVFSMethodHandle **method_handle,
-	 GnomeVFSURI *uri, GnomeVFSOpenMode mode, GnomeVFSContext *context) 
-{
-	GnomeVFSResult result;
-	ReadHandle *read_handle;
-	GnomeVFSFileInfoOptions options;
-	char *base_name;
-	char *dirname, *schemedir, *sep;
-	GnomeVFSURI *dir_uri;
-	
-	result = GNOME_VFS_ERROR_GENERIC;
-	*method_handle = NULL;
-
-	/*g_message ("cdda do_open: %s", gnome_vfs_uri_get_path (uri));*/
-
-	/* Load in context for disc if we not yet done so. */
-	if (global_context == NULL) {
-		base_name = gnome_vfs_uri_extract_short_path_name (uri);
-		if (base_name[0] == GNOME_VFS_URI_PATH_CHR) {
-			g_free (base_name);
-			return result;
-		} else {
-			g_free (base_name);
-		}
-
-		dirname = gnome_vfs_uri_extract_dirname (uri);			
-		schemedir = g_strdup_printf ("cdda://%s", dirname);
-		
-		/* Remove trailing '/' if there is one */
-		sep = strrchr (schemedir, '/');
-		if (sep != NULL) {
-			schemedir [strlen (schemedir) - 1] = '\0';
-		}
-		
-		dir_uri = gnome_vfs_uri_new (schemedir);
-		options = 0;
-		result = do_open_directory (method, method_handle, dir_uri, options,
NULL);
-		gnome_vfs_uri_unref (dir_uri);
-
-		if (result != GNOME_VFS_OK) {
-			/*g_message ("cdda do_open: Unable to load context");*/
-			return result;
+	
+	if (g_ascii_strcasecmp (tmp, ".wav") == 0) {
+		if ((handle->filter = gst_element_factory_make (WAVE_ENCODER,
"wav_filter")) == NULL) {
+			file_handle_free (handle);
+			return GNOME_VFS_ERROR_GENERIC;
 		}
-	}
-
-	if (mode == GNOME_VFS_OPEN_READ) {
-		/* Make sure file is present */
-		if (is_file_is_on_disc (global_context, uri)) {
-			result = GNOME_VFS_OK;			
-			read_handle = read_handle_new (uri);
-			
-			/* Set up cdparanoia */
-			if (!read_handle->inited) {
-				int track;
-				int paranoia_mode;
-				long offset, sec, off;
-
-				track = get_track_index_from_uri (global_context, uri);
-				if (track == -1) {
-					return GNOME_VFS_ERROR_GENERIC;
-				}
 				
- 				if (!cdda_track_audiop (global_context->drive, track)) {
-    					/*g_message ("Error. Selected track is not an audio
track.");*/
-    					return GNOME_VFS_ERROR_GENERIC;
-  				}
-
-				/* Calculate sector span and offset */
-				sec = cdda_track_firstsector (global_context->drive, track);
-				off = cdda_track_lastsector (global_context->drive, track) - sec +
1;
-								
-				read_handle->first_sector = 0;
-				read_handle->last_sector = off - 1;
-												
-				offset = cdda_track_firstsector (global_context->drive, track);
-				read_handle->first_sector += offset;
-				read_handle->last_sector += offset;
-
-				read_handle->paranoia = paranoia_init (global_context->drive);
-				/*paranoia_mode = PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP;*/
-				paranoia_mode = PARANOIA_MODE_DISABLE;
-  				paranoia_modeset (read_handle->paranoia, paranoia_mode);
-				cdda_verbose_set (global_context->drive,
CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_FORGETIT);
-
-				paranoia_seek (read_handle->paranoia, read_handle->cursor =
read_handle->first_sector, SEEK_SET);
-
-				read_handle->inited = TRUE;
-			}
-
-			*method_handle = (GnomeVFSMethodHandle *) read_handle;
-		}
-	} else if (mode == GNOME_VFS_OPEN_WRITE) {
-		result = GNOME_VFS_ERROR_READ_ONLY;		
+	} else if (gst_supports_mp3 && g_ascii_strcasecmp (tmp, ".mp3") == 0)
{
+		if ((handle->filter = gst_element_factory_make (MP3_ENCODER,
"mp3_filter")) == NULL) {
+			file_handle_free (handle);
+			return GNOME_VFS_ERROR_GENERIC;
+		}
+		/* set to joint stereo, 192kbit/s variable bitrate */
+		gst_element_set (handle->filter, "mode", 1, NULL);
+		gst_element_set (handle->filter, "bitrate", 192, NULL);
+		gst_element_set (handle->filter, "vbr", 4, NULL);
+		
+	} else if (gst_supports_ogg && g_ascii_strcasecmp (tmp, ".ogg") == 0)
{
+		if ((handle->filter = gst_element_factory_make (VORBIS_ENCODER,
"ogg_filter")) == NULL) {
+			file_handle_free (handle);
+			return GNOME_VFS_ERROR_GENERIC;
+		}
+		gst_element_set (handle->filter, "quality", 0.5, NULL);
+		
+	} else if (gst_supports_flac && g_ascii_strcasecmp (tmp, ".flac") ==
0) {
+		if ((handle->filter = gst_element_factory_make (FLAC_ENCODER,
"flac_filter")) == NULL) {
+			file_handle_free (handle);
+			return GNOME_VFS_ERROR_GENERIC;
+		}		
 	} else {
-		result = GNOME_VFS_ERROR_INVALID_OPEN_MODE;
+		/* file with an unsupported extension */
+		return GNOME_VFS_ERROR_NOT_SUPPORTED;
 	}
-
-	return result;
-}
-
-static GnomeVFSResult 
-do_close (GnomeVFSMethod *method,
-	  GnomeVFSMethodHandle *method_handle,
-	  GnomeVFSContext *context) 
-{
-	ReadHandle *read_handle;
 	
-	/*g_message ("cdda do_close");*/
-
-	g_return_val_if_fail (method_handle != NULL,
GNOME_VFS_ERROR_INTERNAL);
-
-	read_handle = (ReadHandle *) method_handle;
-	read_handle_destroy (read_handle);
-	
-	return GNOME_VFS_OK;
-}
-
-
-/* We have to pass in a callback to paranoia_read, even though we don't
use it */
-static void 
-paranoia_callback (long inpos, int function) {
-}
-
-static GnomeVFSResult 
-do_read (GnomeVFSMethod *method, 
-	 GnomeVFSMethodHandle *method_handle, 
-	 gpointer buffer,
-	 GnomeVFSFileSize num_bytes, 
-	 GnomeVFSFileSize *bytes_read, 
-	 GnomeVFSContext *context) 
-{
-	ReadHandle *read_handle;
-	gint16 *readbuf;
-	g_return_val_if_fail (method_handle != NULL,
GNOME_VFS_ERROR_INTERNAL);
-
-	if (gnome_vfs_context_check_cancellation (context)) {
-		return GNOME_VFS_ERROR_CANCELLED;
-	}
-
-	read_handle = (ReadHandle *) method_handle;
-	if (read_handle == NULL) {
-		return GNOME_VFS_ERROR_INTERNAL;
-	}
-
-	readbuf = NULL;
-
-	if (!read_handle->wrote_header) {		
-		*bytes_read = write_wav_header (buffer, (read_handle->last_sector -
read_handle->first_sector + 1) 
-										* CD_FRAMESIZE_RAW);
-		read_handle->wrote_header = TRUE;
-		return GNOME_VFS_OK;
-	}
-
-		
-	if (read_handle->cursor <= read_handle->last_sector) {
-		readbuf = paranoia_read (read_handle->paranoia, paranoia_callback);
-	} else {
-		return GNOME_VFS_ERROR_EOF;
-		
-	}
-
-	if (readbuf == NULL) {
-		*bytes_read = 0;
+	handle->source = gst_element_factory_make ("cdparanoia",   "source");
+	if ((handle->source = gst_element_factory_make ("cdparanoia",
"source")) == NULL) {
+		file_handle_free (handle);
 		return GNOME_VFS_ERROR_GENERIC;
 	}
-
-	read_handle->cursor++;	
-
-	memcpy (buffer, readbuf, CD_FRAMESIZE_RAW);	
-	*bytes_read = CD_FRAMESIZE_RAW;
-	       
-	return GNOME_VFS_OK;
-}
-
-#if 0
-static void 
-display_toc (cdrom_drive *d)
-{
-	long audiolen = 0;
-  	int i;
-
-  	printf ("\nTable of contents (audio tracks only):\n"
-	 "track        length               begin        copy pre ch\n"
-	 "===========================================================\n");
-  
-	for (i = 1; i <= d->tracks; i++) {	
-		if (cdda_track_audiop (d, i)) {
-      		char buffer[256];
-
-      		long sec = cdda_track_firstsector (d, i);
-      		long off = cdda_track_lastsector (d, i) - sec + 1;
-      
-      		sprintf(buffer,
-	      		"%3d.  %7ld [%02d:%02d.%02d]  %7ld [%02d:%02d.%02d]  %s %s %
s",
-	      		i,
-	      		off,(int)(off/(60*75)),(int)((off/75)%60),(int)(off%75),
-	      		sec,(int)(sec/(60*75)),(int)((sec/75)%60),(int)(sec%75),
-	      		cdda_track_copyp (d,i)?"  OK":"  no",
-	      		cdda_track_preemp (d,i)?" yes":"  no",
-	      		cdda_track_channels (d,i)==2?" 2":" 4");
-      			printf ("%s\n", buffer);
-      			audiolen+=off;
-		}
+	gst_element_set (handle->source, "device", handle->cdda->drive, NULL);
+	gst_element_set (handle->source, "paranoia-mode", 4, NULL);
+	
+	if ((handle->sink = gst_element_factory_make ("fakesink",   "sink"))
== NULL) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_GENERIC;
 	}
+	gst_element_set (handle->sink, "signal-handoffs", TRUE, NULL);
 	
-	{
-		char buffer[256];
-		sprintf (buffer, "TOTAL %7ld [%02d:%02d.%02d]    (audio only)",
-	    		 audiolen, (int)(audiolen / (60 * 75)),(int)((audiolen / 75) %
60),
-	    		 (int)(audiolen % 75));
-      	printf ("%s\n", buffer);
-  	}
-
-  	printf ("\n");
-}
-#endif
-
-static cdrom_drive *
-open_cdda_device (GnomeVFSURI *uri)
-{
-	const char *device_name;
-	cdrom_drive *drive;
+	if ((handle->thread = gst_thread_new ("thread")) == NULL) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_GENERIC;
+	}
 	
-	device_name = gnome_vfs_uri_get_path (uri);
-
-	drive = cdda_identify (device_name, FALSE, NULL);
-	if (drive == NULL) {
-		return NULL;
-	} 
-
-	/* Turn off verbosity */
-	cdda_verbose_set (drive, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_FORGETIT);
-
-	/* Open drive */
-	switch (cdda_open (drive)) {
-  		case -2:
-  		case -3:
-  		case -4:
-  		case -5:
-    		g_message ("Unable to open disc.  Is there an audio CD in the
drive?");
-    		return NULL;
-
-  		case -6:
-    		g_message ("CDDA method could not find a way to read audio from
this drive.");
-    		return NULL;
-    			
-  		case 0:
-    		break;
-
-  		default:
-    		g_message ("Unable to open disc.");
-    		return NULL;
+	gst_bin_add_many (GST_BIN (handle->thread), handle->source,
handle->filter, handle->sink, NULL);
+	if (!gst_element_link_many (handle->source, handle->filter,
handle->sink, NULL)) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_GENERIC;
 	}
-
-	return drive;
-}
-
-static gboolean
-is_file_is_on_disc (CDDAContext *context, const GnomeVFSURI *uri)
-{
-	int index;
-	char *base_name;
-	char *escaped_name;
 	
-	if (context == NULL) {
-		return FALSE;
+	handle->queue = g_async_queue_new ();
+	g_signal_connect (handle->sink, "handoff", G_CALLBACK (cb_handoff),
handle->queue);
+	g_signal_connect (handle->thread, "eos", G_CALLBACK (cb_eos),
handle->queue);
+	
+	gst_element_set_state (handle->thread, GST_STATE_PAUSED);
+	
+	/* seek to track */
+	src = gst_element_get_pad (handle->source, "src");
+	event = gst_event_new_segment_seek (gst_format_get_by_nick ("track") |
GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, (gint64)
(handle->tracknumber-1), (gint64) handle->tracknumber);
+	if (!gst_pad_send_event (src, event)) {
+		file_handle_free (handle);
+		return GNOME_VFS_ERROR_GENERIC;
 	}
-
-	base_name = gnome_vfs_uri_extract_short_path_name (uri);
-	escaped_name = gnome_vfs_unescape_string_for_display (base_name);
-	g_free (base_name);
-
-	for (index = 0; index < context->drive->tracks; index++) {
-		if (strcmp (escaped_name,
context->disc_data.data_track[index].track_name) == 0) {
-			g_free (escaped_name);
-			return TRUE;
+	
+	/* add tag information */
+	if (GST_IS_TAG_SETTER (handle->filter)) {
+		gst_tag_setter_add (GST_TAG_SETTER (handle->filter), 
+							GST_TAG_MERGE_REPLACE, 
+							GST_TAG_TITLE,
handle->cdda->disc.track[handle->tracknumber-1].name, 
+							GST_TAG_ARTIST,
handle->cdda->disc.track[handle->tracknumber-1].artist, 
+							GST_TAG_ALBUM, handle->cdda->disc.title, 
+							/* GST_TAG_GENRE, cdda->disc.genre, */
+							GST_TAG_DURATION,
(handle->cdda->disc.track[handle->tracknumber-1].size /
BYTES_PER_SECOND) * 1000000000, 
+							GST_TAG_TRACK_NUMBER, handle->tracknumber, 
+							GST_TAG_TRACK_COUNT, handle->cdda->disc.tracks, 
+							NULL);
+		if (handle->cdda->disc.year > 0) {
+			gst_tag_setter_add (GST_TAG_SETTER (handle->filter), 
+							GST_TAG_MERGE_REPLACE, 
+							GST_TAG_DATE, handle->cdda->disc.year, 
+							NULL);
 		}
 	}
-
-	g_free (escaped_name);
-	return FALSE;
-}
-
-static GnomeVFSResult
-get_file_info_for_basename (CDDAContext *context, const char
*base_name)
-{
-	int index;
-
-	g_assert (context);
 	
-	if (!context->use_cddb) {
-		return GNOME_VFS_ERROR_GENERIC;
-	}
+	/* start encoding and fill the buffers in a separate thread, so we
don't have to iterate manually */
+	gst_element_set_state (handle->thread, GST_STATE_PLAYING);
 	
-	/* Check and see if filename is in cddb data list */
-	for (index = 0; index < context->drive->tracks; index++) {
-		if (strcmp (base_name,
context->disc_data.data_track[index].track_name) == 0) {
-			/* Populate file info structure */
-			context->file_info->io_block_size = CD_FRAMESIZE_RAW;			
-			context->file_info->name = g_strdup (base_name);
-			context->file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
-			context->file_info->mime_type = g_strdup ("audio/x-wav");
-			context->file_info->atime = time (NULL);
-			context->file_info->ctime = time (NULL);
-			context->file_info->mtime = time (NULL);
-			context->file_info->size = get_data_size (context->drive, index +
1);
-			context->file_info->valid_fields  = GNOME_VFS_FILE_INFO_FIELDS_TYPE
|
-												GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
-												GNOME_VFS_FILE_INFO_FIELDS_SIZE |
-												GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE |
-												GNOME_VFS_FILE_INFO_FIELDS_ATIME | 
-												GNOME_VFS_FILE_INFO_FIELDS_MTIME |
-												GNOME_VFS_FILE_INFO_FIELDS_CTIME;
+	*method_handle = (GnomeVFSMethodHandle *) handle;
+	return GNOME_VFS_OK;
+}
 
-			return GNOME_VFS_OK;
-		}
-	}	
-	return GNOME_VFS_ERROR_GENERIC;
+static GnomeVFSResult 
+do_close (GnomeVFSMethod *method,
+			GnomeVFSMethodHandle *method_handle,
+			GnomeVFSContext *context) {
+	FileHandle *handle;
+	
+	handle = (FileHandle *) method_handle;
+	file_handle_free (handle);
+	return GNOME_VFS_OK;
 }
 
-static GnomeVFSResult
-do_get_file_info (GnomeVFSMethod *method,
-		  GnomeVFSURI *uri,
-		  GnomeVFSFileInfo *file_info,
-		  GnomeVFSFileInfoOptions options,
-		  GnomeVFSContext *context) 
-{		
-	cdrom_drive *drive;
-	char *base_name;
-	gboolean use_base, use_cache;
+static GnomeVFSResult 
+do_read (GnomeVFSMethod *method, 
+	 		GnomeVFSMethodHandle *method_handle, 
+	 		gpointer buffer,
+			GnomeVFSFileSize num_bytes, 
+			GnomeVFSFileSize *bytes_read, 
+			GnomeVFSContext *context) {
 	GnomeVFSResult result;
-	char *escaped_name;
-
-	/*g_message ("do_get_file_info: %s", gnome_vfs_uri_get_path (uri));*/
+	FileHandle *handle;
 	
-	use_base = FALSE;
-	use_cache = FALSE;
-
-	result = GNOME_VFS_OK;
+	handle = (FileHandle *) method_handle;
 	
-	/* Get basename */
-	base_name = gnome_vfs_uri_extract_short_path_name (uri);
-	escaped_name = gnome_vfs_unescape_string_for_display (base_name);
-	g_free (base_name);
-
-	/* Extract path and attempt to open */
-	drive = open_cdda_device (uri);
-	if (drive == NULL) {
-			/* OK. We failed to open. Let's try the parent... */
-			gchar *dirname, *schemedir, *sep;
-			GnomeVFSURI *dir_uri;
-			
-			dirname = gnome_vfs_uri_extract_dirname (uri);			
-			schemedir = g_strdup_printf ("cdda://%s", dirname);
-			
-			/* Remove trailing '/' if there is one  */
-			sep = strrchr (schemedir, '/');
-			if (sep != NULL) {
-				schemedir [strlen (schemedir) - 1] = '\0';
-			}
-			
-			dir_uri = gnome_vfs_uri_new (schemedir);
-			drive = open_cdda_device (dir_uri);
-
-			g_free (dirname);
-			g_free (schemedir);
-			gnome_vfs_uri_unref (dir_uri);
-
-			if (drive == NULL) {
-				g_free (escaped_name);
-				return GNOME_VFS_ERROR_GENERIC;
-			}
-
-			use_base = TRUE;
-	}
-
-	/* Check and see if we already have opened and stashed this drive */
-	if (!use_base) {
-		if (global_context != NULL) {
-#ifdef __linux__
-			if (strcmp (drive->cdda_device_name,
global_context->drive->cdda_device_name) == 0) {
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) ||
defined(__DragonFly__)
-			if (strcmp (drive->dev->device_path,
global_context->drive->dev->device_path) == 0) {
-#endif
-				use_cache = TRUE;
-				cdda_close (drive);
-				gnome_vfs_file_info_copy (file_info, global_context->file_info);
-			} else {
-				/* We have a new drive. */
-				cdda_context_free (global_context);
-				global_context = cdda_context_new (drive, uri);
-				cdda_set_file_info_for_root (global_context, uri);
-				gnome_vfs_file_info_copy (file_info, global_context->file_info);
-			}			
-		} else {
-			/* Create a new context */
-			global_context = cdda_context_new (drive, uri);
-			cdda_set_file_info_for_root (global_context, uri);
-			gnome_vfs_file_info_copy (file_info, global_context->file_info);
-		}
+	handle->buffer = (GstBuffer *) g_async_queue_pop (handle->queue);
+	if (GST_BUFFER_SIZE (handle->buffer) == 0) {
+		result = GNOME_VFS_ERROR_EOF;
 	} else {
-		cdda_context_free (global_context);
-		global_context = cdda_context_new (drive, uri);
-		result = get_file_info_for_basename (global_context, escaped_name);
-		if (result == GNOME_VFS_OK) {
-			gnome_vfs_file_info_copy (file_info, global_context->file_info);
-		} else {
-			cdda_context_free (global_context);
-			global_context = NULL;
-		}
+		*bytes_read = GST_BUFFER_SIZE (handle->buffer);
+		memcpy (buffer, GST_BUFFER_DATA (handle->buffer), *bytes_read);
+		result = GNOME_VFS_OK;
 	}
-
-	g_free (escaped_name);
+	gst_buffer_default_free (handle->buffer);
 	return result;
 }
 
 static GnomeVFSResult 
-do_open_directory (GnomeVFSMethod *method, GnomeVFSMethodHandle
**method_handle,
-		   GnomeVFSURI *uri, GnomeVFSFileInfoOptions options,
-		   GnomeVFSContext *context)
-{
-	cdrom_drive *drive;
-	gboolean use_base, use_cache;
-	char *base_name;
-	char *escaped_name;
-	
-	g_print ("do_open_directory () in uri: %s\n", gnome_vfs_uri_get_path
(uri));
-
-	use_base = FALSE;
-	use_cache = FALSE;
-	
-	/* Get basename */
-	base_name = gnome_vfs_uri_extract_short_path_name (uri);
-	escaped_name = gnome_vfs_unescape_string_for_display (base_name);
-	g_free (base_name);
-
-	/* Make sure we can open URI */
-	drive = open_cdda_device (uri);
-	if (drive == NULL) {								
-			/* OK. We failed to open. Let's try the parent... */
-			gchar *dirname, *schemedir, *sep;
-			GnomeVFSURI *dir_uri;
-
-			dirname = gnome_vfs_uri_extract_dirname (uri);			
-			schemedir = g_strdup_printf ("cdda://%s", dirname);
-			
-			/* Remove trailing '/' if there is one */
-			sep = strrchr (schemedir, '/');
-			if (sep != NULL) {
-				schemedir [strlen (schemedir) - 1] = '\0';
-			}
-			
-			dir_uri = gnome_vfs_uri_new (schemedir);
-			drive = open_cdda_device (dir_uri);
-
-			g_free (dirname);
-			g_free (schemedir);
-			gnome_vfs_uri_unref (dir_uri);
-
-			if (drive == NULL) {
-				g_free (escaped_name);
-				return GNOME_VFS_ERROR_GENERIC;
-			}
-			use_base = TRUE;
-	}
-
-	if (!use_base) {
-		/* Check for cache */
-		if (global_context != NULL) {
-#ifdef __linux__
-				if (strcmp (drive->cdda_device_name,
global_context->drive->cdda_device_name) != 0) {
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) ||
defined(__DragonFly__)
-				if (strcmp (drive->dev->device_path,
global_context->drive->dev->device_path) != 0) {
-#endif
-					/*	Clear old cache */
-					cdda_context_free (global_context);
-					global_context = cdda_context_new (drive, uri);
-					cdda_set_file_info_for_root (global_context, uri);
-				} else {
-					/* g_message ("Using cache"); */
-					cdda_close (drive);
-				}
-		} else {
-			/* Allocate new context */
-			global_context = cdda_context_new (drive, uri);
-			cdda_set_file_info_for_root (global_context, uri);
-		}
-	} else {
-		/* This is a file. Blast cache.*/
-		/* g_message ("Use base: %s", escaped_name); */
-		cdda_context_free (global_context);
-		global_context = NULL;
-		*method_handle = NULL;
-		cdda_close (drive);
-		g_free (escaped_name);
-		return GNOME_VFS_ERROR_GENERIC;
+do_open_directory (GnomeVFSMethod *method, 
+					GnomeVFSMethodHandle **method_handle,
+					GnomeVFSURI *uri, 
+					GnomeVFSFileInfoOptions options,
+					GnomeVFSContext *context) {
+	FileHandle *handle;
+	
+	handle = g_new0 (FileHandle, 1);
+	if ((handle->cdda = get_cdda_from_uri (uri)) == NULL) {
+		g_free (handle);
+		return GNOME_VFS_ERROR_INTERNAL;
 	}
-	
-	*method_handle = (GnomeVFSMethodHandle *) global_context;
-	g_free (escaped_name);
-	
+	handle->uri = gnome_vfs_uri_dup (uri);
+	handle->tracknumber = 0;
+	*method_handle = (GnomeVFSMethodHandle *) handle;
 	return GNOME_VFS_OK;
 }
 
 
 static GnomeVFSResult
 do_close_directory (GnomeVFSMethod *method,
-		    GnomeVFSMethodHandle *method_handle,
-		    GnomeVFSContext *context) 
-{
-	CDDAContext *cdda_context = (CDDAContext *)method_handle;
-
-	/*g_message ("cdda do_close_directory");*/
-
-	if (cdda_context == NULL) {
-		/*g_message ("cdda do_close_directory: NULL cdda context");*/
-		return GNOME_VFS_ERROR_GENERIC;
-	}
+					GnomeVFSMethodHandle *method_handle,
+					GnomeVFSContext *context) {
+	FileHandle *handle;
 	
-	cdda_context->access_count = 0;
-		
+	handle = (FileHandle *) method_handle;
+	gnome_vfs_uri_unref (handle->uri);
+	g_free (handle);
 	return GNOME_VFS_OK;
 }
-
-static int
-get_data_size (cdrom_drive *drive, int track)
-{
-	int minutes, seconds, total_seconds, size;
-
-	size = 0;
-	
-	if (cdda_track_audiop (drive, track)) {
-		long sec = cdda_track_firstsector (drive, track);
-		long off = cdda_track_lastsector (drive, track) - sec + 1;
-
-      		minutes = off / (60 * 75);
-      		seconds = (off / 75) % 60;
-
-		total_seconds = (minutes * 60) + seconds;
-		size = ((total_seconds * 44) * 2 * 2) * 1024;
-	}
-
-	/*g_message ("get_data_size: %d", size);*/
+ 
+static GnomeVFSResult
+do_read_directory (GnomeVFSMethod *method,
+					GnomeVFSMethodHandle *method_handle,
+					GnomeVFSFileInfo *file_info,
+					GnomeVFSContext *context) {
+	FileHandle *handle;
+	gchar *dirname, *name;
+	GnomeVFSResult result;
 	
-	return size;
-}
-
-#if 0
-static int
-get_data_size_from_uri (GnomeVFSURI *uri, CDDAContext *context)
-{
-	int minutes, seconds, total_seconds, size, index;
-	const char *base_name;
+	handle = (FileHandle *) method_handle;
 	
-	size = -1;
+	handle->tracknumber++;
+	dirname = gnome_vfs_uri_extract_short_name (handle->uri);
 	
-	if (context == NULL) {
-		return size;
+	if (handle->tracknumber <= handle->cdda->disc.tracks) {
+		if (g_ascii_strcasecmp (gnome_vfs_uri_get_path(handle->uri),
handle->cdda->drive) == 0) {
+			name = g_strdup_printf ("%.2d - %s.wav", handle->tracknumber,
handle->cdda->disc.track[handle->tracknumber-1].name);
+		} else if (gst_supports_mp3 && g_ascii_strcasecmp (dirname, "MP3") ==
0) {
+			name = g_strdup_printf ("%.2d - %s.mp3", handle->tracknumber,
handle->cdda->disc.track[handle->tracknumber-1].name);
+		} else if (gst_supports_ogg && g_ascii_strcasecmp (dirname, "Ogg
Vorbis") == 0) {
+			name = g_strdup_printf ("%.2d - %s.ogg", handle->tracknumber,
handle->cdda->disc.track[handle->tracknumber-1].name);
+		} else if (gst_supports_flac && g_ascii_strcasecmp (dirname, "Flac")
== 0) {
+			name = g_strdup_printf ("%.2d - %s.flac", handle->tracknumber,
handle->cdda->disc.track[handle->tracknumber-1].name);
+		} else {
+			return GNOME_VFS_ERROR_NOT_FOUND;
+		}
+	/* Tracks+3 because there are 3 folders in the root directory.
Otherwise the last 3 tracks are not shown. 
+	 * This is only valid for the root directory.
+	 */
+	} else if (handle->tracknumber <= handle->cdda->disc.tracks+3) {
+		if (g_ascii_strcasecmp (gnome_vfs_uri_get_path(handle->uri),
handle->cdda->drive) == 0) {
+			switch ((handle->tracknumber)-(handle->cdda->disc.tracks)) {
+				case 1:
+					if (gst_supports_mp3) {
+						name = g_strdup ("MP3");
+						 break;
+					} else {
+						handle->tracknumber++;
+					}
+				case 2:
+					if (gst_supports_ogg) {
+						name = g_strdup ("Ogg Vorbis");
+						 break;
+					} else {
+						handle->tracknumber++;
+					}
+				case 3:
+					if (gst_supports_flac) {
+						name = g_strdup ("Flac");
+					} else {
+						handle->tracknumber++;
+					}
+					break;
+				default:
+					return GNOME_VFS_ERROR_GENERIC;
+			}
+		} else {
+			return GNOME_VFS_ERROR_EOF;
+		}
+	} else {
+		return GNOME_VFS_ERROR_EOF;
 	}
-
-	base_name = gnome_vfs_uri_extract_short_path_name (uri);
 	
-	/* Check and see if filename is in cddb data list */
-	for (index = 0; index < context->drive->tracks; index++) {
-		if (strcmp (base_name,
context->disc_data.data_track[index].track_name) == 0) {	
-			if (cdda_track_audiop (context->drive, index+1)) {
-				long sec = cdda_track_firstsector (context->drive, index+1);
-				long off = cdda_track_lastsector (context->drive, index+1) - sec +
1;
-
-		      	minutes = off / (60 * 75);
-		      	seconds = (off / 75) % 60;
+	g_free (dirname);
 
-				total_seconds = (minutes * 60) + seconds;
-				size = ((total_seconds * 44) * 2 * 2) * 1024;
-			}
-			g_free (base_name);
-			return size;
-		}		
-	}
-	g_free (base_name);
-	return size;
+	return get_file_info (name, handle->tracknumber, handle->cdda,
file_info);
 }
-#endif
- 
-static GnomeVFSResult
-do_read_directory (GnomeVFSMethod *method,
-		   GnomeVFSMethodHandle *method_handle,
-		   GnomeVFSFileInfo *file_info,
-		   GnomeVFSContext *context)
-{
-
-	CDDAContext *cdda_context = (CDDAContext *) method_handle;
 
-	/*g_message ("cdda do_read_directory");*/
-	
-	if (cdda_context == NULL) {
-		g_warning ("do_read_directory: NULL context");
-		return GNOME_VFS_ERROR_GENERIC;
-	}
+static GnomeVFSResult
+do_get_file_info (GnomeVFSMethod *method,
+		 			GnomeVFSURI *uri,
+					GnomeVFSFileInfo *file_info,
+					GnomeVFSFileInfoOptions options,
+					GnomeVFSContext *context) {
+	CDDA *cdda;
+	gchar *name;
+	gushort tracknumber;
+	
+	if ((cdda = get_cdda_from_uri (uri)) == NULL) {
+		if ((cdda = cdda_new (uri)) == NULL) {
+			return GNOME_VFS_ERROR_INTERNAL;
+		}
+	}
+	name = gnome_vfs_uri_extract_short_name (uri);
+	tracknumber = get_tracknumber_from_uri (uri);
+	return get_file_info (name, tracknumber, cdda, file_info);
+}
 
-	if (cdda_context->access_count >= cdda_context->drive->tracks) {
-		/*g_message ("do_read_directory: over access count");*/
-		return GNOME_VFS_ERROR_EOF;
-	}
+static GnomeVFSResult 
+do_get_file_info_from_handle (GnomeVFSMethod *method,
+								GnomeVFSMethodHandle *method_handle,
+								GnomeVFSFileInfo *file_info,
+								GnomeVFSFileInfoOptions options,
+								GnomeVFSContext *context) {
+	FileHandle *handle;
 
-	cdda_context->access_count++;
+	handle = (FileHandle *) method_handle;
+	return do_get_file_info (method, handle->uri, file_info, options,
context);
+}
 
-	/* Populate file info */
-	file_info->io_block_size = CD_FRAMESIZE_RAW;
-	file_info->size = get_data_size (cdda_context->drive,
cdda_context->access_count);		
-	file_info->atime = time (NULL);
-	file_info->ctime = time (NULL);
-	file_info->mtime = time (NULL);
-	if (cdda_context->use_cddb) {
-		file_info->name = g_strdup
(cdda_context->disc_data.data_track[cdda_context->access_count-1].track_name);
+static gboolean       
+do_is_local (GnomeVFSMethod *method, 
+				const GnomeVFSURI *uri) {
+	gchar *dir;
+	
+	dir = gnome_vfs_uri_extract_short_name (uri);
+	if (g_ascii_strcasecmp (dir, "MP3") == 0 || g_ascii_strcasecmp (dir,
"Ogg Vorbis") == 0 || g_ascii_strcasecmp (dir, "Flac") == 0) {
+		/* The compressed files are local, of course, but we pretend they
aren't, so nautilus won't try to thumbnail them. */
+		g_free (dir);
+		return FALSE;
 	} else {
-		file_info->name = g_strdup_printf ("Untitled %d",
cdda_context->access_count);
+		/* Wave-files in the root directory may be thumbnailed. */
+		g_free (dir);
+		return TRUE;
 	}
-	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
-	file_info->mime_type = g_strdup ("audio/x-wav");
-	file_info->valid_fields = 	GNOME_VFS_FILE_INFO_FIELDS_TYPE |
-								GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE | 
-								GNOME_VFS_FILE_INFO_FIELDS_SIZE |
-								GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE |
-								GNOME_VFS_FILE_INFO_FIELDS_ATIME | 
-								GNOME_VFS_FILE_INFO_FIELDS_MTIME |
-	  							GNOME_VFS_FILE_INFO_FIELDS_CTIME;
-
-	return GNOME_VFS_OK;
 }
 
 static GnomeVFSResult
 do_check_same_fs (GnomeVFSMethod *method,
-      GnomeVFSURI *a,
-      GnomeVFSURI *b,
-      gboolean *same_fs_return,
-      GnomeVFSContext *context)
-{
-	*same_fs_return = TRUE;
-
+					GnomeVFSURI *a,
+					GnomeVFSURI *b,
+					gboolean *same_fs_return,
+					GnomeVFSContext *context) {
+	*same_fs_return = FALSE;
 	return GNOME_VFS_OK;
 }
 
-static gboolean       
-do_is_local (GnomeVFSMethod *method, const GnomeVFSURI *uri)
-{
-	return TRUE;
-}
+/* You can rename a file on the cd (not permanent of course, but nice
if you want to give them certain names BEFORE copying).
+ * Be aware that this is track-based, so renaming a wave file in the
root dir will also rename its counterparts in the subdirs. 
+ */
+static GnomeVFSResult 
+do_set_file_info (GnomeVFSMethod *method,
+					GnomeVFSURI *a,
+					const GnomeVFSFileInfo *info,
+					GnomeVFSSetFileInfoMask mask,
+					GnomeVFSContext *context) {
+	CDDA *cdda;
+	gushort tracknumber;
+	gchar *ext;
+
+	if ((cdda = get_cdda_from_uri (a)) == NULL) {
+		return GNOME_VFS_ERROR_INTERNAL;
+	}
 
+	if (mask == GNOME_VFS_SET_FILE_INFO_NAME) {
+		ext = g_strrstr (info->name, ".");
+		tracknumber = get_tracknumber_from_uri (a);
+		g_free (cdda->disc.track[tracknumber-1].name);
+		g_mutex_lock (cdda->mutex);
+		cdda->disc.track[tracknumber-1].name = g_strndup (info->name,
ext-(info->name));
+		g_mutex_unlock (cdda->mutex);
+		return GNOME_VFS_OK;
+	} else {
+		return GNOME_VFS_ERROR_NOT_PERMITTED;
+	}
+}
 
 static GnomeVFSMethod method = {
 	sizeof (GnomeVFSMethod),
@@ -908,136 +406,53 @@ static GnomeVFSMethod method = {
 	do_close_directory,
 	do_read_directory,
 	do_get_file_info,
-	NULL,
+	do_get_file_info_from_handle,
 	do_is_local,
 	NULL, 	/* make directory */
 	NULL, 	/* remove directory */
 	NULL, 	/* rename */
 	NULL, 	/* unlink */
 	do_check_same_fs,
-	NULL, 	/* do_set_file_info */
+	do_set_file_info, 	/* do_set_file_info */
 	NULL, 	/* do_truncate */
 	NULL, 	/* do_find_directory */
-	NULL 	/* do_create_symbolic_link */
+	NULL, 	/* do_create_symbolic_link */
+	NULL,   /* do_monitor_add */
+	NULL,   /* do_monitor_cancel */
+	NULL,   /* do_file_control */
+	NULL    /* do_forget_cache */
 };
 
-#if 0
-static void 
-put_num (long num, int f, int endianness, int bytes)
-{
-	int i;
-	unsigned char c;
-
-	if (!endianness) {
-		i = 0;
-	} else {
-		i = bytes - 1;
-	}
-		
-	while (bytes--){
-		c = (num >> (i << 3)) & 0xff;
-		if (write (f, &c, 1) == -1) {
-			perror ("Could not write to output.");
-			exit (1);
-		}
-
-		if (endianness) {
-			i--;
-		} else {
-			i++;
-		}
-	}
-}
-#endif
-
-
-/* Write WAV header information into memory buffer */
-#if 0
-static int
-write_wav_header (gpointer buffer, long bytes)
-{
-		char *ptr;
-
-		memset (buffer, 0, CD_FRAMESIZE_RAW);
-		
-		ptr = buffer;
-		
-		*ptr = "RIFF"; ptr += 4;
-		*ptr = bytes + 44 - 8; ptr += 4;
-		*ptr = "WAVEfmt "; ptr += 8;
-		*ptr = 16; ptr += 4;
-		*ptr = 1; ptr += 2;
-		*ptr = 2; ptr += 2;
-		*ptr = 44100; ptr += 4;
-		*ptr = 44100 * 2 * 2; ptr += 4;
-		*ptr = 4; ptr += 2;
-		*ptr = 16; ptr += 2;		
-		*ptr = "data"; ptr += 4;
-		*ptr = bytes; ptr += 4;
-
-		return 44;
-}
-#endif
-
-static int 
-write_wav_header (gpointer buffer, long bytes)
-{
-		char *ptr;
-		int var;
-
-		memset (buffer, 0, CD_FRAMESIZE_RAW);
-		
-		ptr = buffer;
-		
-		memcpy (ptr, "RIFF", 4); ptr += 4;
-
-		var = bytes + 44 - 8;
-		memcpy (ptr, &var, 4); ptr += 4;
-		
-		memcpy (ptr, "WAVEfmt ", 8); ptr += 8;
-
-		var = 16;
-		memcpy (ptr, &var, 4); ptr += 4;
-
-		var = 1;
-		memcpy (ptr, &var, 2); ptr += 2;
-		
-		var = 2;
-		memcpy (ptr, &var, 2); ptr += 2;
-
-		var = 44100;
-		memcpy (ptr, &var, 4); ptr += 4;
-
-		var = 44100 * 2 * 2;
-		memcpy (ptr, &var, 4); ptr += 4;
-
-		var = 4;
-		memcpy (ptr, &var, 2); ptr += 2;
-
-		var = 16;
-		memcpy (ptr, &var, 2); ptr += 2;
-		
-		memcpy (ptr, "data", 4); ptr += 4;
-		
-		memcpy (ptr, &bytes, 4); ptr += 4;
-
-		return 44;
-}
-
 GnomeVFSMethod *
 vfs_module_init (const char *method_name, 
-		 const char *args)
-{
+					const char *args) {
 	char *argv[] = { "gnome-vfs-cdda-module", NULL };
 	
 	if (!gconf_is_initialized ()) {
 		gconf_init (1, argv, NULL);
 	}
+	
+	gst_init (NULL, NULL);
+
+	/* check if compressed formats are supported by gstreamer */
+	/* at least wave encoding MUST be supported */
+	if (gst_element_factory_find (WAVE_ENCODER) == NULL) {
+		return NULL;
+	}
+	gst_supports_mp3 = (gst_element_factory_find (MP3_ENCODER) != NULL);
+	gst_supports_ogg = (gst_element_factory_find (VORBIS_ENCODER) !=
NULL);
+	gst_supports_flac = (gst_element_factory_find (FLAC_ENCODER) != NULL);
+	
+#ifdef DEBUG
+	gst_debug_set_active (TRUE);
+	gst_debug_set_default_threshold (GST_LEVEL_DEBUG);
+#endif
 
 	return &method;
 }
 
 void
-vfs_module_shutdown (GnomeVFSMethod *method)
-{
+vfs_module_shutdown (GnomeVFSMethod *method) {
+	g_list_foreach (disclist, &cdda_free, NULL);
+	g_list_free (disclist);
 }




The following additional files will also be required:
cdda-data.h:
----------------
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*-
*/

/* cdda-data.h

   Copyright (C) 2005, Martin Schoen

   The Gnome 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.

   The Gnome Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the Gnome Library; see the file COPYING.LIB.  If
not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite
330,
   Boston, MA 02111-1307, USA.
*/

#include <glib.h> 
#include <libgnomevfs/gnome-vfs-uri.h>
#include <gst/gst.h>

#define PROXY_HOST_KEY "/system/http_proxy/host"
#define PROXY_PORT_KEY "/system/http_proxy/port"
#define USE_PROXY_KEY "/system/http_proxy/use_http_proxy"

#define CD_FRAMESIZE_RAW	2352 /* bytes per frame, raw mode */
#define BYTES_PER_SECOND 	176400 /* (44100 samples per second) * (2
Bytes per sample) * (2 channels) */
#define MB_BUFFER_SIZE 		256

#define WAVE_ENCODER "wavenc"
#define MP3_ENCODER "lame"
#define VORBIS_ENCODER "vorbisenc"
#define FLAC_ENCODER "flacenc"

typedef struct _track_data {
	gchar *name;
	gchar *artist;
	guint64 size;
} TrackData;

typedef struct _disc_data {
	gchar *id;
	gchar *title;
	guint genre;
	guint year;
	guint64 tracks;
	TrackData track[99];
} DiscData;

typedef struct {
	GnomeVFSURI *uri;
	gchar *drive;
	DiscData disc;
	GMutex *mutex;
	GTime last_used;
} CDDA;

typedef struct {
	GnomeVFSURI *uri;
	CDDA *cdda;
	gushort tracknumber;
	GstElement *thread, *source, *filter, *sink;
	GstBuffer *buffer;
	GAsyncQueue *queue;
} FileHandle;


cdda-utils.h:
----------------
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*-
*/

/* cdda-utils.h

   Copyright (C) 2005, Martin Schoen

   The Gnome 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.

   The Gnome Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the Gnome Library; see the file COPYING.LIB.  If
not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite
330,
   Boston, MA 02111-1307, USA.
*/

#include <libgnomevfs/gnome-vfs-file-info.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <musicbrainz/mb_c.h>
#include "cdda-data.h"

void cb_handoff (GstElement *fakesrc, GstBuffer *buffer, GstPad *pad,
gpointer user_data);

void cb_eos (GstElement *thread, gpointer data);

gboolean query_musicbrainz (musicbrainz_t *mb, CDDA *cdda);

CDDA* cdda_new (GnomeVFSURI *uri);

void cdda_free (gpointer data, gpointer user_data);

CDDA* get_cdda_from_uri (GnomeVFSURI *uri);

gushort get_tracknumber_from_uri (GnomeVFSURI *uri);

GnomeVFSResult get_file_info (gchar *name, gushort tracknumber, CDDA
*cdda, GnomeVFSFileInfo *file_info);


cdda-utils.c:
----------------
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*-
*/

/* cdda-utils.c

   Copyright (C) 2005, Martin Schoen

   The Gnome 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.

   The Gnome Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the Gnome Library; see the file COPYING.LIB.  If
not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite
330,
   Boston, MA 02111-1307, USA.
*/

#include <gconf/gconf-client.h>
#include <gconf/gconf.h>
#include "cdda-utils.h"

extern gboolean gst_supports_mp3, gst_supports_ogg, gst_supports_flac;
extern GList *disclist;

void
cb_handoff (GstElement *fakesrc,
	 			GstBuffer *buffer,
	 			GstPad *pad,
	 			gpointer user_data) {
	gint64 size;
	gpointer current;
	GstBuffer *tmp;

	gst_buffer_ref(buffer);
	GAsyncQueue *queue = (GAsyncQueue *) user_data;
	
	g_async_queue_ref (queue);
	/* to make sure do_read gets no more than the expected number of bytes
*/
	size = GST_BUFFER_SIZE (buffer);
	if (size > CD_FRAMESIZE_RAW) {
		current =  GST_BUFFER_DATA (buffer);
		while (size > 0)
		{
			tmp = gst_buffer_new ();
			
			if (size > CD_FRAMESIZE_RAW) {
				tmp->data = g_memdup (current, CD_FRAMESIZE_RAW);
				tmp->size = CD_FRAMESIZE_RAW;
			} else {
				tmp->data = g_memdup (current, size);
				tmp->size = size;
			}
			
			g_async_queue_push (queue, tmp);
			size -= CD_FRAMESIZE_RAW;
			current += CD_FRAMESIZE_RAW;
		}
	} else {
		g_async_queue_push (queue, buffer);
	}
	g_async_queue_unref (queue);
}

/* signals end of stream by sending an empty buffer to the queue */
void
cb_eos (GstElement *thread, 
			gpointer data) {
	GAsyncQueue *queue = (GAsyncQueue *) data;
	g_async_queue_ref (queue);
	g_async_queue_push (queue, gst_buffer_new_and_alloc (0));
	g_async_queue_unref (queue);
}

gboolean
query_musicbrainz (musicbrainz_t *mb, 
						CDDA *cdda) {
	GConfClient *gconf_client;
	char *proxy_host;
	guint proxy_port;
	
	/* check if we need to use a proxy */
	gconf_client = gconf_client_get_default ();
	if (gconf_client_get_bool (gconf_client, USE_PROXY_KEY, NULL)) {
		proxy_host = gconf_client_get_string (gconf_client, PROXY_HOST_KEY,
NULL);
		proxy_port = gconf_client_get_int (gconf_client, PROXY_PORT_KEY,
NULL);
		if (proxy_host != NULL) {	
			if (proxy_port == 0) {
				proxy_port = 8080;
			}
			mb_SetProxy (*mb, proxy_host, proxy_port);
		}
	}
	g_object_unref (gconf_client);

#ifdef DEBUG
	mb_SetDebug (*mb, 1);
#endif

	mb_UseUTF8 (*mb, TRUE);
	mb_SetDevice (*mb, cdda->drive);
	return (mb_Query (*mb, MBQ_GetCDInfo) && mb_GetResultInt(*mb,
MBE_GetNumAlbums) >= 1);
}

void 
file_handle_free (FileHandle *handle) {
	g_mutex_free (handle->cdda->mutex);
	gnome_vfs_uri_unref (handle->uri);
	gst_object_unref (GST_OBJECT (handle->thread));
	gst_object_unref (GST_OBJECT (handle->source));
	gst_object_unref (GST_OBJECT (handle->filter));
	gst_object_unref (GST_OBJECT (handle->sink));
	g_free (handle->buffer);
	g_free (handle->queue);
}

CDDA* 
cdda_new (GnomeVFSURI *uri) {
	CDDA *cdda, *rem;
	musicbrainz_t mb;
	gushort size, index;
	const gchar *current_dir, *tmp;
	
	cdda = g_new0 (CDDA, 1);
	cdda->uri = gnome_vfs_uri_dup (uri);
	cdda->last_used = time (NULL);
	
	/* keep list of cdda structures at an acceptable size */
	size = g_list_length (disclist);
	while (size >= 10) {
		rem = (CDDA *) g_list_nth_data (disclist, 0);
		for (index = 1; index < size; index++) {
			cdda = (CDDA *) g_list_nth_data (disclist, index);
			if (cdda->last_used < rem->last_used) {
				rem = cdda;			
			}
		}
		disclist = g_list_remove (disclist, rem);
	}
	
	cdda = g_new0 (CDDA, 1);
	cdda->uri = gnome_vfs_uri_dup (uri);
	
	/* get cdda device name from uri */
	cdda->drive = g_strdup (gnome_vfs_uri_get_path (cdda->uri));
	while (!g_file_test (cdda->drive, G_FILE_TEST_EXISTS)) {
		current_dir = g_strrstr (cdda->drive, GNOME_VFS_URI_PATH_STR);
		tmp = cdda->drive;
		cdda->drive = g_strndup (tmp, current_dir-tmp);
	}
	
	cdda->mutex = g_mutex_new ();
	
	/* try to get cd info from musicbrainz */
	mb = mb_New ();	
	if (query_musicbrainz (&mb, cdda)) {
		gchar data[MB_BUFFER_SIZE];
		guint duration;
		
		/* FIXME: failure & error checking */
		if (!mb_Select1(mb, MBS_SelectAlbum, 1)) {
			cdda_free (cdda, NULL);
			return NULL;
		}
		if (!mb_GetResultData (mb, MBE_AlbumGetAlbumName, data,
MB_BUFFER_SIZE)) {
			cdda->disc.title = g_strdup (data);
		} else {
			cdda->disc.title = g_strdup ("Unknown Title");
    		}
    		if (mb_GetResultInt(mb, MBE_AlbumGetNumReleaseDates) >= 1)	{
    			mb_Select1(mb, MBS_SelectReleaseDate, 1);
    			mb_GetResultData(mb, MBE_ReleaseGetDate, data, MB_BUFFER_SIZE);
    			cdda->disc.year = atoi (data);
    		 	mb_Select(mb, MBS_Back);
    		} else {
    			cdda->disc.year = 0;
 		}
		cdda->disc.genre = 0;
		cdda->disc.tracks = mb_GetResultInt (mb, MBE_AlbumGetNumTracks);
		if (cdda->disc.tracks == 0) {
			cdda_free (cdda, NULL);
			return NULL;
		}

		 for (index = 0; index < cdda->disc.tracks; index++) {
			if (mb_GetResultData1 (mb, MBE_AlbumGetTrackName, data,
MB_BUFFER_SIZE, index+1)) {
				cdda->disc.track[index].name = g_strdup (data);
			} else {
				cdda->disc.track[index].name = g_strdup_printf ("Track %.2d", index
+1);
			}
			if (mb_GetResultData1 (mb, MBE_AlbumGetArtistName, data,
MB_BUFFER_SIZE, index+1)) {
				cdda->disc.track[index].artist = g_strdup (data);
			} else {
				cdda->disc.track[index].artist = g_strdup ("");
			}
			duration = mb_GetResultInt1 (mb, MBE_AlbumGetTrackDuration, index+1);
			cdda->disc.track[index].size = (duration / 1000) * BYTES_PER_SECOND;
		}
		
	} else {		/* musicbrainz lookup failed, we put in some defaults */
		if (!mb_Query (mb, MBQ_GetCDTOC)) {
			cdda_free (cdda, NULL);
			return NULL;
		}
		
		cdda->disc.title = g_strdup ("Unknown Title");
		cdda->disc.genre = 0;
		cdda->disc.year = 0;
		cdda->disc.tracks = mb_GetResultInt (mb, MBE_TOCGetLastTrack);
		
		for (index = 0; index < cdda->disc.tracks; index++) {
			cdda->disc.track[index].name = g_strdup_printf ("Track %.2d", index
+1);
			cdda->disc.track[index].artist = g_strdup ("Unknown Artist");
			cdda->disc.track[index].size = mb_GetResultInt1 (mb,
MBE_TOCGetTrackNumSectors, index+2) * CD_FRAMESIZE_RAW;
		}
	}
	mb_Delete (mb);
	disclist = g_list_append (disclist, cdda);
	return cdda;
}

void 
cdda_free (gpointer data, 
				gpointer user_data) {
	CDDA *cdda = (CDDA *) data;
	gnome_vfs_uri_unref (cdda->uri);
	g_mutex_free (cdda->mutex);
	g_free (cdda->drive);
	disclist = g_list_remove (disclist, cdda);
}

CDDA* 
get_cdda_from_uri (GnomeVFSURI *uri) {
	CDDA *cdda;
	gchar *str_uri;
	guint length, index;
	
	str_uri = gnome_vfs_uri_to_string (uri,
GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD);
	length = g_list_length (disclist);
	for (index = 0; index < length; index++) {
		cdda = (CDDA *) g_list_nth_data (disclist, index);
		if (g_ascii_strncasecmp (str_uri, cdda->drive, strlen (cdda->drive))
== 0) {
			cdda->last_used = time (NULL);
			return cdda;
		}
	}
	return NULL;
}

gushort 
get_tracknumber_from_uri (GnomeVFSURI *uri) {
	CDDA *cdda;
	gushort index;
	gchar *escaped_name, *name, *ext, *trackname;
	
	g_return_val_if_fail ((cdda = get_cdda_from_uri (uri)) != NULL, 0);
	
	escaped_name =gnome_vfs_uri_extract_short_name (uri);
	name =  gnome_vfs_unescape_string_for_display (escaped_name);
	ext = g_strrstr (name, ".");
	
	if (ext == NULL) {
		g_free (escaped_name);
		g_free (name);
		return 0;
	}
	
	trackname = g_strndup (name, ext - name);
	g_free (escaped_name);
	g_free (name);
	
	for (index = 0; index < cdda->disc.tracks; index++) {
		if (g_ascii_strcasecmp (trackname, g_strdup_printf ("%.2d - %s", index
+1, cdda->disc.track[index].name)) == 0) {
			g_free (trackname);
			return index+1;
		}
	}
	g_free (trackname);
	return 0;
}

GnomeVFSResult 
get_file_info (gchar *name, 
				gushort tracknumber, 
				CDDA *cdda, 
				GnomeVFSFileInfo *file_info) {
	gchar *ext, *dev;

	file_info->atime = time (NULL);
	file_info->ctime = time (NULL);
	file_info->mtime = time (NULL);
	file_info->permissions = GNOME_VFS_PERM_USER_READ |
GNOME_VFS_PERM_GROUP_READ;
	file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
								GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
								GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS |
								GNOME_VFS_FILE_INFO_FIELDS_ATIME | 
								GNOME_VFS_FILE_INFO_FIELDS_MTIME |
								GNOME_VFS_FILE_INFO_FIELDS_CTIME;
	file_info->name = name;
	
	ext = g_strrstr (name, ".");
	dev = g_strrstr (cdda->drive, GNOME_VFS_URI_PATH_STR);
	dev++;
		
	if (ext != NULL) {			/* is file */
		/* This is always set this way, so we can rely on a common buffer size
when reading */
		file_info->io_block_size = CD_FRAMESIZE_RAW;
		file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
		file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE |
GNOME_VFS_FILE_INFO_FIELDS_SIZE;
		if (g_ascii_strcasecmp (ext, ".wav") == 0) {
			file_info->mime_type = g_strdup ("audio/x-wav");
			file_info->size = cdda->disc.track[tracknumber-1].size;
		} else if (gst_supports_mp3 && g_ascii_strcasecmp (ext, ".mp3") == 0)
{
			file_info->mime_type = g_strdup ("audio/mpeg");
			/* We just assume that mp3/ogg files have 1/10 of the original size.
This may or may not be true, 
			 * depending on the file. The real size is known only after encoding
(due to vbr usage in mp3/vorbis), 
			 * but it is needed for the progress dialog to work, so we make a
good guess about the size.
			 * The same is true for flac files, but with 1/2 of the original
size. (Is this right?)
			 */
			file_info->size = cdda->disc.track[tracknumber-1].size / 10;
		} else if (gst_supports_ogg && g_ascii_strcasecmp (ext, ".ogg") == 0)
{
			file_info->mime_type = g_strdup ("application/ogg");
			file_info->size = cdda->disc.track[tracknumber-1].size / 10;
		} else if (gst_supports_flac && g_ascii_strcasecmp (ext, ".flac") ==
0) {
			file_info->mime_type = g_strdup ("audio/x-flac");
			file_info->size = cdda->disc.track[tracknumber-1].size / 2;
		} else {
			return GNOME_VFS_ERROR_NOT_FOUND;
		}
	} else if (g_ascii_strcasecmp (dev, name) == 0 
				|| g_ascii_strcasecmp (name, "MP3") == 0 
				|| g_ascii_strcasecmp (name, "Ogg Vorbis") == 0 
				|| g_ascii_strcasecmp (name, "Flac") == 0) {						/* is directory */
			file_info->type = GNOME_VFS_FILE_TYPE_DIRECTORY;
			file_info->permissions |= GNOME_VFS_PERM_USER_EXEC |
GNOME_VFS_PERM_GROUP_EXEC ;
			file_info->mime_type = g_strdup ("x-directory/normal");
	} else {
		return GNOME_VFS_ERROR_NOT_FOUND;
	}
	return GNOME_VFS_OK;
}





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