Re: [Nautilus-list] Nautilus with ogg



Jonathan Blandford wrote:

Remi Cohen-Scali <Remi Cohen-Scali Sun COM> writes:

Jonathan Blandford wrote:

Marius Stepien <marius linuxgamer de> writes:

Hello !

I like the abbility of nautilus to listen to MP3s by leaving the mouse
pointer above a mp3 file. Now I plan to convert my MP3s to ogg vorbis,
so I wanted to ask if there are plans to make nautilus support this
file-type ?  Thank you !

It should do that already.  It would be nice to have someone port the
music view to handle .ogg files, though.  I started this a while ago,
but put it down due to the 'not-enough-spare-cycles' problem.
Interested???

-Jonathan

_______________________________________________
Nautilus-list mailing list
Nautilus-list lists eazel com
http://lists.eazel.com/mailman/listinfo/nautilus-list

I also did some work about it. I would be interrested in sharing
experiences about it. Was you able to read ogg files ?
I was able to read ogg in preview mode (add no problems) but I ran
into some problems when implementing the multi threaded player. It
turns into an instable state after 2 or three play/stop/pause
cycles. I also didn't yet implemented the fetch functionality.
Another work I think should be done is to enable the music view to be
file type/player type independent. I have some thought about it, but I
did nothing at now.


I just added a music-file abstraction to the player, and then changed
added the ogg/mp3 as backends to them.  You can see the patch at:
http://people.redhat.com/jrb/files/music.patch
I'm not sure how cleanly it applies anymore, though.

Anyway, I never quite got it to play -- just display .ogg files
correctly.  If you start doing work again, I wouldn't mind taking a
quick look at it.

Thanks,
-Jonathan

Hey, it seems our work have been complementary.
Here is the patch. I do not know if it will apply on 1.4.0.x because it has been made for 1.3.0.2, but I'am going to adapt it to your abstraction layer. I'll send you soon another with your patch applied for cvs head.


--
                                    Remi Cohen-Scali
  _/_/_/   _/    _/  _/      /      Development engineer
  _/      _/    _/  _/_/   _/       International Center for Network Computing
 _/_/_/  _/    _/  _/  _/ _/        Network Service Provider Division
    _/  _/    _/  _/   _/_/         Phone:     +33-139-447-509  x44509
_/_/_/   _/_/_/   _/     _/          E-mails: Remi Cohen-Scali Sun COM
M  I  C  R  O  S  Y  S  T  E  M  S            Remi Cohen-Scali COM
                                    WAPmail: Remi CohenScali Itineris Net




diff -urNwbB nautilus/components/music/Makefile.am nautilus-ogg/components/music/Makefile.am
--- nautilus/components/music/Makefile.am	Thu May  3 23:14:29 2001
+++ nautilus-ogg/components/music/Makefile.am	Sun Jun 24 03:27:48 2001
@@ -1,5 +1,13 @@
 NULL =
 
+if HAVE_LIBVORBIS
+player_srcs = mpg123.c ogg.c
+player_hdrs = mpg123.h ogg.h
+else
+ogg_srcs = mpg123.c
+ogg_hdrs = mpg123.h
+endif
+
 if X86_OPTIMIZED
 decode_source = decode_i386.c
 dct64_source  = dct64_i386.c
@@ -15,6 +23,8 @@
 	-I$(top_srcdir)				\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
 	$(NAUTILUS_PRIVATE_CFLAGS) \
+	@HAVE_LIBVORBIS@			\
+	@OGG_CFLAGS@ @VORBIS_CFLAGS@ 		\
 	$(NULL)
 
 bin_PROGRAMS =					\
@@ -35,8 +45,8 @@
 	decode_ntom.c  				\
 	dxhead.c  				\
 	dxhead.h  				\
-	mpg123.c				\
-	mpg123.h				\
+	$(player_srcs)				\
+	$(player_hdrs)				\
 	common.c				\
 	layer1.c				\
 	layer2.c				\
@@ -60,6 +70,7 @@
 	$(top_builddir)/libnautilus/libnautilus.la	\
 	$(top_builddir)/libnautilus-private/libnautilus-private.la	\
 	$(NAUTILUS_PRIVATE_LIBS) \
+	@VORBISFILE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@	\
 	$(NULL)
 
 oafdir = $(datadir)/oaf
diff -urNwbB nautilus/components/music/Nautilus_View_music.oaf.in nautilus-ogg/components/music/Nautilus_View_music.oaf.in
--- nautilus/components/music/Nautilus_View_music.oaf.in	Sun Feb 25 05:01:56 2001
+++ nautilus-ogg/components/music/Nautilus_View_music.oaf.in	Sat Jun 23 16:26:12 2001
@@ -25,6 +25,8 @@
 	<oaf_attribute name="nautilus:required_directory_content_mime_types" type="stringv">
 		<item value="audio/x-mpeg"/>
 		<item value="audio/x-mp3"/>
+		<item value="application/x-ogg"/>
+		<item value="audio/x-ogg"/>
 	</oaf_attribute>
 	<oaf_attribute name="nautilus:view_as_name" type="string" _value="Music"/>
 	<oaf_attribute name="nautilus:view_as_label" type="string" _value="View as Music"/>
diff -urNwbB nautilus/components/music/esd-audio.c nautilus-ogg/components/music/esd-audio.c
--- nautilus/components/music/esd-audio.c	Mon Apr 23 09:55:23 2001
+++ nautilus-ogg/components/music/esd-audio.c	Fri Jun 29 02:48:13 2001
@@ -5,6 +5,14 @@
 #include "esd-audio.h"
 #include "config.h"
 
+//#define ESDOUT_DEBUG
+#ifdef ESDOUT_DEBUG
+#define ESDOUT_LOG(fmt...)		fprintf(stdout, fmt);
+#else
+#define ESDOUT_LOG(fmt...)		/* */
+#endif
+
+
 static gint fd = 0;
 static gpointer buffer;
 static gboolean going = FALSE, prebuffer, paused = FALSE, remove_prebuffer = FALSE;
