Start work on sound capabilities
authorPhilip Chimento <philip.chimento@gmail.com>
Tue, 28 Dec 2010 13:57:16 +0000 (14:57 +0100)
committerPhilip Chimento <philip.chimento@gmail.com>
Tue, 28 Dec 2010 13:57:16 +0000 (14:57 +0100)
Compile with GStreamer libraries. Implement creation of Glk sound
channel objects containing GStreamer pipelines.

.gitignore
configure.ac
libchimara/chimara-glk-private.h
libchimara/dispatch.c
libchimara/gestalt.c
libchimara/init.c
libchimara/schannel.c
libchimara/schannel.h

index 16deb0cbb4a87350346d3e9efbb59cee66e45cab..449d2775b1bc0299ed9e52775a823ee9bc330053 100644 (file)
@@ -19,3 +19,6 @@ m4
 missing
 stamp-h1
 ylwrap
+*.anjuta*
+TODO.tasks
+*~
index 81677ccaf92e1936506ca3e593179a373bbdea2f..646c9097c0f5659f03c576189c17f9b7f97b96bc 100644 (file)
@@ -105,6 +105,17 @@ AC_ARG_ENABLE([rpm],
 )
 AM_CONDITIONAL([BUILDING_RPM], [$TEST "x$rpm" = xtrue])
 
+### SOUND LIBRARY TO USE ######################################################
+
+AC_ARG_WITH([gstreamer],
+       [AS_HELP_STRING([--without-gstreamer], [Disable GStreamer sound])],
+       [],
+       [with_gstreamer=yes])
+SOUND_MODULE=
+AS_IF([$TEST "x$with_gstreamer" != xno], 
+       [AC_DEFINE([GSTREAMER_SOUND], [1], [Define to enable sound support with GStreamer])
+       SOUND_MODULE=gstreamer-0.10])
+
 ### CHECK FOR LIBRARIES #######################################################
 
 # Libraries needed to build Chimara library
@@ -114,6 +125,7 @@ PKG_CHECK_MODULES([CHIMARA], [
        gthread-2.0 
        gmodule-2.0
        pango
+       $SOUND_MODULE
 ])
 CHIMARA_LIBS="$CHIMARA_LIBS -lm"
 AC_SUBST(CHIMARA_LIBS)
index e4f4123f5a00e9bd8dc00ed3817532a78718d456..67366707f92af252c0354a97e5dc08041a934ec7 100644 (file)
@@ -83,6 +83,8 @@ struct _ChimaraGlkPrivate {
     strid_t current_stream;
     /* List of streams currently in existence */
     GList *stream_list;
+       /* List of sound channels currently in existence */
+       GList *schannel_list;
        /* Current timer */
        guint timer_id;
        /* Current resource blorb map */
index f15472750d12de0518c488330fcf0ca6448e9b54..c428fbb7e4a39943f13b0e7047b92cdf2478f93d 100644 (file)
@@ -3,6 +3,7 @@
 #include "window.h"
 #include "stream.h"
 #include "fileref.h"
+#include "schannel.h"
 
 extern GPrivate *glk_data_key;
 
@@ -117,6 +118,8 @@ gidispatch_get_objrock(void *obj, glui32 objclass)
                        return ((strid_t)obj)->disprock;
                case gidisp_Class_Fileref:
                        return ((frefid_t)obj)->disprock;
+               case gidisp_Class_Schannel:
+                       return ((schanid_t)obj)->disprock;
                default: 
                {
                        gidispatch_rock_t dummy;
index e3529094233d4f88cf055abc7af0023b76562421..bcd2113c6608381e1fedd5a3d9513f75f323de65 100644 (file)
@@ -124,9 +124,11 @@ glk_gestalt_ext(glui32 sel, glui32 val, glui32 *arr, glui32 arrlen)
 
                case gestalt_GraphicsTransparency:
                        return 1;
+
+               case gestalt_Sound:
+                       return 1;
                        
                /* Unsupported capabilities */
-               case gestalt_Sound:
                case gestalt_SoundVolume:
                case gestalt_SoundNotify:
                case gestalt_SoundMusic:
index bfc67dd033bb4d994a9d2fc9cb21c29ea89c228f..b0da4c435947186794551f36dedf71d4697b71aa 100644 (file)
@@ -1,6 +1,9 @@
 #include <config.h>
 #include <glib.h>
 #include <glib/gi18n-lib.h>
+#ifdef GSTREAMER_SOUND
+#include <gst/gst.h>
+#endif
 
 static gboolean chimara_initialized = FALSE;
 
@@ -21,7 +24,15 @@ chimara_init(void)
                                " the thread system by calling g_threads_init() and "
                                "gdk_threads_init() BEFORE the initial call to gtk_init() in "
                                "your main program."));
-               
+
+#ifdef GSTREAMER_SOUND
+               /* Make sure GStreamer has been initialized if it hasn't been already;
+               in particular, if you want your program to parse GStreamer command line
+               options then you should do it yourself, before gtk_init(). */
+               if( !gst_is_initialized() )
+                       gst_init(NULL, NULL);
+#endif
+
                /* Initialize thread-private data */
                extern GPrivate *glk_data_key;
                glk_data_key = g_private_new(NULL);
index d8bfefc9945b685828f5e33033d923a8b4f0a5c2..696aaa2a7351f225ea9a009e44c1d0e3741d43f4 100644 (file)
@@ -1,8 +1,15 @@
+#include <config.h>
 #include <glib.h>
 #include <libchimara/glk.h>
