From b026b1ac697815f2bd67e11a8718478dc1d3aed6 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Tue, 28 Dec 2010 14:57:16 +0100 Subject: [PATCH] Start work on sound capabilities Compile with GStreamer libraries. Implement creation of Glk sound channel objects containing GStreamer pipelines. --- .gitignore | 3 ++ configure.ac | 12 +++++ libchimara/chimara-glk-private.h | 2 + libchimara/dispatch.c | 3 ++ libchimara/gestalt.c | 4 +- libchimara/init.c | 13 ++++- libchimara/schannel.c | 84 +++++++++++++++++++++++++++----- libchimara/schannel.h | 9 ++++ 8 files changed, 117 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 16deb0c..449d277 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ m4 missing stamp-h1 ylwrap +*.anjuta* +TODO.tasks +*~ diff --git a/configure.ac b/configure.ac index 81677cc..646c909 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/libchimara/chimara-glk-private.h b/libchimara/chimara-glk-private.h index e4f4123..6736670 100644 --- a/libchimara/chimara-glk-private.h +++ b/libchimara/chimara-glk-private.h @@ -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 */ diff --git a/libchimara/dispatch.c b/libchimara/dispatch.c index f154727..c428fbb 100644 --- a/libchimara/dispatch.c +++ b/libchimara/dispatch.c @@ -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; diff --git a/libchimara/gestalt.c b/libchimara/gestalt.c index e352909..bcd2113 100644 --- a/libchimara/gestalt.c +++ b/libchimara/gestalt.c @@ -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: diff --git a/libchimara/init.c b/libchimara/init.c index bfc67dd..b0da4c4 100644 --- a/libchimara/init.c +++ b/libchimara/init.c @@ -1,6 +1,9 @@ #include #include #include +#ifdef GSTREAMER_SOUND +#include +#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); diff --git a/libchimara/schannel.c b/libchimara/schannel.c index d8bfefc..696aaa2 100644 --- a/libchimara/schannel.c +++ b/libchimara/schannel.c @@ -1,8 +1,15 @@ +#include #include #include - +#ifdef GSTREAMER_SOUND +#include +#endif #include "magic.h" #include "schannel.h" +#include "chimara-glk-private.h" +#include "gi_dispa.h" + +extern GPrivate *glk_data_key; /** * glk_schannel_create: @@ -13,14 +20,45 @@ * 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. * - * This function is not implemented yet. - * * 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). - * - * This function is not implemented yet. */ 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. * - * This function is not implemented yet. - * * 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 Rocks. * - * This function is not implemented yet. - * * Returns: A rock value. */ glui32 glk_schannel_get_rock(schanid_t chan) { VALID_SCHANNEL(chan, return 0); - return 0; + return chan->rock; } /** diff --git a/libchimara/schannel.h b/libchimara/schannel.h index 6ec0ce3..fee87b1 100644 --- a/libchimara/schannel.h +++ b/libchimara/schannel.h @@ -1,9 +1,13 @@ #ifndef __SCHANNEL_H__ #define __SCHANNEL_H__ +#include #include #include "glk.h" #include "gi_dispa.h" +#ifdef GSTREAMER_SOUND +#include +#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 -- 2.30.2