@@ -309,7 +317,9 @@
 void 
 esdout_close (void)
 {
+        ESDOUT_LOG("esdout_close -- entry\n"); 
 	if (!going) {
+                ESDOUT_LOG("esdout_close -- not going\n"); 
 		return;
 	}
 	
@@ -318,7 +328,9 @@
 	going = 0;
 	g_free (hostname);
 	hostname = NULL;
+        ESDOUT_LOG("esdout_close -- joining buffer thread\n"); 
 	pthread_join (buffer_thread, NULL);
+        ESDOUT_LOG("esdout_close -- buffer thread joined\n"); 
 }
 
 void 
@@ -341,16 +353,19 @@
 {
 	gint length, cnt;
 	
+        ESDOUT_LOG("esdout_loop -- entry\n"); 
 	while (going) {
 		if (esdout_used () > prebuffer_size) {
 			prebuffer = FALSE;
 		}
+                ESDOUT_LOG("esdout_loop -- prebuffer = %s\n", prebuffer ? "TRUE" : "FALSE"); 
 		
 		if (esdout_used () > 0 && !paused && !prebuffer) {
 			length = MIN (blk_size, esdout_used ());
 			while (length > 0) {
 				cnt = MIN(length,buffer_size-rd_index);
 				esdout_write_audio ((gchar *)buffer + rd_index, cnt);
+                                ESDOUT_LOG("esdout_loop -- wrote = %d\n", cnt); 
 				rd_index=(rd_index+cnt)%buffer_size;
 				length-=cnt;				
 			}
@@ -358,6 +373,7 @@
 			usleep (10000);
 		}
 
+                ESDOUT_LOG("esdout_loop -- flush = %d\n", flush); 
 		if (flush != -1) {
 			output_time_offset = flush;
 			written = (guint64)(flush / 10) * (guint64)(input_bps / 100);
@@ -369,6 +385,7 @@
 
 	close (fd);
 	g_free (buffer);
+        ESDOUT_LOG("esdout_loop -- exit\n"); 
 	pthread_exit (NULL);
 	return NULL;  /* make gcc happy */
 }
@@ -386,6 +403,7 @@
 gint
 esdout_open (AFormat fmt, gint rate, gint nch)
 {	
+        ESDOUT_LOG("esdout_open -- entry\n"); 
 	esdout_init ();
 	
 	esdout_setup_format (fmt,rate,nch);
@@ -419,12 +437,15 @@
 	
 	esdout_set_audio_params ();
 	if (fd == -1) {
+                ESDOUT_LOG("esdout_open -- error opening audio socket\n"); 
 		g_free(buffer);
 		return 0;
 	}
 	going = 1;
 
+        ESDOUT_LOG("esdout_open -- starting buffer thread\n"); 
 	pthread_create (&buffer_thread, NULL, esdout_loop, NULL);
+        ESDOUT_LOG("esdout_open -- buffer thread started\n"); 
 	
 	return 1;
 }
diff -urNwbB nautilus/components/music/mpg123.c nautilus-ogg/components/music/mpg123.c
--- nautilus/components/music/mpg123.c	Fri May 18 14:20:49 2001
+++ nautilus-ogg/components/music/mpg123.c	Thu Jun 28 23:30:12 2001
@@ -10,7 +10,7 @@
 
 static struct frame fr, temp_fr;
 
-PlayerInfo *mpg123_info = NULL;
+Mp3PlayerInfo *mpg123_info = NULL;
 static pthread_t decode_thread;
 MPG123Config mpg123_cfg;
 
@@ -564,7 +564,7 @@
 }
 
 void 
-get_song_info (char *filename, char **title_real, int *len_real)
+mpg123_get_song_info (char *filename, char **title_real, int *len_real)
 {
 	FILE *file;
 
@@ -578,8 +578,8 @@
 	}
 }
 
-static void 
-*decode_loop (void *arg)
+static void *
+decode_loop (void *arg)
 {
 	gboolean output_opened = FALSE;
 	gint disp_count = 0, temp_time;
@@ -787,7 +787,7 @@
 	memset(&fr, 0, sizeof (struct frame));
 	memset(&temp_fr, 0, sizeof (struct frame));
 
-	mpg123_info = g_malloc0(sizeof (PlayerInfo));
+	mpg123_info = g_malloc0(sizeof (Mp3PlayerInfo));
 	mpg123_info->going = TRUE;
 	mpg123_info->paused = FALSE;
 	mpg123_info->first_frame = TRUE;
@@ -830,7 +830,7 @@
 }
 
 int 
-get_time (void)
+mpg123_get_time (void)
 {
 	if (audio_error)
 		return -2;
diff -urNwbB nautilus/components/music/mpg123.h nautilus-ogg/components/music/mpg123.h
--- nautilus/components/music/mpg123.h	Fri May 18 14:20:49 2001
+++ nautilus-ogg/components/music/mpg123.h	Thu Jun 28 23:29:54 2001
@@ -72,12 +72,12 @@
 	gboolean first_frame;
 	guint32 filesize;	/* Filesize without junk */
 }
-PlayerInfo;
+Mp3PlayerInfo;
 
 void mpg123_set_eq(int on, float preamp, float *band);
 void mpg123_file_info_box(char *);
 
