<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40582 >
Hello all, I tried to make a GStreamer audio plugin for Freeciv. It's a work in progress but it already works well. It's my first contribution so, please let me know if there are any rules I break. I'm working on a Linux machine so I didn't test this on other platforms but because GStreamer can run on all the other supported platforms it should not be a problem I think. Gr, Thijs
--- client/Makefile.am | 20 ++++- client/audio.c | 17 ++++- client/audio_gst.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++ client/audio_gst.h | 18 +++++ configure.ac | 13 +++ 5 files changed, 240 insertions(+), 8 deletions(-) --- freeciv.orig/client/Makefile.am +++ freeciv/client/Makefile.am @@ -33,11 +33,17 @@ AUDIO_SDL_FILES=$(ALL_AUDIO_SDL_FILES) endif +ALL_AUDIO_GST_FILES=audio_gst.c audio_gst.h + +if AUDIO_GST +AUDIO_GST_FILES=$(ALL_AUDIO_GST_FILES) +endif + if MINGW32 CLIENTICON=../win32/clienticon.o endif -EXTRA_DIST= $(ALL_AUDIO_SDL_FILES) +EXTRA_DIST= $(ALL_AUDIO_SDL_FILES) $(ALL_AUDIO_GST_FILES) ## This is usually false, so "include" is not recursed into ## by 'make', but it can be enabled in configure, and it is @@ -53,9 +59,10 @@ bin_PROGRAMS = civclient -AM_CPPFLAGS = -I$(top_srcdir)/utility -I$(srcdir)/include -I$(top_srcdir)/common -I$(top_srcdir)/common/aicore -I$(srcdir)/agents $(CLIENT_CFLAGS) $(SOUND_CFLAGS) $(LIBGGZ_INCLUDES) $(GGZMOD_INCLUDES) $(GGZ_GTK_INCLUDES) +AM_CPPFLAGS = -I$(top_srcdir)/utility -I$(srcdir)/include -I$(top_srcdir)/common -I$(top_srcdir)/common/aicore -I$(srcdir)/agents $(CLIENT_CFLAGS) $(SOUND_CFLAGS) $(LIBGGZ_INCLUDES) $(GGZMOD_INCLUDES) $(GGZ_GTK_INCLUDES) $(GSTREAMER_CFLAGS) civclient_SOURCES = $(AUDIO_SDL_FILES) \ + $(AUDIO_GST_FILES) \ attribute.h \ attribute.c \ citydlg_common.c \ @@ -114,9 +121,9 @@ themes_common.h \ tilespec.c \ tilespec.h \ - audio.c \ - audio.h \ - audio_none.c \ + audio.c \ + audio.h \ + audio_none.c \ audio_none.h # packhand_gen.c & packhand_gen.h are generated files, but as they are @@ -132,7 +139,8 @@ $(gui_sources)/libguiclient.a civclient_DEPENDENCIES = $(fc_civclient_libs) civclient_LDADD = $(fc_civclient_libs) $(fc_civclient_libs) \ - $(INTLLIBS) $(CLIENT_LIBS) $(SOUND_LIBS) $(LIB_GGZMOD) $(CLIENTICON) + $(INTLLIBS) $(CLIENT_LIBS) $(SOUND_LIBS) $(LIB_GGZMOD) $(CLIENTICON) \ + $(GSTREAMER_LIBS) desktopfiledir = $(prefix)/share/applications desktopfile_DATA = \ freeciv.desktop --- freeciv.orig/client/audio.c +++ freeciv/client/audio.c @@ -29,13 +29,18 @@ #include "support.h" #include "audio_none.h" + +#ifdef AUDIO_GST +#include "audio_gst.h" +#endif + #ifdef AUDIO_SDL #include "audio_sdl.h" #endif #include "audio.h" -#define MAX_NUM_PLUGINS 2 +#define MAX_NUM_PLUGINS 3 #define SNDSPEC_SUFFIX ".soundspec" /* keep it open throughout */ @@ -142,6 +147,10 @@ assert(num_plugins_used == 1); selected_plugin = 0; +#ifdef AUDIO_GST + audio_gst_init (); +#endif + #ifdef AUDIO_SDL audio_sdl_init(); #endif @@ -248,8 +257,12 @@ return; } +#ifdef AUDIO_GST + if (audio_select_plugin ("gst")) return; +#endif + #ifdef AUDIO_SDL - if (audio_select_plugin("sdl")) return; + if (audio_select_plugin("sdl")) return; #endif freelog(LOG_NORMAL, _("No real audio subsystem managed to initialize!")); freelog(LOG_NORMAL, --- /dev/null +++ freeciv/client/audio_gst.c @@ -0,0 +1,180 @@ +/********************************************************************** + Freeciv - Copyright (C) 2008 Thijs Vermeir <[EMAIL PROTECTED]> + 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#include "support.h" + +#include "audio.h" +#include "gui_main_g.h" + +#include "audio_gst.h" + +#include <gst/gst.h> + +static void my_stop(void); +static void my_wait(void); + +GstElement *pipeline; +GstElement *playbin; +gchar *last_fullpath; +GMutex *audio_lock; + +static void my_shutdown(void) +{ + GstState new_state; + GstStateChangeReturn ret; + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); + gst_element_get_state (pipeline, &new_state, NULL, GST_CLOCK_TIME_NONE); + + gst_object_unref (pipeline); + gst_object_unref (playbin); + if (last_fullpath) + g_free (last_fullpath); + if (audio_lock) + g_mutex_free (audio_lock); +} + +static void my_stop(void) +{ + g_mutex_lock (audio_lock); + gst_element_set_state (pipeline, GST_STATE_READY); + g_mutex_unlock (audio_lock); +} + +static void my_wait(void) +{ + GstState new_state; + GstStateChangeReturn ret; + + g_mutex_lock (audio_lock); + ret = gst_element_get_state (pipeline, &new_state, NULL, GST_CLOCK_TIME_NONE); + while (ret == GST_STATE_CHANGE_SUCCESS && new_state == GST_STATE_PLAYING) { + ret = gst_element_get_state (pipeline, &new_state, NULL, GST_CLOCK_TIME_NONE); + } + g_mutex_unlock (audio_lock); +} + +static bool my_play(const char *const tag, const char *const fullpath, + bool repeat) +{ + if (fullpath) { + gboolean last_fullpath_changed = FALSE; + GstState new_state; + GstStateChangeReturn ret; + + g_mutex_lock (audio_lock); + + if (!last_fullpath || g_strcmp0 (fullpath, last_fullpath) != 0) { + if (last_fullpath) + g_free (last_fullpath); + last_fullpath = g_strdup (fullpath); + gchar *full_uri = g_strdup_printf ("file://%s", fullpath); + g_object_set (G_OBJECT (playbin), "uri", full_uri, NULL); + g_free (full_uri); + last_fullpath_changed = TRUE; + } + + ret = gst_element_get_state (pipeline, &new_state, NULL, GST_CLOCK_TIME_NONE); + if (ret != GST_STATE_CHANGE_SUCCESS) + goto no_change_succes; + + if (new_state != GST_STATE_PAUSED || new_state != GST_STATE_PLAYING || + last_fullpath_changed) { + gst_element_set_state (pipeline , GST_STATE_READY); + ret = gst_element_get_state (pipeline, &new_state, NULL, GST_CLOCK_TIME_NONE); + if (ret != GST_STATE_CHANGE_SUCCESS) + goto no_change_succes; + + gst_element_set_state (pipeline , GST_STATE_PAUSED); + ret = gst_element_get_state (pipeline, &new_state, NULL, GST_CLOCK_TIME_NONE); + if (ret != GST_STATE_CHANGE_SUCCESS) + goto no_change_succes; + + } + gst_element_seek_simple (pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, 0 * GST_SECOND); + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + +no_change_succes: + g_mutex_unlock (audio_lock); + return TRUE; + } + + return FALSE; +} + +static void +message_cb (GstBus *bus, GstMessage *message, gpointer user_data) { + + g_mutex_lock (audio_lock); + switch (GST_MESSAGE_TYPE (message)) { + default: + break; + } + g_mutex_unlock (audio_lock); +} + +static bool my_init(void) +{ + GstBus *bus; + + pipeline = gst_pipeline_new ("freeciv_pipeline"); + playbin = gst_element_factory_make ("playbin", NULL); + gst_object_ref (playbin); + gst_bin_add (GST_BIN (pipeline), playbin); + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + + gst_bus_add_signal_watch (bus); + g_signal_connect (bus, "message", (GCallback) message_cb, + NULL); + + last_fullpath = NULL; + audio_lock = g_mutex_new (); + + gst_object_unref (bus); + + return TRUE; +} + +static void my_set_volume (double volume) { + g_object_set (G_OBJECT (playbin), "volume", volume, NULL); +} + +static double my_get_volume (void) { + double temp; + g_object_get (G_OBJECT (playbin), "volume", &temp, NULL); + return temp; +} + +void audio_gst_init(void) +{ + gst_init (NULL, NULL); + + struct audio_plugin self; + + sz_strlcpy(self.name, "gst"); + sz_strlcpy(self.descr, "GStreamer audio plugin"); + self.init = my_init; + self.shutdown = my_shutdown; + self.stop = my_stop; + self.wait = my_wait; + self.play = my_play; + self.get_volume = my_get_volume; + self.set_volume = my_set_volume; + audio_add_plugin(&self); +} --- /dev/null +++ freeciv/client/audio_gst.h @@ -0,0 +1,18 @@ +/********************************************************************** + Freeciv - Copyright (C) 2008 - Thijs Vermeir <[EMAIL PROTECTED]> + 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. +***********************************************************************/ +#ifndef FC__AUDIO_GST_H +#define FC__AUDIO_GST_H + +void audio_gst_init(void); + +#endif /* FC__AUDIO_GST_H */ --- freeciv.orig/configure.ac +++ freeciv/configure.ac @@ -566,6 +566,16 @@ AC_CHECK_FUNCS([chdir mkdtemp]) fi +dnl Check for GStreamer +PKG_CHECK_MODULES(GSTREAMER, + gstreamer-0.10, + HAVE_GST="yes", + HAVE_GST="no") + +if test "x$HAVE_GST" = "xyes" ; then + AC_DEFINE(AUDIO_GST, 1, [Enable GStreamer audio]) +fi + AC_SUBST(gui_sources) AC_SUBST(CLIENT_CFLAGS) AC_SUBST(CLIENT_CXXFLAGS) @@ -577,7 +587,10 @@ AC_SUBST([VERSION_WITHOUT_LABEL]) AC_SUBST([VERSION_LABEL]) AC_SUBST([HOST_PATH_SEPARATOR]) +AC_SUBST(GSTREAMER_CFLAGS) +AC_SUBST(GSTREAMER_LIBS) AM_CONDITIONAL(AUDIO_SDL, test "x$SDL_mixer" = "xyes") +AM_CONDITIONAL(AUDIO_GST, test "x$HAVE_GST" = "xyes") AM_CONDITIONAL(CLIENT_GUI_SDL, test "$gui_sources" = "gui-sdl") AM_CONDITIONAL(CLIENT_GUI_GTK_2_0, test "$gui_sources" = "gui-gtk-2.0") AM_CONDITIONAL(CLIENT_GUI_XAW, test "$gui_sources" = "gui-xaw")
_______________________________________________ Freeciv-dev mailing list Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev