bonobo-media and Ogg Vorbis



I took some time out today to work on Ogg Vorbis support for
bonobo-media.

My work so far is attached below (all you need to is create a 'vorbis'
directory under the stream-providers dir, and then add it to the
stream-providers/Makefile.am and to the configure.in)

There is one slight thing that is missing though. We don't actually play
any sound ;) The problem is, I'm not sure of a reliable way to output
sound. The MP3 player does not face this problem since it uses 'smpeg'
(which obviously doesn't handler vorbis). The three possible solutions I
currently see in front of me:

1) Use the 'libao' (audio output) library that is in vorbis CVS. This is
used by ogg123 and luckily has a nice "range" of plugins (i.e. you can
output to alsa, esd, or OSS (as well as solaris, IRIX, wav or NULL)).
2) I can just assume esound is installed and use that (most GNOME users
have esound)
3) I can just use the OSS device (DSP)
4) We could add some configure.in hackery and detect wether to use
esound (if its available), or to use OSS (in case esound is not
available). In reality, all I would be doing is ripping some functions
out of libao and putting them locally into the bonobo-media-vorbis.gob
file.

Any other suggestions?

Oh, you also need to make sure you have the libogg and libvorbis
libraries installed. Right now, they are hardcoded in, but I plan to add
some autoconf stuff in later to auto-detect and conditionally compile.

Regards,
Ali

P.S. If you would like this in patch format, or would just like me to
commit please tell.
GOB_FILES	= \
		bonobo-media-vorbis.gob

GOB_SOURCE	= \
		bonobo-media-vorbis.h bonobo-media-vorbis-private.h bonobo-media-vorbis.c

OAF_FILES	= bonobo-media-vorbis.oafinfo

INCLUDES	= \
		-I. \
		-I$(srcdir) -I$(top_srcdir) -I$(top_builddir) \
		-I$(includedir) \
		-I$(GNOME_CFLAGS) $(GNOME_INCLUDEDIR) \
		-I$(EXTRA_BONOBO_CFLAGS) $(EXTRA_WARNING_CFLAGS) \
		-I/usr/include/vorbis -I/usr/include/ogg # FIXME: Use autoconf

bin_PROGRAMS	= bonobo-media-vorbis

VORBIS_LIBS	= -lvorbis -logg -lvorbisfile # FIXME: Use autoconf

bonobo_media_vorbis_SOURCES = \
			$(GOB_FILES) $(GOB_SOURCE) \
			bonobo-media-vorbis-factory.c

bonobo_media_vorbis_LDADD = \
			$(EXTRA_GNOME_LIBS) $(EXTRA_BONOBO_LIBS) \
			-lpthread \
			$(VORBIS_LIBS) \
			$(top_builddir)/bonobo-media/libbonobo-media.la

.c %.h %-private.h: $(srcdir)/%.gob
	@GOB@ $<

oafdir			= $(datadir)/oaf
oaf_DATA		= $(OAF_FILES)



BUILT_SOURCES           = $(GOB_SOURCE)
CLEANFILES              += $(BUILT_SOURCES)
/* bonobo-media-vorbis-factry: Factory for Ogg Vorbis player using the
 * Bonobo:Media interfaces
 *
 * Copyright (C) 2001 Ali Abdin <aliabdin aucegypt edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#include <gnome.h>
#include <bonobo.h>
#include <liboaf/liboaf.h>
#include "bonobo-media-vorbis.h"

static BonoboObject* vorbis_factory (BonoboGenericFactory *factory,
				     gpointer user_data)
{
	return BONOBO_OBJECT (bonobo_media_vorbis_new ());
}

static void init_bonobo (int argc, char **argv)
{
	CORBA_ORB orb;

	gnome_init_with_popt_table ("bonobo-media-vorbis", "0.0",
				    argc, argv,
				    oaf_popt_options, 0, NULL);

	orb = oaf_init (argc, argv);

	if (bonobo_init (orb, NULL, NULL) == FALSE)
		g_error ("Could not initialize Bonobo");
}

static void last_unref_cb (BonoboObject *bonobo_object,
			   BonoboGenericFactory *factory)
{
	bonobo_object_unref (BONOBO_OBJECT (factory));
	gtk_main_quit ();
}

int main (int argc, char **argv)
{
	BonoboGenericFactory *factory;

	init_bonobo (argc, argv);

	factory = bonobo_generic_factory_new (
			"OAFIID:Bonobo_Media_Vorbis_Factory",
			vorbis_factory, NULL);

	gtk_signal_connect (GTK_OBJECT (bonobo_context_running_get ()), "last_unref",
			    GTK_SIGNAL_FUNC (last_unref_cb), factory);

	bonobo_main ();

	return 0;
}
/* vim: set syntax=c: */
%at{
 /* bonobo-media-vorbis: Ogg Vorbis player using the Bonobo:Meida interfaces
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Copyright (c) 2001  Ali Abdin <aliabdin aucegypt edu>
 * Based HEAVILY on bonobo-media-smpeg.gob by ÉRDI Gergõ <cactus cactus rulez org>
 */
%}