-extern PlayerInfo *mpg123_info;
+extern Mp3PlayerInfo *mpg123_info;
 
 struct al_table
 {
@@ -298,11 +298,11 @@
 extern int tabsel_123[2][3][16];
 
 
-void get_song_info (char *filename, char **title_real, int *len_real);
+void mpg123_get_song_info (char *filename, char **title_real, int *len_real);
 void mpg123_play_file (const char *filename);
 void mpg123_stop (void);
 void mpg123_seek (int time);
 void mpg123_pause (gboolean pause);
-int get_time (void);
+int mpg123_get_time (void);
 
 #endif
diff -urNwbB nautilus/components/music/nautilus-music-view.c nautilus-ogg/components/music/nautilus-music-view.c
--- nautilus/components/music/nautilus-music-view.c	Wed Jun  6 18:01:28 2001
+++ nautilus-ogg/components/music/nautilus-music-view.c	Fri Jun 29 04:19:43 2001
@@ -65,13 +65,22 @@
 #include <fcntl.h>
 #include <limits.h>
 
+#ifdef HAVE_LIBVORBIS
+#include <vorbis/vorbisfile.h>
+#include <vorbis/codec.h>
+
+#include "ogg.h"
+#endif
+
 #define SCALED_IMAGE_WIDTH	108
 #define SCALED_IMAGE_HEIGHT 	108
 
 typedef enum {
 	PLAYER_STOPPED,
-	PLAYER_PAUSED,
-	PLAYER_PLAYING,
+	PLAYER_PAUSED_MP3,
+	PLAYER_PAUSED_OGG,
+	PLAYER_PLAYING_MP3,
+	PLAYER_PLAYING_OGG,
 	PLAYER_NEXT
 } PlayerState;
 
@@ -118,6 +127,12 @@
 	PlayerState last_player_state;
 };
 