-
+#ifdef GSTREAMER_SOUND
+#include <gst/gst.h>
+#endif
 #include "magic.h"
 #include "schannel.h"
+#include "chimara-glk-private.h"
+#include "gi_dispa.h"
+
+extern GPrivate *glk_data_key;
 
 /**
  * glk_schannel_create:
  * Remember that it is possible that the library will be unable to create a new
  * channel, in which case glk_schannel_create() will return %NULL.
  *
- * <warning><para>This function is not implemented yet.</para></warning>
- *
  * Returns: A new sound channel, or %NULL.
  */
 schanid_t 
 glk_schannel_create(glui32 rock)
 {
+#ifdef GSTREAMER_SOUND
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+
+       schanid_t s = g_new0(struct glk_schannel_struct, 1);
+       s->magic = MAGIC_SCHANNEL;
+       s->rock = rock;
+       if(glk_data->register_obj)
+               s->disprock = (*glk_data->register_obj)(s, gidisp_Class_Schannel);
+
+       /* Add it to the global sound channel list */
+       glk_data->schannel_list = g_list_prepend(glk_data->schannel_list, s);
+       s->schannel_list = glk_data->schannel_list;
+
+       /* Create a GStreamer pipeline for the sound channel */
+       gchar *pipeline_name = g_strdup_printf("pipeline-%p", s);
+       s->pipeline = gst_pipeline_new(pipeline_name);
+       g_free(pipeline_name);
+
+       /* Create GStreamer elements to put in the pipeline */
+       s->source = gst_element_factory_make("fakesrc", NULL);
+       s->filter = gst_element_factory_make("identity", NULL);
+       s->sink = gst_element_factory_make("fakesink", NULL);
+       gst_bin_add_many(GST_BIN(s->pipeline), s->source, s->filter, s->sink, NULL);
+       if(!gst_element_link_many(s->source, s->filter, s->sink, NULL))
+               goto fail;
+       
+       return s;
+
+fail:
+       glk_schannel_destroy(s);
        return NULL;
+#else
+       return NULL;
+#endif /* GSTREAMER_SOUND */
 }
 
 /**
@@ -29,13 +67,27 @@ glk_schannel_create(glui32 rock)
  *
  * Destroys the channel. If the channel is playing a sound, the sound stops 
  * immediately (with no notification event).
- *
- * <warning><para>This function is not implemented yet.</para></warning>
  */
 void 
 glk_schannel_destroy(schanid_t chan)
 {
        VALID_SCHANNEL(chan, return);
+
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       
+       glk_data->schannel_list = g_list_delete_link(glk_data->schannel_list, chan->schannel_list);
+
+       if(glk_data->unregister_obj)
+       {
+               (*glk_data->unregister_obj)(chan, gidisp_Class_Schannel, chan->disprock);
+               chan->disprock.ptr = NULL;
+       }
+       
+       if(chan->pipeline)
+               g_object_unref(chan->pipeline);
+       
+       chan->magic = MAGIC_FREE;
+       g_free(chan);
 }
 
 /**
@@ -50,15 +102,27 @@ glk_schannel_destroy(schanid_t chan)
  * As that section describes, the order in which channels are returned is 
  * arbitrary.
  *
- * <warning><para>This function is not implemented yet.</para></warning>
- *
  * Returns: the next sound channel, or %NULL if there are no more.
  */
 schanid_t 
 glk_schannel_iterate(schanid_t chan, glui32 *rockptr)
 {
        VALID_SCHANNEL_OR_NULL(chan, return NULL);
-       return NULL;
+
+       ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+       GList *retnode;
+       
+       if(chan == NULL)
+               retnode = glk_data->schannel_list;
+       else
+               retnode = chan->schannel_list->next;
+       schanid_t retval = retnode? (schanid_t)retnode->data : NULL;
+               
+       /* Store the sound channel's rock in rockptr */
+       if(retval && rockptr)
+               *rockptr = glk_schannel_get_rock(retval);
+               
+       return retval;
 }
 
 /**
@@ -68,15 +132,13 @@ glk_schannel_iterate(schanid_t chan, glui32 *rockptr)
  * Retrieves the channel's rock value. See <link 
  * linkend="chimara-Rocks">Rocks</link>.
  *
- * <warning><para>This function is not implemented yet.</para></warning>
- *
  * Returns: A rock value.
  */
 glui32 
 glk_schannel_get_rock(schanid_t chan)
 {
        VALID_SCHANNEL(chan, return 0);
-       return 0;
+       return chan->rock;
 }
 
 /**
index 6ec0ce31e7e6daec57a23428d0eb97819fca1d66..fee87b1c577ad7feeb56f9324f787289f8ef8e45 100644 (file)
@@ -1,9 +1,13 @@
 #ifndef __SCHANNEL_H__
 #define __SCHANNEL_H__
 
+#include <config.h>
 #include <glib.h>
 #include "glk.h"
 #include "gi_dispa.h"
+#ifdef GSTREAMER_SOUND
+#include <gst/gst.h>
+#endif
 
 struct glk_schannel_struct
 {
@@ -13,6 +17,11 @@ struct glk_schannel_struct
        /* Pointer to the list node in the global sound channel list that contains 
         this sound channel */
        GList *schannel_list;
+
+#ifdef GSTREAMER_SOUND
+       /* Each sound channel is represented as a GStreamer pipeline.  */
+       GstElement *pipeline, *source, *filter, *sink;
+#endif
 };
 
 #endif
\ No newline at end of file