%header{
#include <bonobo/bonobo-persist-file.h>
#include "bonobo-media/bonobo-media-stream.h"
%}

%privateheader{
#include <vorbis/vorbisfile.h>
%}

%{
#include <bonobo/bonobo-exception.h>
#include <bonobo-media/bonobo-media-audio.h>

#include <bonobo-media/bonobo-media-stream-private.h>
%}

class Bonobo:Media:Vorbis from Bonobo:Media:Stream
{
	private gint 		length;
	private gchar 		*filename destroywith g_free;
	private OggVorbis_File 	vorbis_file;
	private gint		current_pos;
	
	private guint timeout_id
		destroy
		{
			if (VAR)
				gtk_timeout_remove (VAR);
		} = 0;

	private gboolean update_position (self)
		{
			gint current_time;
			
			current_time = (int)ov_time_tell (&self->_priv->vorbis_file);
			
			bonobo_media_stream_send_pos_notification (
				BONOBO_MEDIA_STREAM (self),
				current_time);
				
			if (current_time == self->_priv->length)
				bonobo_media_stream_send_end_notification (
					BONOBO_MEDIA_STREAM (self));
			
			return TRUE;
		}
	
	override (Bonobo:Media:Stream)
		gfloat get_pos_per_sec (BonoboMediaStream *media_stream,
				       CORBA_Environment *ev)
		{
			Self *self = SELF (media_stream);
			gfloat ratio;

			/* ratio (from bonobo-media-smpeg.gob) is the bitrate? */
			ratio = (gfloat)ov_bitrate (&self->_priv->vorbis_file, -1);
			printf ("Ratio:\t%f\n", ratio);

			return ratio;
		}

	override (Bonobo:Media:Stream)
		gint get_length (BonoboMediaStream *media_stream,
				 CORBA_Environment *ev)
		{
			return SELF (media_stream)->_priv->length;
		}
		
	override (Bonobo:Media:Stream)
		void seek (BonoboMediaStream *media_stream,
			   gint pos,
			   CORBA_Environment *ev)
		{
			gint seek_success;
			BonoboMediaVorbis *self = SELF (media_stream);

			if (pos < 0 || pos > self->_priv->length) {
				CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
						     ex_Bonobo_Media_Stream_InvalidPosition,
						     NULL);
				return;
			}