+#ifdef HAVE_LIBVORBIS
+typedef enum {
+        BITSTREAM_TYPE_MP3,
+        BITSTREAM_TYPE_OGG
+} BitstreamType;
+#endif
 
 /* structure for holding song info */
 typedef struct {
@@ -133,6 +148,9 @@
 	char *year;
 	char *comment;
 	char *path_uri;
+#ifdef HAVE_LIBVORBIS
+        BitstreamType stream_type;
+#endif
 } SongInfo;
 
 enum {
@@ -203,8 +221,12 @@
 static void play_current_file                                 (NautilusMusicView      *music_view,
                                                                gboolean                from_start);
 static void detach_file                                       (NautilusMusicView      *music_view);
-static void start_playing_file 				      (NautilusMusicView      *music_view, 
+static void start_playing_mp3_file			      (NautilusMusicView      *music_view, 
+							       const char 	      *file_name);
+#ifdef HAVE_LIBVORBIS
+static void start_playing_ogg_file			      (NautilusMusicView      *music_view, 
 							       const char 	      *file_name);
+#endif
 static void stop_playing_file 				      (NautilusMusicView      *music_view);
 static PlayerState get_player_state 			      (NautilusMusicView      *music_view);
 static void set_player_state 				      (NautilusMusicView      *music_view, 
@@ -454,7 +476,9 @@
 	PlayerState state;
 	
 	state = get_player_state (music_view);
-	is_playing_or_paused = (state == PLAYER_PLAYING || state == PLAYER_PAUSED);
+	is_playing_or_paused =
+          (state == PLAYER_PLAYING_MP3 || state == PLAYER_PLAYING_OGG) || 
+            (state == PLAYER_PAUSED_MP3 || state == PLAYER_PAUSED_OGG);
 	 
 	/* Exit if we are playing and clicked on the row that represents the playing song */
 	if (is_playing_or_paused && (music_view->details->selected_index == row)) {
@@ -909,7 +933,7 @@
 
 /* allocate a return a song info record, from an mp3 tag if present, or from intrinsic info */
 static SongInfo *
-fetch_song_info (const char *song_uri, GnomeVFSFileInfo *file_info, int file_order) 
+fetch_mp3_song_info (const char *song_uri, GnomeVFSFileInfo *file_info, int file_order) 
 {
 	gboolean has_info = FALSE;
 	SongInfo *info; 
@@ -926,6 +950,9 @@
 
 	info = g_new0 (SongInfo, 1); 
 	initialize_song_info (info);
+#ifdef HAVE_LIBVORBIS
+        info->stream_type = BITSTREAM_TYPE_MP3;
+#endif
 	
 	has_info = read_id_tag (song_uri, info);
 
@@ -978,6 +1005,209 @@
 	return	info;
 }
 
+#ifdef HAVE_LIBVORBIS
+/* determine if a file is an mp3 file by looking at the mime type */
+static gboolean
+is_ogg_file (GnomeVFSFileInfo *file_info)
+{
+	return eel_istr_has_prefix (file_info->mime_type, "application/")
+		&& eel_istr_has_suffix (file_info->mime_type, "ogg");
+}
+
+/* The 4 following func are given to vorbisfile lib as an adaptation
+   to GnomeVFS */
+/* read_func */
+static size_t
+read_ogg_cb(void *ptr, size_t size, size_t nmemb, void* datasrc)
+{
+        GnomeVFSHandle *ogg_file =(GnomeVFSHandle *)datasrc;
+        GnomeVFSResult result;
+        GnomeVFSFileSize bytes_read;
+
+        result = gnome_vfs_read(ogg_file, (gpointer)ptr, size * nmemb, &bytes_read);
+        
+        g_return_val_if_fail(result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_EOF, (size_t)-1);
+        return( (size_t)bytes_read);
+}
+
+/* seek_func */
+static int
+seek_ogg_cb(void *datasrc, int64_t offset, int whence)
+{
+        GnomeVFSHandle *ogg_file =(GnomeVFSHandle *)datasrc;
+        GnomeVFSSeekPosition vfs_whence;
+        GnomeVFSFileOffset vfs_offset = (GnomeVFSFileOffset)offset;
+        GnomeVFSResult result;
+
+        switch (whence) {
+              case SEEK_CUR:
+                vfs_whence = GNOME_VFS_SEEK_CURRENT;
+                break;
+              case SEEK_END:
+                vfs_whence = GNOME_VFS_SEEK_END;
+                break;
+              case SEEK_SET:
+              default:
+                vfs_whence = GNOME_VFS_SEEK_START;
+        }
+        
+        result = gnome_vfs_seek(ogg_file, vfs_whence, vfs_offset);
+        g_return_val_if_fail(result == GNOME_VFS_OK, -1);
+        return(0);
+}
+
+/* close_func */
+static int
+close_ogg_cb(void *datasrc)
+{
+        GnomeVFSHandle *ogg_file =(GnomeVFSHandle *)datasrc;
+        GnomeVFSResult result;
+
+        result = gnome_vfs_close(ogg_file);
+        g_return_val_if_fail(result == GNOME_VFS_OK, -1);
+        return(0);
+}
+
+/* tell_func */
+static long
+tell_ogg_cb(void *datasrc)
+{
+        GnomeVFSHandle *ogg_file =(GnomeVFSHandle *)datasrc;
+        GnomeVFSFileSize curpos =(GnomeVFSFileSize)0L;
+        GnomeVFSResult result;
+
+        result = gnome_vfs_tell(ogg_file, &curpos);
+        g_return_val_if_fail(result == GNOME_VFS_OK, -1L);
+        return( (long)curpos);
+}
+
+static gchar *extname(const char *filename)
+{
+	gchar *ext = strrchr(filename, '.');
+
+	if (ext != NULL)
+		++ext;
+
+	return ext;
+}
+
+/* Read the ogg comments and fill song infos (artist, title, ...) */
+static void
+decode_ogg_vorbis_comments(vorbis_comment *vc, SongInfo *song_info, char *fname)
+{
+        int i, j;
+
+        for (i = 0; i < vc->comments; i++) {
+                for (j = 0; j < OGG_COMMENT_KEY_N_KEYS; j++) {
+                        if (g_strncasecmp(ogg_comment_keys[j], vc->user_comments[i], strlen(ogg_comment_keys[j])))
+                          break;
+                }
+                switch (j) {
+                      case OGG_COMMENT_KEY_ARTIST:
+                              song_info->artist = g_strdup (vc->user_comments[i]+
+                                                            strlen(ogg_comment_keys[j])+1);
+                              break;
+                        
+                      case OGG_COMMENT_KEY_ALBUM:
+                              song_info->album = g_strdup (vc->user_comments[i]+
+                                                           strlen(ogg_comment_keys[j])+1); 
+                              break;
+                        
+                      case OGG_COMMENT_KEY_TITLE:
+                              song_info->title = g_strdup (vc->user_comments[i]+
+                                                           strlen(ogg_comment_keys[j])+1);
+                              break;
+                        
+                      case OGG_COMMENT_KEY_TRACKNUMBER:
+                              song_info->track_number = atoi (vc->user_comments[i]+
+                                                              strlen(ogg_comment_keys[j])+1);
+                              if (song_info->track_number <= 0) {
+                                      song_info->track_number = extract_number(fname);
+                              }
+                              break;
+                        
+                      case OGG_COMMENT_KEY_DESCRIPTION: 
+                              song_info->comment = g_strdup (vc->user_comments[i]+
+                                                             strlen(ogg_comment_keys[j])+1);
+                              break;
+                        
+                      case OGG_COMMENT_KEY_DATE: 
+                              song_info->year = g_strdup (vc->user_comments[i]+
+                                                          strlen(ogg_comment_keys[j])+1);
+                              break;
+                        
+                      case OGG_COMMENT_KEY_VERSION:
+                      case OGG_COMMENT_KEY_ORGANIZATION: 
+                      case OGG_COMMENT_KEY_GENRE: 
+                      case OGG_COMMENT_KEY_LOCATION:
+                      case OGG_COMMENT_KEY_COPYRIGHT:
+                      default:
+                        /* discard ...??... FIXME */
+                        break;
+                }
+                        
+                /* there was no id3 tag, so set up the info heuristically from the file name and file order */
+                if (!song_info || !song_info->title || !*song_info->title) {
+                        song_info->title = g_strdup (fname);
+                        if (extname(song_info->title) != NULL)
+                                *(extname(song_info->title) - 1) = '\0';	/* removes period */
+                }	
+        }
+}
+
+/* allocate a return a OGG song info recordg if present, or from intrinsic info */
+static SongInfo *
+fetch_ogg_song_info (const char *song_uri, GnomeVFSFileInfo *file_info, int file_order) 
+{
+	SongInfo *info; 
+	GnomeVFSHandle *ogg_file =(GnomeVFSHandle*)NULL;
+        OggVorbis_File vf;
+        vorbis_comment *vc;
+        vorbis_info *vi;
+        ov_callbacks cbs = {
+                read_ogg_cb,
+                seek_ogg_cb,
+                close_ogg_cb,
+                tell_ogg_cb
+        };
+        int err;
+        
+	if (!is_ogg_file (file_info)) {
+		return NULL;
+        }
+
+	info = g_new0 (SongInfo, 1); 
+	initialize_song_info (info);
+        info->stream_type = BITSTREAM_TYPE_OGG;
+
+	if (GNOME_VFS_OK == gnome_vfs_open (&ogg_file, song_uri, GNOME_VFS_OPEN_READ)) {
+                err = ov_open_callbacks( (void*)ogg_file, &vf, NULL, 0, cbs);
+                if (err) {
+                        return info;
+                }
+                
+                vc = ov_comment( &vf, -1);
+                if (vc) {
+                        decode_ogg_vorbis_comments(vc, info, file_info->name);
+                }
+
+                vi = ov_info( &vf, -1);
+                if (!vi) {
+                        return info;
+                }
+
+                info->bitrate = ov_bitrate( &vf, -1) / 1024;
+                info->samprate = vi->rate;
+                info->stereo = (vi->channels == 1 ? 0 : 3);
+                info->track_time = ov_time_total( &vf, -1);
+
+                ov_clear( &vf);
+	}
+        
+	return	info;
+}
+#endif
+
 /* utility routine to determine most common attribute in song list.  The passed in boolean selects
    album or artist. Return NULL if they are heterogenous */
 static char *
@@ -1010,7 +1240,7 @@
 static void
 update_play_controls_status (NautilusMusicView *music_view, PlayerState state)
 {
-	if (state == PLAYER_PLAYING) {
+	if (state == PLAYER_PLAYING_MP3 || state == PLAYER_PLAYING_OGG) {
 		gtk_widget_show (music_view->details->active_play_pixwidget);
 		gtk_widget_hide (music_view->details->inactive_play_pixwidget);
 		//gtk_widget_set_sensitive (music_view->details->pause_button, TRUE);
@@ -1019,7 +1249,7 @@
 		gtk_widget_show (music_view->details->inactive_play_pixwidget);		
 	}
 
-	if (state == PLAYER_PAUSED) {
+	if (state == PLAYER_PAUSED_MP3 || state == PLAYER_PAUSED_OGG) {
 		gtk_widget_show (music_view->details->active_pause_pixwidget);
 		gtk_widget_hide (music_view->details->inactive_pause_pixwidget);
 		//gtk_widget_set_sensitive (music_view->details->pause_button, FALSE);
@@ -1053,7 +1283,9 @@
 	PlayerState status;
 			
 	status = get_player_state (music_view);
-	is_playing_or_paused = (status == PLAYER_PLAYING) || (status == PLAYER_PAUSED);
+	is_playing_or_paused =
+          (status == PLAYER_PLAYING_MP3 || status == PLAYER_PLAYING_OGG) ||
+            (status == PLAYER_PAUSED_MP3 || status == PLAYER_PAUSED_OGG);
 	
 	if (status == PLAYER_NEXT) {
 		stop_playing_file (music_view);
@@ -1221,7 +1453,14 @@
 	}
 	
 	/* set up the current duration so we can give progress feedback */        
-	get_song_info (song_filename, &title, &length);
+        switch (song_info->stream_type) {
+        case BITSTREAM_TYPE_MP3:
+                mpg123_get_song_info (song_filename, &title, &length);
+                break; 
+        case BITSTREAM_TYPE_OGG:
+                mpg123_get_song_info (song_filename, &title, &length);
+                break;
+        }
 	music_view->details->current_duration = length;
 	g_free (title);
 	
@@ -1244,7 +1483,17 @@
         
 	music_view->details->status_timeout = gtk_timeout_add (900, (GtkFunction) play_status_display, music_view);
 
-	start_playing_file (music_view, song_filename);
+        switch (song_info->stream_type) {
+        case BITSTREAM_TYPE_MP3:
+                start_playing_mp3_file (music_view, song_filename);
+                break; 
+#ifdef HAVE_LIBVORBIS
+        case BITSTREAM_TYPE_OGG:
+                start_playing_ogg_file (music_view, song_filename);
+                break; 
+#endif
+        default:
+        }
 
 	g_free (song_filename);
 }
@@ -1253,7 +1502,7 @@
 static void
 go_to_next_track (NautilusMusicView *music_view)
 {
-	mpg123_stop ();		
+	stop_playing_file(music_view); 
 	if (music_view->details->selected_index < (GTK_CLIST (music_view->details->song_list)->rows - 1)) {
 		music_view->details->selected_index += 1;		
 		play_current_file (music_view, TRUE);
@@ -1271,7 +1520,7 @@
 		music_view->details->selected_index -= 1;
 	}
 	
-	mpg123_stop ();	
+	stop_playing_file (music_view);	
 	play_current_file (music_view, TRUE);
 }
 
@@ -1282,13 +1531,17 @@
 static void
 play_button_callback (GtkWidget *widget, NautilusMusicView *music_view)
 {
-	if (get_player_state (music_view) == PLAYER_PLAYING) {
+	if (get_player_state (music_view) == PLAYER_PLAYING_MP3 || 
+            get_player_state (music_view) == PLAYER_PLAYING_OGG) {
 		return;
 	}
 
-	if (get_player_state (music_view) == PLAYER_PAUSED) {				
-		set_player_state (music_view, PLAYER_PLAYING);
+	if (get_player_state (music_view) == PLAYER_PAUSED_MP3) {
+		set_player_state (music_view, PLAYER_PLAYING_MP3);
 		mpg123_pause (FALSE);
+	} else if (get_player_state (music_view) == PLAYER_PAUSED_OGG) {
+		set_player_state (music_view, PLAYER_PLAYING_OGG);
+		ogg_pause (FALSE);
 	} else {
 		play_current_file (music_view, FALSE);
 	}
@@ -1306,12 +1559,18 @@
 	PlayerState state;
 	state = get_player_state (music_view);
 	
-	if (state == PLAYER_PLAYING) {
-		set_player_state (music_view, PLAYER_PAUSED);
+	if (state == PLAYER_PLAYING_MP3) {
+		set_player_state (music_view, PLAYER_PAUSED_OGG);
 		mpg123_pause (TRUE);
-	} else if (state == PLAYER_PAUSED) {
-		set_player_state (music_view, PLAYER_PLAYING);
+	} else if (state == PLAYER_PLAYING_OGG) {
+                set_player_state (music_view, PLAYER_PAUSED_OGG);
+		ogg_pause (TRUE);
+	} else if (state == PLAYER_PAUSED_MP3) {
+		set_player_state (music_view, PLAYER_PLAYING_MP3);
 		mpg123_pause (FALSE);
+	} else if (state == PLAYER_PAUSED_OGG) {
+		set_player_state (music_view, PLAYER_PLAYING_OGG);
+		ogg_pause (FALSE);
 	}
 }
 
@@ -1717,7 +1976,12 @@
 		g_free (escaped_name);
                 
 		/* fetch info and queue it if it's an mp3 file */
-		info = fetch_song_info (path_uri, current_file_info, file_index);
+		info = fetch_mp3_song_info (path_uri, current_file_info, file_index);
+#ifdef HAVE_LIBVORBIS
+                if (!info) {
+                        info = fetch_ogg_song_info (path_uri, current_file_info, file_index);
+                }
+#endif
 		if (info) {
 			info->path_uri = path_uri;
 			file_index += 1;
@@ -1938,12 +2202,21 @@
 }
 
 static void
-start_playing_file (NautilusMusicView *music_view, const char *file_name)
+start_playing_mp3_file (NautilusMusicView *music_view, const char *file_name)
 {
-	set_player_state (music_view, PLAYER_PLAYING);
+	set_player_state (music_view, PLAYER_PLAYING_MP3);
 	mpg123_play_file (file_name);
 }
 
+#ifdef HAVE_LIBVORBIS
+static void
+start_playing_ogg_file (NautilusMusicView *music_view, const char *file_name)
+{
+	set_player_state (music_view, PLAYER_PLAYING_OGG);
+	ogg_play_file (file_name);
+}
+#endif
+
 static void
 stop_playing_file (NautilusMusicView *music_view)
 {
@@ -1951,16 +2224,24 @@
 
 	state = get_player_state (music_view);
 	
-	if (state == PLAYER_PLAYING || state == PLAYER_PAUSED) {
+	if (state == PLAYER_PLAYING_MP3 || state == PLAYER_PAUSED_MP3) {
 		set_player_state (music_view, PLAYER_STOPPED);
 		mpg123_stop ();
 	}
+#ifdef HAVE_LIBVORBIS
+	if (state == PLAYER_PLAYING_OGG || state == PLAYER_PAUSED_OGG) {
+		set_player_state (music_view, PLAYER_STOPPED);
+		ogg_stop ();
+	}
+#endif
 }
 
 static PlayerState
 get_player_state (NautilusMusicView *music_view)
 {
-	if (music_view->details->player_state == PLAYER_PLAYING && !esdout_playing ()) {
+	if ((music_view->details->player_state == PLAYER_PLAYING_MP3 || 
+             music_view->details->player_state == PLAYER_PLAYING_OGG) &&
+            !esdout_playing ()) {
 		music_view->details->player_state = PLAYER_NEXT;
 	}
 
diff -urNwbB nautilus/components/music/ogg.c nautilus-ogg/components/music/ogg.c
--- nautilus/components/music/ogg.c	Wed Dec 31 19:00:00 1969
+++ nautilus-ogg/components/music/ogg.c	Fri Jun 29 04:20:18 2001
@@ -0,0 +1,320 @@
+
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <eel/eel-stock-dialogs.h>
+
+#include "esd-audio.h"
+#include "ogg.h"
+
+#define OGGPLAYER_DEBUG
+#ifdef OGGPLAYER_DEBUG
+#define OGG_LOG(fmt...)		fprintf(stdout, fmt);
+#else
+#define OGG_LOG(fmt...)		/* */
+#endif
+
+#define OGG_WRN(msg)								\
+	fprintf(stderr, msg);							\
+        eel_show_error_dialog (msg, _("Vorbis-Ogg Stream Warning"), NULL);
+
+        
+#define OGG_ERR(msg)								\
+	fprintf(stderr, msg);							\
+        eel_show_error_dialog (msg, _("Vorbis-Ogg Stream Error"), NULL);
+
+static pthread_t player_thread;
+static gboolean audio_error = FALSE;
+
+OggPlayerInfo *ogg_info = NULL;
+
+void 	ogg_get_song_info(char *filename, char **title_real, int *len_real);
+
+/*
+ * Function extname (filename)
+ *
+ *    Return pointer within filename to its extenstion, or NULL if
+ *    filename has no extension.
+ *
+ */
+static gchar *extname(const char *filename)
+{
+	gchar *ext = strrchr(filename, '.');
+
+	if (ext != NULL)
+		++ext;
+
+	return ext;
+}
+
+/*
+ * Function mpg123_format_song_title (tag, filename)
+ *
+ *    Create song title according to `tag' and/or `filename' and
+ *    return it.  The title must be subsequently freed using g_free().
+ *
+ */
+static gchar*
+ogg_format_song_title(vorbis_comment *vc, gchar* filename)
+{
+        int i;
+        gchar* ret; 
+
+        for (i = 0; i < vc->comments; i++) {
+                if (!g_strncasecmp(ogg_comment_keys[OGG_COMMENT_KEY_TITLE], 
+                                   vc->user_comments[i], 
+                                   strlen(ogg_comment_keys[OGG_COMMENT_KEY_TITLE]))) {
+                  break; 
+                }
+        }
+        
+	if (i == vc->comments)
+	{
+		/*
+		 * Format according to filename.
+		 */
+		ret = g_strdup(g_basename(filename));
+		if (extname(ret) != NULL)
+			*(extname(ret) - 1) = '\0';	/* removes period */
+	}
+        else {
+                ret = g_strdup(vc->user_comments[i]+
+                               strlen(ogg_comment_keys[OGG_COMMENT_KEY_TITLE])+1); 
+        }
+
+	return ret;
+}
+
+
+static gchar*
+get_song_title(OggVorbis_File* vf, gchar* filename)
+{
+        return ogg_format_song_title(ov_comment(vf, -1), filename); 
+}
+
+void
+ogg_get_song_info(char *filename, char **title_real, int *len_real)
+{
+	FILE *file;
+        OggVorbis_File vf;
+
+	(*len_real) = -1;
+	(*title_real) = NULL;
+
+	if ((file = fopen(filename, "rb")) != NULL) {
+                if(ov_open (file, &vf, NULL, 0) < 0) {
+                        OGG_LOG ("ogg_get_song_info -- >>> opening stream failed ! <<<\n"); 
+                }
+                else {
+                        (*len_real) = ov_time_total( &vf, -1); 
+                        (*title_real) = get_song_title ( &vf, filename);
+                        ov_clear( &vf); 
+                        fclose(file);
+                }
+        }
+}
+
+static void *
+decode_loop (void *arg)
+{
+	gboolean output_opened = FALSE;
+	gboolean stream_opened = FALSE;
+	gchar *filename = arg;
+        OggVorbis_File* vf;
+	vorbis_comment *vc;
+	vorbis_info *vi;
+        FILE* fp;
+        guchar *ogg_pcm_sample;
+        long ret;
+        int current_section;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+        int endianness = 0;
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+        int endianness = 1;
+#endif
+
+        ogg_info->filename = filename;
+        vf = &(ogg_info->vf); 
+        memset(vf, 0, sizeof(OggVorbis_File)); 
+        OGG_LOG ("decode_loop -- filename = '%s'\n", ogg_info->filename); 
+        ogg_pcm_sample = ogg_info->ogg_pcm_sample;
+        audio_error = FALSE; 
+        
+        do {
+                OGG_LOG ("decode_loop -- opening filename\n"); 
+                if (!(fp = fopen (filename, "rb"))) {
+                        ogg_info->eof = TRUE; 
+                        break;
+                }
+        
+                OGG_LOG ("decode_loop -- opening stream\n");
+                if(ov_open (fp, vf, NULL, 0) < 0) {
+                        OGG_LOG ("decode_loop -- >>> opening stream failed ! <<<\n"); 
+                        ogg_info->eof = TRUE; 
+                        break;
+                }
+                stream_opened = TRUE; 
+
+                OGG_LOG ("decode_loop -- stream opened\n"); 
+                vc = ov_comment (vf, -1);
+                OGG_LOG ("decode_loop -- opening comments = 0x%x\n",(unsigned int)vc); 
+                vi = ov_info (vf, -1);
+                OGG_LOG ("decode_loop -- opening infos = 0x%x\n", (unsigned int)vi); 
+
+                OGG_LOG ("decode_loop -- rate = %ld, channels = %d\n", vi->rate, vi->channels); 
+		output_opened = TRUE;
+                if (!esdout_open (FMT_S16_NE, vi->rate, vi->channels)) {
+                        audio_error = TRUE; 
+                        ogg_info->eof = TRUE;
+                }
+
+                ogg_info->eof = FALSE;
+                while (ogg_info->going) {
+
+//#define SEEK_AVAILABLE yes
+#ifdef SEEK_AVAILABLE
+                        if (ogg_info->jump_to_time != -1) {
+                                ov_time_seek (vf, ogg_info->jump_to_time);
+                                esdout_flush (ogg_info->jump_to_time * 1000);
+                                ogg_info->jump_to_time = -1;
+                                ogg_info->eof = FALSE;
+                        }
+#endif
+                        if (!ogg_info->eof) {
+                                ret = ov_read (vf,
+                                               ogg_pcm_sample, PCM_SAMPLES_BUFSIZE,
+                                               endianness,
+                                               2, 1,
+                                               &current_section);
+                                OGG_LOG ("decode_loop -- read = %ld in section %d\n", ret, current_section); 
+                                if ( !ret) {
+                                        esdout_free ();
+                                        esdout_free ();
+                                        ogg_info->eof = TRUE; 
+                                        usleep(10000);
+                                }
+                                else if (ret == OV_HOLE) {
+                                        OGG_WRN (_("Warning: hole in the stream; probably harmless\n"));
+                                        ogg_info->eof = FALSE; 
+                                }
+                                else if (ret < 0) {
+                                        OGG_ERR (_("Error: libvorbis reported a stream error.\n"));
+                                        esdout_free ();
+                                        esdout_free ();
+                                        ogg_info->eof = TRUE; 
+                                        usleep(10000);
+                                }
+                                else {
+                                        ogg_info->eof = FALSE;
+                                        if (esdout_free () < ret && ogg_info->going && ogg_info->jump_to_time == -1) {
+                                                OGG_LOG("decode_loop -- waiting for buffer to release\n"); 
+                                                while (esdout_free () < ret && ogg_info->going && ogg_info->jump_to_time == -1) {
+                                                        usleep (10000);
+                                                }
+                                        }
+                                        OGG_LOG("decode_loop -- writing to audio\n"); 
+                                        esdout_write (ogg_pcm_sample, ret);
+                                }
+                        }
+                        else {
+                                usleep(10000); 
+                        }
+                }
+        } while ( 0 );
+
+        OGG_LOG ("decode_loop -- output_opened = %s\n", output_opened ? "YES" : "NO"); 
+        OGG_LOG ("decode_loop -- audio_error = %s\n", audio_error ? "YES" : "NO"); 
+	if (output_opened && !audio_error) {
+		esdout_close ();
+	}
+
+        /* Release Ogg file */
+        if (stream_opened) {
+                ov_clear (vf);
+        }
+        
+        fclose (fp);
+
+        pthread_exit (NULL);
+
+        /* never reached */
+        return NULL;
+}
+
+void
+ogg_play_file(const char *filename)
+{
+        OGG_LOG ("ogg_play_file -- entry: calling stop\n"); 
+        ogg_stop ();
+
+        ogg_info = g_malloc(sizeof(OggPlayerInfo));
+        if (!ogg_info) return; 
+        ogg_info->going = TRUE;
+        ogg_info->paused = FALSE;
+	ogg_info->jump_to_time = -1;
+	ogg_info->eof = FALSE;
+	audio_error = FALSE;
+        
+        OGG_LOG ("ogg_play_file -- Starting player thread\n"); 
+        pthread_create (&player_thread, NULL, decode_loop, g_strdup (filename));        
+        OGG_LOG ("ogg_play_file -- Player thread started\n"); 
+}
+
+void
+ogg_stop(void)
+{
+        OGG_LOG("ogg_stop -- ogg_info        = 0x%x\n",(unsigned int)ogg_info);         
+	if (ogg_info) {
+                OGG_LOG("ogg_stop -- ogg_info->going = %s\n", ogg_info->going ? "YES" : "NO");         
+                if (ogg_info->going) {
+                        OGG_LOG("ogg_stop -- ogg_filename = %s\n", ogg_info->filename);         
+                        ogg_info->going = FALSE;
+                        OGG_LOG("ogg_stop -- waiting for player thread to stop\n");         
+                        pthread_join (player_thread, NULL);
+                        OGG_LOG("ogg_stop -- player thread joined\n");         
+                        if (ogg_info->filename) {
+                                g_free (ogg_info->filename);
+                                ogg_info->filename = NULL; 
+                        }
+                        OGG_LOG("ogg_stop -- filename freed\n");         
+                        g_free (ogg_info);
+                        OGG_LOG("ogg_stop -- ogg_info freed\n");         
+                        ogg_info = NULL;
+                        OGG_LOG("ogg_stop -- stopped\n");         
+                }
+        }
+}
+
+void 
+ogg_seek (int time)
+{
+//	ogg_info->jump_to_time = time;
+
+//	while (ogg_info->jump_to_time != -1) {
+//		usleep(10000);
+//	}
+}
+
+void 
+ogg_pause (gboolean pause)
+{
+	esdout_pause (pause);
+}
+
+int 
+ogg_get_time (void)
+{
+	if (audio_error)
+		return -2;
+		
+	if (!ogg_info)
+		return -1;
+		
+	if (!ogg_info->going || ogg_info->eof) {
+		return -1;
+	}
+
+	return esdout_get_output_time ();
+}
diff -urNwbB nautilus/components/music/ogg.h nautilus-ogg/components/music/ogg.h
--- nautilus/components/music/ogg.h	Wed Dec 31 19:00:00 1969
+++ nautilus-ogg/components/music/ogg.h	Fri Jun 29 03:24:22 2001
@@ -0,0 +1,111 @@
+/*
+ * ogg defines 
+ * used source: musicout.h from mpegaudio package
+ */
+
+#ifndef __OGG_H__
+#define __OGG_H__
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <math.h>
+
+#include <gtk/gtk.h>
+
+/* Common includes */
+#include <ogg/ogg.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+#include <ao/ao.h>
+
+
+enum {
+        OGG_COMMENT_KEY_ARTIST, 
+        OGG_COMMENT_KEY_ALBUM, 
+        OGG_COMMENT_KEY_TITLE, 
+        OGG_COMMENT_KEY_VERSION, 
+        OGG_COMMENT_KEY_TRACKNUMBER, 
+        OGG_COMMENT_KEY_ORGANIZATION, 
+        OGG_COMMENT_KEY_GENRE, 
+        OGG_COMMENT_KEY_DESCRIPTION, 
+        OGG_COMMENT_KEY_DATE, 
+        OGG_COMMENT_KEY_LOCATION,
+        OGG_COMMENT_KEY_COPYRIGHT,
+        OGG_COMMENT_KEY_N_KEYS
+};
+
+static const char * const ogg_comment_keys[OGG_COMMENT_KEY_N_KEYS] = {
+        "ARTIST=",
+        "ALBUM=",
+        "TITLE=",
+        "VERSION=",
+        "TRACKNUMBER=",
+        "ORGANIZATION=",
+        "GENRE=",
+        "DESCRIPTION=",
+        "DATE=",
+        "LOCATION=",
+        "COPYRIGHT="
+};
+
+#define PCM_SAMPLES_BUFSIZE 4096
+
+typedef struct
+{
+  	guchar ogg_pcm_sample[PCM_SAMPLES_BUFSIZE];
+  	guchar* filename; 
+	gboolean going, paused;	
+	gint eof, jump_to_time;
+        OggVorbis_File vf;
+}
+OggPlayerInfo;
+
+void ogg_set_eq(int on, float preamp, float *band);
+void ogg_file_info_box(char *);
+
+extern OggPlayerInfo *ogg_info;
+
+void ogg_configure(void);
+
+typedef struct
+{
+	gint resolution;
+	gint channels;
+	gint downsample;
+	gint downsample_custom;
+	gint http_buffer_size;
+	gint http_prebuffer;
+	gboolean use_proxy;
+	gchar *proxy_host;
+	gint proxy_port;
+	gboolean proxy_use_auth;
+	gchar *proxy_user, *proxy_pass;
+	gboolean save_http_stream;
+	gchar *save_http_path;
+	gboolean cast_title_streaming;
+	gboolean use_udp_channel;
+	gchar *id3_format;
+	gboolean use_id3, disable_id3v2;
+	gboolean detect_by_content;
+}
+OGGConfig;
+
+extern OGGConfig ogg_cfg;
+
+void get_song_info (char *filename, char **title_real, int *len_real);
+void ogg_play_file (const char *filename);
+void ogg_stop (void);
+void ogg_seek (int time);
+void ogg_pause (gboolean pause);
+int ogg_get_time (void);
+
+#endif
diff -urNwbB nautilus/configure.in nautilus-ogg/configure.in
--- nautilus/configure.in	Thu Jun 14 09:03:43 2001
+++ nautilus-ogg/configure.in	Sat Jun 30 13:46:39 2001
@@ -613,6 +613,26 @@
 dnl =======================
 
 dnl ====================================
+dnl = Begin tests for ogg & vorbis & ao
+dnl ====================================
+
+AC_ARG_WITH(ogg, [  --with-ogg=DIR          Set where the Ogg library is located]) 
+AC_ARG_WITH(vorbis, [  --with-vorbis=DIR          Set where the Vorbis library is located]) 
+
+AM_PATH_OGG(,AC_MSG_ERROR(Ogg needed!))
+AM_PATH_VORBIS(,AC_MSG_ERROR(Vorbis needed!))
+
+if test "x$no_ogg" = x -a "x$no_vorbis" = x ; then
+	HAVE_LIBVORBIS="-DHAVE_LIBVORBIS"
+	AC_SUBST(HAVE_LIBVORBIS)
+fi
+AM_CONDITIONAL(HAVE_LIBVORBIS, test "x$HAVE_LIBVORBIS" != "x")
+
+dnl ==================================
+dnl = End tests for ogg & vorbis & ao
+dnl ==================================
+
+dnl ====================================
 dnl = Begin tests for ammonite
 dnl ====================================
 ammonite_module=`$GNOME_CONFIG --modversion ammonite 2> /dev/null | awk -F"-" '{ print $1; }'`


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