			seek_success = ov_time_seek (&self->_priv->vorbis_file, pos);
			if (!seek_success) {
				CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
						     ex_Bonobo_Media_Stream_InvalidPosition,
						     NULL);
				return;
			}
			update_position (self);
		}

	override (Bonobo:Media:Stream)
		void play (BonoboMediaStream *media_stream,
			   CORBA_Environment *ev)
		{
			BonoboMediaVorbis *self = SELF (media_stream);

			/* FIXME: Implement audio output - in
			 * bonobo-media-smpeg.gob they use SMPEG_play */
			 g_print ("Playing");
			
			if (!self->_priv->timeout_id)
				self->_priv->timeout_id = 
					gtk_timeout_add (100,
						(GtkFunction)update_position,
						self);
		}

	override (Bonobo:Media:Stream)
		void stop (BonoboMediaStream *media_stream,
			   CORBA_Environment *ev)
		{
			BonoboMediaVorbis *self = SELF (media_stream);
			
			/* FIXME: Stop audio output here */
			g_print ("Stopping");

			if (self->_priv->timeout_id)
				gtk_timeout_remove (self->_priv->timeout_id);
				
			self->_priv->timeout_id = 0;
		}
		
	private void volume_cb (GtkObject *obj, gfloat vol,
				Bonobo:Media:Vorbis *self (check null type))
		{
			printf ("Volume changed to %f\n", vol);
		}
	
	private void read_file_info (self)
		{	
			self->_priv->length = (int)ov_time_total(&self->_priv->vorbis_file,-1);
		}

	public gint PersistFile_load (BonoboPersistFile   *pf,
				      const CORBA_char    *filename,
				      CORBA_Environment   *ev,
				      Bonobo:Media:Vorbis *self (check null type))
		{
			load_file (self, filename);
			
			return 0;
		}

	public gint PersistFile_save (BonoboPersistFile   *pf,
				      const CORBA_char    *filename,
				      CORBA_Environment   *ev,
				      Bonobo:Media:Vorbis *self (check null type))
		{
			CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
					     ex_Bonobo_NotSupported, NULL);
			return 0;
		}
	
	public void load_file (self, const gchar *filename)
		{
			FILE *thefile;
			gint open_succ;
			
			if (self->_priv->filename)
				g_free (self->_priv->filename);
			if (self->_priv->timeout_id)
				gtk_timeout_remove (self->_priv->timeout_id);
			if (&self->_priv->vorbis_file)
				ov_clear (&self->_priv->vorbis_file);
			
			self->_priv->filename = g_strdup (filename);
			
			thefile = fopen (filename, "rb");
			open_succ = ov_open (thefile, &self->_priv->vorbis_file, NULL, 0);
			if (open_succ < 0) {
         	       		/* This is unpredictable - We should return an
				 * exception or something*/
                		fclose(thefile);
                		g_assert ("Ack! We passed a non-Ogg Vorbis file!!!");
			}

			read_file_info (self);
		}

	private void construct (self)
		{
			Bonobo_Media_Stream corba_stream;
			BonoboMediaAudio *audio;
			BonoboPersistFile *pf;
			
			corba_stream = bonobo_media_stream_corba_object_create (BONOBO_OBJECT (self));

			audio = bonobo_media_audio_new ();
			gtk_signal_connect (GTK_OBJECT (audio), "volume_changed", 
					    (GtkSignalFunc) bonobo_media_vorbis_volume_cb, self);
			bonobo_object_add_interface (BONOBO_OBJECT (self),
						     BONOBO_OBJECT (audio));

			pf = bonobo_persist_file_new (
				(BonoboPersistFileIOFn) PersistFile_load,
				(BonoboPersistFileIOFn) PersistFile_save,
				self);
			bonobo_object_add_interface (BONOBO_OBJECT (self),
						     BONOBO_OBJECT (pf));

			bonobo_media_stream_construct (BONOBO_MEDIA_STREAM (self), corba_stream);
		}

	public Bonobo:Media:Vorbis* new_from_file (const gchar *filename)
		{
			Self *self;

			self = bonobo_media_vorbis_new ();

			construct (self);
			load_file (self, filename);

			return self;
		}

	public Bonobo:Media:Vorbis* new (void)
		{
			Self *self;
			
			self = GET_NEW;
			
			construct (self);

			return self;
		}
}
<oaf_info>
<oaf_server iid="OAFIID:Bonobo_Media_Vorbis_Factory" type="exe" location="bonobo-media-vorbis">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/GenericFactory:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Bonobo Media Ogg Vorbis player factory"/>
<oaf_attribute name="description" type="string" value="Bonobo Media Ogg Vorbis player factory"/>
</oaf_server>

<oaf_server iid="OAFIID:Bonobo_Media_Vorbis" type="factory" location="OAFIID:Bonobo_Media_Vorbis_Factory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/Unknown:1.0"/>
<item value="IDL:Bonobo/Media/Stream:1.0"/>
<item value="IDL:Bonobo/Media/Audio:1.0"/>
<item value="IDL:Bonobo/PersistFile:1.0"/>
<item value="IDL:Bonobo/Persist:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Bonobo Media Ogg Vorbis component"/>
<oaf_attribute name="description" type="string" value="Bonobo Media component for playing back Ogg
Vorbis files (uses libogg/libvorbis/libao as the backend)"/>
<oaf_attribute name="bonobo:editable" type="boolean" value="false"/>
<oaf_attribute name="bonobo:supported_mime_types" type="stringv">
<item value="application/x-ogg"/>
</oaf_attribute>
</oaf_server>

</oaf_info>


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