Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYves Combe <ycombe@src.gnome.org>2006-11-29 22:36:20 (GMT)
committer Yves Combe <ycombe@src.gnome.org>2006-11-29 22:36:20 (GMT)
commitca72d79e5237bdecab78bcc20225242488ea1e8f (patch)
treee7ced9d2c038cb56788eabb8a9079aba43a2e887
parent33cfc959568035ec0cfd0088821cc99ad8ef64a9 (diff)
Rewrite gc_sound without gob (in C).
-rw-r--r--ChangeLog70
-rw-r--r--src/gc_sound/ChangeLog69
-rw-r--r--src/gc_sound/aclocal.m454
-rw-r--r--src/gc_sound/configure.in6
-rw-r--r--src/gc_sound/src/Makefile.am47
-rw-r--r--src/gc_sound/src/gc-sound-channel.c290
-rw-r--r--src/gc_sound/src/gc-sound-channel.gob321
-rw-r--r--src/gc_sound/src/gc-sound-channel.h104
-rw-r--r--src/gc_sound/src/gc-sound-item.c421
-rw-r--r--src/gc_sound/src/gc-sound-item.gob310
-rw-r--r--src/gc_sound/src/gc-sound-item.h104
-rw-r--r--src/gc_sound/src/gc-sound-marshallers.c56
-rw-r--r--src/gc_sound/src/gc-sound-marshallers.h21
-rw-r--r--src/gc_sound/src/gc-sound-mixer-SDL.c456
-rw-r--r--src/gc_sound/src/gc-sound-mixer-SDL.h110
-rw-r--r--src/gc_sound/src/gc-sound-mixer-private.h52
-rw-r--r--src/gc_sound/src/gc-sound-mixer.c125
-rw-r--r--src/gc_sound/src/gc-sound-mixer.gob156
-rw-r--r--src/gc_sound/src/gc-sound-mixer.h97
-rw-r--r--src/gc_sound/src/gc-sound.h1
-rw-r--r--src/gc_sound/src/marshallers.list3
-rw-r--r--src/gc_sound/src/test_gc_sound.c78
22 files changed, 2126 insertions, 825 deletions
diff --git a/ChangeLog b/ChangeLog
index 6e8e082..37dbaa9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,73 @@
+2006-11-29 Yves Combe <yves@ycombe.net>
+
+ Rewrite gc_sound without gob (in C).
+ Architecture change:
+ - GCSoundMixer is an interface. GCSoundMixerSDL just implement it.
+ That to allow change libsdl dependencie to gstreamer when needed.
+ - GCSoundChannel and GCSoundItem just uses GCSoundMixer interface to run.
+
+ TODO:
+ - object_ref is not correct.
+ - python binding.
+ - add a record capability in interface (for now SDL_mixer can not do it).
+ - future way. add a gstreamer implementation of interface.
+
+ * aclocal.m4:
+ * configure.in:
+ * src/gc_sound/src/Makefile.am:
+ * src/gc_sound/src/gc-sound-channel.c: (gc_sound_channel_play_item),
+ (gc_sound_channel_get_root), (gc_sound_channel_pause),
+ (gc_sound_channel_resume), (gc_sound_channel_halt),
+ (gc_sound_channel_get_policy), (gc_sound_channel_set_policy),
+ (gc_sound_channel_play), (gc_sound_channel_init),
+ (gc_sound_channel_get_property), (gc_sound_channel_set_property),
+ (gc_sound_channel_signal_chunk_end), (gc_sound_channel_signal_run),
+ (gc_sound_channel_class_init):
+ * src/gc_sound/src/gc-sound-channel.gob:
+ * src/gc_sound/src/gc-sound-channel.h:
+ * src/gc_sound/src/gc-sound-item.c: (gc_sound_item_run_next),
+ (gc_sound_item_set_loop), (gc_sound_item_get_policy),
+ (gc_sound_item_set_policy), (gc_sound_item_child_start),
+ (gc_sound_item_child_end), (gc_sound_item_append_child),
+ (gc_sound_item_play), (gc_sound_item_set_filename),
+ (gc_sound_item_get_filename), (gc_sound_item_signal_real_play),
+ (gc_sound_item_signal_play_end), (gc_sound_item_signal_play_start),
+ (gc_sound_item_signal_chunk_end),
+ (gc_sound_item_signal_chunk_start), (gc_sound_item_init),
+ (gc_sound_item_get_property), (gc_sound_item_set_property),
+ (gc_sound_item_class_init):
+ * src/gc_sound/src/gc-sound-item.gob:
+ * src/gc_sound/src/gc-sound-item.h:
+ * src/gc_sound/src/gc-sound-marshallers.c:
+ * src/gc_sound/src/gc-sound-marshallers.h:
+ * src/gc_sound/src/gc-sound-mixer-SDL.c: (gc_sound_mixer_SDL_new),
+ (gc_sound_mixer_SDL_open_audio), (gc_sound_mixer_SDL_close_audio),
+ (gc_sound_mixer_SDL_new_channel), (gc_sound_mixer_SDL_pause),
+ (gc_sound_mixer_SDL_resume), (gc_sound_mixer_SDL_halt),
+ (gc_sound_mixer_SDL_pause_channel),
+ (gc_sound_mixer_SDL_resume_channel),
+ (gc_sound_mixer_SDL_halt_channel), (gc_sound_mixer_SDL_play_item),
+ (channel_finished_cb), (gc_sound_mixer_SDL_channel_finished),
+ (gc_sound_mixer_SDL_init), (gc_sound_mixer_SDL_finalize),
+ (gc_sound_mixer_SDL_get_property),
+ (gc_sound_mixer_SDL_set_property), (gc_sound_mixer_SDL_class_init),
+ (gc_init_sound_mixer):
+ * src/gc_sound/src/gc-sound-mixer-SDL.h:
+ * src/gc_sound/src/gc-sound-mixer-private.h:
+ * src/gc_sound/src/gc-sound-mixer.c: (gc_sound_mixer_open_audio),
+ (gc_sound_mixer_close_audio), (gc_sound_mixer_new_channel),
+ (gc_sound_mixer_pause), (gc_sound_mixer_resume),
+ (gc_sound_mixer_halt), (gc_sound_mixer_pause_channel),
+ (gc_sound_mixer_resume_channel), (gc_sound_mixer_halt_channel),
+ (gc_sound_mixer_play_item), (gc_sound_mixer_get_type),
+ (_gc_sound_mixer_install_property), (gc_sound_mixer_iface_init):
+ * src/gc_sound/src/gc-sound-mixer.gob:
+ * src/gc_sound/src/gc-sound-mixer.h:
+ * src/gc_sound/src/gc-sound.h:
+ * src/gc_sound/src/marshallers.list:
+ * src/gc_sound/src/test_gc_sound.c: (main):
+
+
2006-11-16 Yves Combe <yves@ycombe.net>
Added sound policy (play only if iddle, after current, or interrupt and play).
diff --git a/src/gc_sound/ChangeLog b/src/gc_sound/ChangeLog
index 87a4b27..72e5c10 100644
--- a/src/gc_sound/ChangeLog
+++ b/src/gc_sound/ChangeLog
@@ -1,3 +1,72 @@
+2006-11-29 Yves Combe <yves@ycombe.net>
+
+ Rewrite gc_sound without gob (in C).
+ Architecture change:
+ - GCSoundMixer is an interface. GCSoundMixerSDL just implement it.
+ That to allow change libsdl dependencie to gstreamer when needed.
+ - GCSoundChannel and GCSoundItem just uses GCSoundMixer interface to run.
+
+ TODO:
+ - object_ref is not correct.
+ - python binding.
+ - add a record capability in interface (for now SDL_mixer can not do it).
+ - future way. add a gstreamer implementation of interface.
+
+ * aclocal.m4:
+ * configure.in:
+ * src/Makefile.am:
+ * src/gc-sound-channel.c: (gc_sound_channel_play_item),
+ (gc_sound_channel_get_root), (gc_sound_channel_pause),
+ (gc_sound_channel_resume), (gc_sound_channel_halt),
+ (gc_sound_channel_get_policy), (gc_sound_channel_set_policy),
+ (gc_sound_channel_play), (gc_sound_channel_init),
+ (gc_sound_channel_get_property), (gc_sound_channel_set_property),
+ (gc_sound_channel_signal_chunk_end), (gc_sound_channel_signal_run),
+ (gc_sound_channel_class_init):
+ * src/gc-sound-channel.gob:
+ * src/gc-sound-channel.h:
+ * src/gc-sound-item.c: (gc_sound_item_run_next),
+ (gc_sound_item_set_loop), (gc_sound_item_get_policy),
+ (gc_sound_item_set_policy), (gc_sound_item_child_start),
+ (gc_sound_item_child_end), (gc_sound_item_append_child),
+ (gc_sound_item_play), (gc_sound_item_set_filename),
+ (gc_sound_item_get_filename), (gc_sound_item_signal_real_play),
+ (gc_sound_item_signal_play_end), (gc_sound_item_signal_play_start),
+ (gc_sound_item_signal_chunk_end),
+ (gc_sound_item_signal_chunk_start), (gc_sound_item_init),
+ (gc_sound_item_get_property), (gc_sound_item_set_property),
+ (gc_sound_item_class_init):
+ * src/gc-sound-item.gob:
+ * src/gc-sound-item.h:
+ * src/gc-sound-marshallers.c:
+ * src/gc-sound-marshallers.h:
+ * src/gc-sound-mixer-SDL.c: (gc_sound_mixer_SDL_new),
+ (gc_sound_mixer_SDL_open_audio), (gc_sound_mixer_SDL_close_audio),
+ (gc_sound_mixer_SDL_new_channel), (gc_sound_mixer_SDL_pause),
+ (gc_sound_mixer_SDL_resume), (gc_sound_mixer_SDL_halt),
+ (gc_sound_mixer_SDL_pause_channel),
+ (gc_sound_mixer_SDL_resume_channel),
+ (gc_sound_mixer_SDL_halt_channel), (gc_sound_mixer_SDL_play_item),
+ (channel_finished_cb), (gc_sound_mixer_SDL_channel_finished),
+ (gc_sound_mixer_SDL_init), (gc_sound_mixer_SDL_finalize),
+ (gc_sound_mixer_SDL_get_property),
+ (gc_sound_mixer_SDL_set_property), (gc_sound_mixer_SDL_class_init),
+ (gc_init_sound_mixer):
+ * src/gc-sound-mixer-SDL.h:
+ * src/gc-sound-mixer-private.h:
+ * src/gc-sound-mixer.c: (gc_sound_mixer_open_audio),
+ (gc_sound_mixer_close_audio), (gc_sound_mixer_new_channel),
+ (gc_sound_mixer_pause), (gc_sound_mixer_resume),
+ (gc_sound_mixer_halt), (gc_sound_mixer_pause_channel),
+ (gc_sound_mixer_resume_channel), (gc_sound_mixer_halt_channel),
+ (gc_sound_mixer_play_item), (gc_sound_mixer_get_type),
+ (_gc_sound_mixer_install_property), (gc_sound_mixer_iface_init):
+ * src/gc-sound-mixer.gob:
+ * src/gc-sound-mixer.h:
+ * src/gc-sound.h:
+ * src/marshallers.list:
+ * src/test_gc_sound.c: (main):
+
2006-11-16 Yves Combe <yves@ycombe.net>
Added sound policy (play only if iddle, after current, or interrupt and play).
diff --git a/src/gc_sound/aclocal.m4 b/src/gc_sound/aclocal.m4
index 936c7ca..75137d0 100644
--- a/src/gc_sound/aclocal.m4
+++ b/src/gc_sound/aclocal.m4
@@ -70,6 +70,60 @@ AC_DEFUN([GOB2_CHECK],[
GOB2_HOOK($1,[],[AC_MSG_WARN([Cannot find GOB-2, check http://www.5z.com/jirka/gob.html])])
])
+dnl -*- mode: autoconf -*-
+
+# serial 1
+
+dnl Usage:
+dnl GTK_DOC_CHECK([minimum-gtk-doc-version])
+AC_DEFUN([GTK_DOC_CHECK],
+[
+ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+ dnl for overriding the documentation installation directory
+ AC_ARG_WITH(html-dir,
+ AC_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
+ [with_html_dir='${datadir}/gtk-doc/html'])
+ HTML_DIR="$with_html_dir"
+ AC_SUBST(HTML_DIR)
+
+ dnl enable/disable documentation building
+ AC_ARG_ENABLE(gtk-doc,
+ AC_HELP_STRING([--enable-gtk-doc],
+ [use gtk-doc to build documentation [default=no]]),,
+ enable_gtk_doc=no)
+
+ have_gtk_doc=no
+ if test x$enable_gtk_doc = xyes; then
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+ if test "$PKG_CONFIG" != "no" && $PKG_CONFIG --exists gtk-doc; then
+ have_gtk_doc=yes
+ fi
+
+ dnl do we want to do a version check?
+ifelse([$1],[],,
+ [gtk_doc_min_version=$1
+ if test "$have_gtk_doc" = yes; then
+ AC_MSG_CHECKING([gtk-doc version >= $gtk_doc_min_version])
+ if $PKG_CONFIG --atleast-version $gtk_doc_min_version gtk-doc; then
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ have_gtk_doc=no
+ fi
+ fi
+])
+ if test "$have_gtk_doc" != yes; then
+ enable_gtk_doc=no
+ fi
+ fi
+
+ AM_CONDITIONAL(ENABLE_GTK_DOC, test x$enable_gtk_doc = xyes)
+ AM_CONDITIONAL(GTK_DOC_USE_LIBTOOL, test -n "$LIBTOOL")
+])
+
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
# serial 48 Debian 1.5.22-4 AC_PROG_LIBTOOL
diff --git a/src/gc_sound/configure.in b/src/gc_sound/configure.in
index be5d5f9..3d3b878 100644
--- a/src/gc_sound/configure.in
+++ b/src/gc_sound/configure.in
@@ -14,8 +14,14 @@ AC_PROG_LIBTOOL
AC_PROG_CC
AC_PROG_INSTALL
+GTK_DOC_CHECK
GOB2_CHECK([2.0.0])
+AC_MSG_CHECKING([for glib-genmarshal])
+GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
+AC_SUBST(GLIB_GENMARSHAL)
+AC_MSG_RESULT($GLIB_GENMARSHAL)
+
PKG_CHECK_MODULES(GC_SOUND,[
glib-2.0 >= 2.10.0
gobject-2.0 >= 2.8.0
diff --git a/src/gc_sound/src/Makefile.am b/src/gc_sound/src/Makefile.am
index 39c1d2e..9999865 100644
--- a/src/gc_sound/src/Makefile.am
+++ b/src/gc_sound/src/Makefile.am
@@ -12,19 +12,24 @@ libgcsoundincludedir = $(includedir)/gcompris/gcsound
libgcsoundinclude_HEADERS = \
gc-sound.h \
gc-sound-mixer.h \
+ gc-sound-mixer-SDL.h \
gc-sound-channel.h \
+ gc-sound-marshallers.h \
gc-sound-item.h
-libgcsound_PRIVATE = \
- gc-sound.h \
- gc-sound-mixer-private.h \
- gc-sound-channel-private.h \
- gc-sound-item-private.h
+libgcsound_PRIVATE =
+# \
+# gc-sound.h \
+# gc-sound-mixer-private.h \
+# gc-sound-channel-private.h \
+# gc-sound-item-private.h
libgcsound_2_la_SOURCES = \
$(libgcsoundinclude_HEADERS) \
$(libgcsound_PRIVATE) \
gc-sound-mixer.c \
+ gc-sound-mixer-SDL.c \
+ gc-sound-marshallers.c \
gc-sound-channel.c \
gc-sound-item.c
@@ -43,7 +48,31 @@ gc-sound-item.c: gc-sound-channel.c
gc-sound-mixer.c: gc-sound-channel.c
-%.c %.h %-private.h: %.gob
- gob2 $<
-clean-local:
- rm -f gc-sound-*.h gc-sound-*.c
+gc-sound-marshallers.h: $(srcdir)/marshallers.list $(srcdir)/Makefile
+ @( $(GLIB_GENMARSHAL) --header --prefix=gc_sound_marshal $< ) > xgen-cmh \
+ && (cmp -s xgen-cmh $@ || (echo "Creating $@..."; cp xgen-cmh $@) ) \
+ && rm -f xgen-cmh
+
+gc-sound-marshallers.c: $(srcdir)/marshallers.list $(srcdir)/Makefile
+ @( echo "#include <gc-sound-marshallers.h>"; \
+ $(GLIB_GENMARSHAL) --body --prefix=gc_sound_marshal $< ) > xgen-cmc \
+ && (cmp -s xgen-cmc $@ || (echo "Creating $@..."; cp xgen-cmc $@) ) \
+ && rm -f xgen-cmc
+
+# gc-sound-enumerations.h: $(static_headers) Makefile gc-sound-enumerations.h.in
+# @( cd $(srcdir) && $(GLIB_MKENUMS) --template gc-sound-enumerations.h.in \
+# $(gc_sound_HEADERS) ) > xgen-gtbh \
+# && (cmp -s xgen-gtbh $@ || (echo "Creating $@..."; cp xgen-gtbh $@) ) \
+# && rm -f xgen-gtbh
+
+# gc-sound-enumerations.c: $(static_headers) Makefile gc-sound-enumerations.c.in
+# @( cd $(srcdir) && $(GLIB_MKENUMS) --template gc-sound-enumerations.c.in \
+# $(gc_sound_HEADERS) ) >> xgen-gtbc \
+# && (cmp -s xgen-gtbc $@ || (echo "Creating $@..."; cp xgen-gtbc $@) ) \
+# && rm -f xgen-gtbc
+
+# gc-sound-enumerations.c.in \
+# gc-sound-enumerations.h.in \
+EXTRA_DIST=\
+ marshallers.list \
+ $(NULL)
diff --git a/src/gc_sound/src/gc-sound-channel.c b/src/gc_sound/src/gc-sound-channel.c
new file mode 100644
index 0000000..15592a8
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-channel.c
@@ -0,0 +1,290 @@
+/* gcompris - gc-sound-channel.c
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ *
+ * 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 <gc-sound-channel.h>
+#include <gc-sound-marshallers.h>
+
+/* signals */
+enum {
+ RUN, /* internal: launch recursive playing of playlist */
+ CHUNK_END,
+ PLAY_START, /* Start real playing of item */
+ PLAY_END, /* end playing */
+ PAUSED, /* channel paused */
+ RESUMED, /* channel resumed */
+ HALTED, /* channel halted */
+ DESTROY,
+
+ N_SIGNALS
+};
+
+guint gc_sound_channel_signals[N_SIGNALS] = {0};
+
+gboolean gc_sound_channel_play_item (GCSoundChannel * self, GCSoundItem *item)
+{
+ g_warning("gc_sound_channel_play_item %s %s", self->nick, item->nick);
+
+ self->running_sample = item;
+ self->stopped = FALSE;
+
+ return gc_sound_mixer_play_item (self->mixer, self, item);
+}
+
+GCSoundItem * gc_sound_channel_get_root (GCSoundChannel * self)
+{
+ return self->root;
+}
+
+gboolean gc_sound_channel_pause (GCSoundChannel * self)
+{
+ return gc_sound_mixer_pause_channel( self->mixer, self);
+}
+
+gboolean gc_sound_channel_resume (GCSoundChannel * self)
+{
+ return gc_sound_mixer_resume_channel( self->mixer, self);
+}
+
+gboolean gc_sound_channel_halt (GCSoundChannel * self)
+{
+ return gc_sound_mixer_halt_channel( self->mixer, self);
+}
+
+GCSoundPolicy gc_sound_channel_get_policy (GCSoundChannel * self)
+{
+ return self->policy;
+}
+gboolean gc_sound_channel_set_policy (GCSoundChannel * self,
+ GCSoundPolicy policy)
+{
+ self->policy = policy;
+ return TRUE;
+}
+
+gboolean gc_sound_channel_play (GCSoundChannel *self,
+ GCSoundItem *item)
+{
+ GCSoundPolicy policy;
+
+ /* item policy if it's set */
+ if (gc_sound_item_get_policy(item) == GC_SOUND_POLICY_NONE)
+ policy = self->policy;
+ else
+ policy = gc_sound_item_get_policy(item);
+
+ //g_warning ("play_item %s with policy %d", item->nick, policy);
+
+ switch (policy) {
+ case GC_SOUND_PLAY_ONLY_IF_IDLE:
+ if (self->running_sample || g_list_length (self->playlist)>0)
+ return;
+ self->playlist = g_list_append (self->playlist, item);
+ // TODO send a signal to run !!!
+ g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
+ break;
+
+ case GC_SOUND_INTERRUPT_AND_PLAY:
+ g_list_free (self->playlist);
+ self->playlist = NULL;
+ self->playlist = g_list_append (self->playlist, item);
+ if (self->running_sample){
+ self->stopped = TRUE;
+ //g_warning("halting channel %d %d", self->_priv->channel, g_list_length(self->_priv->play_list));
+ // send a signal to halt.
+ gc_sound_channel_halt(self);
+ }
+ // TODO send a signal to run !!!
+ g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
+ break;
+
+ default:
+ self->playlist = g_list_append (self->playlist, item);
+ if (!self->running_sample)
+ // TODO send a signal to run !!!
+ g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
+ break;
+ }
+
+}
+
+/* GType stuff */
+enum {
+ PROP_0,
+ PROP_MIXER
+};
+
+
+/* GType */
+G_DEFINE_TYPE(GCSoundChannel, gc_sound_channel, G_TYPE_OBJECT);
+
+static void
+gc_sound_channel_init(GCSoundChannel* self)
+{
+ // initialisation des variables.
+ //g_warning("gc_sound_channel_init");
+
+ self->volume = 1.0;
+ self->policy = GC_SOUND_PLAY_AFTER_CURRENT;
+
+ self->stopped = FALSE;
+
+ self->mixer = NULL;
+ self->root = GC_SOUND_ITEM(g_object_new(GC_TYPE_SOUND_ITEM, "channel", self, NULL));
+
+ self->playlist = NULL;
+
+ //this one is the item with the file
+ self->running_sample = NULL;
+ // this one is the group playing
+ self->running_root = NULL;
+
+ //debug. will be removed.
+ gchar *nick;
+
+}
+
+static void
+gc_sound_channel_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
+{
+ GCSoundChannel *self = GC_SOUND_CHANNEL(object);
+ switch(prop_id) {
+ case PROP_MIXER:
+ g_value_set_object(value, self->mixer);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gc_sound_channel_set_property(GObject* object, guint prop_id, GValue const* value, GParamSpec* pspec)
+{
+ GCSoundChannel *self = GC_SOUND_CHANNEL(object);
+
+ switch(prop_id) {
+ case PROP_MIXER:
+ self->mixer = g_value_get_object(value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+
+}
+
+static void
+gc_sound_channel_signal_chunk_end (GCSoundChannel *self)
+{
+ GCSoundItem *chunk = self->running_sample;
+
+ self->running_sample = NULL;
+
+ g_return_if_fail(GC_IS_SOUND_ITEM(chunk));
+
+ g_warning ("%s received chunk_end self->stopped %s", self->nick, self->stopped ? "TRUE" : "FALSE");
+
+ g_signal_emit_by_name (chunk, "chunk_end", 0, self->stopped);
+}
+
+static void
+gc_sound_channel_signal_run (GCSoundChannel *self)
+{
+ GList *item_root;
+ gboolean ret;
+
+ g_warning("Channel %s received run !", self->nick);
+
+ while (g_list_length(self->playlist)>0)
+ {
+ self->running_root = g_list_first (self->playlist);
+ self->playlist = g_list_remove_link (self->playlist, self->running_root);
+
+ ret = gc_sound_item_run_next (GC_SOUND_ITEM(self->running_root->data), FALSE);
+ if (ret)
+ return ;
+ }
+}
+
+static void
+gc_sound_channel_class_init(GCSoundChannelClass* self_class)
+{
+ // c'est ici qu'il faut passer les properties et les signals.
+ // g_warning("gc_sound_channel_class_init");
+
+ GObjectClass* go_class;
+
+ /* GObjectClass */
+ go_class = G_OBJECT_CLASS(self_class);
+
+ go_class->get_property = gc_sound_channel_get_property;
+ go_class->set_property = gc_sound_channel_set_property;
+
+ g_object_class_install_property(go_class,
+ PROP_MIXER,
+ g_param_spec_object ("mixer",
+ "GCompris mixer",
+ "The mixer where this channel stand",
+ GC_TYPE_SOUND_MIXER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+
+/* signals */
+/* enum { */
+/* RUN, /\* internal: launch recursive playing of playlist *\/ */
+
+/* PLAY_START, /\* Start real playing of item *\/ */
+/* PLAY_END, /\* end playing *\/ */
+/* PAUSED, /\* channel paused *\/ */
+/* RESUMED, /\* channel resumed *\/ */
+/* HALTED, /\* channel halted *\/ */
+/* DESTROY, */
+
+/* N_SIGNALS */
+/* }; */
+
+ self_class->run = gc_sound_channel_signal_run;
+ self_class->chunk_end = gc_sound_channel_signal_chunk_end;
+
+ gc_sound_channel_signals[RUN] =
+ g_signal_new("run", /* name */
+ GC_TYPE_SOUND_CHANNEL, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundChannelClass, run), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__VOID, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 0 /* n_params */
+ );
+
+ gc_sound_channel_signals[CHUNK_END] =
+ g_signal_new("chunk_end", /* name */
+ GC_TYPE_SOUND_CHANNEL, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundChannelClass, chunk_end), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__BOOLEAN, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 1, /* n_params */
+ G_TYPE_BOOLEAN
+ );
+
+}
diff --git a/src/gc_sound/src/gc-sound-channel.gob b/src/gc_sound/src/gc-sound-channel.gob
deleted file mode 100644
index 37bfc08..0000000
--- a/src/gc_sound/src/gc-sound-channel.gob
+++ /dev/null
@@ -1,321 +0,0 @@
-%alltop{/* gcompris - gc-sound-channel.gob
- *
- * Copyright (C) 2006 Yves Combe
- *
- *
- * 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
- */
-%}
-
-requires 2.0.0
-
-%{
-#include <gc-sound-channel.h>
-#include <SDL.h>
-#include <SDL_thread.h>
-#include <SDL_mixer.h>
-#include <SDL_audio.h>
-#include <libintl.h>
-
-#define _(String) gettext (String)
-#define gettext_noop(String) String
-
-#ifndef N_
-#define N_(String) gettext_noop (String)
-#endif
-
-#include "gc-sound-channel-private.h"
-#include "gc-sound-item-private.h"
-%}
-
-%h{
-#include <gc-sound.h>
-%}
-
-
-%{
-static GHashTable *channels_table = NULL;
-%}
-
-enum GC_SOUND {
- POLICY_NONE,
- PLAY_ONLY_IF_IDLE,
- PLAY_AFTER_CURRENT,
- INTERRUPT_AND_PLAY
-} GC:Sound:Policy;
-
-class GC:Sound:Channel from G:Object {
- public gchar *nick = {NULL};
-
- /* channel is the mixer channel number we use */
- private int channel
- destroy {
- g_hash_table_remove(channels_table, GINT_TO_POINTER(channel));
-
- if (g_hash_table_size (channels_table) == 0) {
- g_hash_table_destroy(channels_table);
- channels_table = NULL;
- }
- };
-
- private gboolean initialised = {FALSE};
-
- private Mix_Chunk *sample;
- private GC:Sound:Item *playing_item = { NULL };
- private G:List *playing_root = { NULL };
- private G:List *play_list = { NULL };
-
- /* the default volume for the channel */
- private int volume = { MIX_MAX_VOLUME };
- property INT volume
- ( nick= _("Channel volume"),
- blurb= _("Default volume of the channel"),
- export,
- link);
-
- /* The default policy for the channel */
- private GCSoundPolicy policy = {GC_SOUND_PLAY_AFTER_CURRENT};
- property ENUM policy
- ( nick = _("Channel policy"),
- blurb = _("Default policy for this channel"),
- enum_type = GC:Sound:Policy,
- export, link);
-
- /* the mixer we are attached on */
- /* The mixer initalise SDL and audio */
- private GC:Sound:Mixer *mixer = { NULL }
- destroywith g_object_unref ;
-
- property OBJECT mixer
- (nick = _("GCompris Sound Mixer"),
- blurb = _("GCompris Sound Mixer where this sound channel is"),
- object_type=GC:Sound:Mixer,
- flags = CONSTRUCT_ONLY,
- export)
- set { self->_priv->mixer = GC_SOUND_MIXER(g_value_get_object
-(VAL));
- self->_priv->channel = self->_priv->mixer->channels++ ;
- Mix_AllocateChannels(self->_priv->mixer->channels );
-
- g_warning("Channel #%d initialised", self->_priv->channel);
- Mix_HaltChannel(self->_priv->channel);
-
- g_hash_table_insert(channels_table, &(self->_priv->channel), self);
-
- self->_priv->rootItem = GC_SOUND_ITEM(g_object_new(gc_sound_item_get_type(), "channel", self, NULL));
-
- g_object_ref(self->_priv->rootItem);
-
- }
- get { g_value_set_object (VAL, G_OBJECT(self->_priv->channel)); }
- ;
-
- private GC:Sound:Item *rootItem = { NULL }
- destroywith g_object_unref;
-
- property OBJECT rootItem
- (nick = _("GCompris Sound Item root"),
- blurb = _("GCompris Sound Item root"),
- object_type=GC:Sound:Item,
- export, link)
- ;
-
- private gboolean stopped = { FALSE };
-
- init (self) {
- //g_warning("gc channel instance init");
- if (!channels_table)
- channels_table = g_hash_table_new (g_int_hash, g_int_equal);
-
- Mix_ChannelFinished(self_channel_finished);
- }
-
- class_init (class) {
- //g_warning("gc channel class init");
- }
-
- public GC:Sound:Item *
- new_item (self)
- {
- return GC_SOUND_ITEM(g_object_new(gc_sound_item_get_type(), "parent", self->_priv->rootItem, NULL));
- }
-
- private void channel_finished (int channel)
- {
- /* check we are on the right channel */
- /* this a too simple callback */
- /* get self */
- GCSoundChannel *self;
-
- //g_warning ("Channel finished %d", channel);
-
- self = GC_SOUND_CHANNEL(g_hash_table_lookup(channels_table, &channel));
-
- if (!self) {
- g_warning ("Cannot get GCSoundChannel from hash !!!!!");
- return;
- }
- self_play_finished (self, self->_priv->playing_item);
- }
-
- private void real_play ( GC:Sound:Item *item, gpointer data)
- {
- //g_warning ("Real play %s", item->nick);
- GCSoundChannel *self = GC_SOUND_CHANNEL(data);
-
- gchar * filename = gc_sound_item_get_filename(item);
-
- if (Mix_Playing(self->_priv->channel)){
- g_warning("Channel busy ? no play!");
- return;
- }
-
- if (filename == NULL){
- g_warning("No filename ? no play!");
- return;
- }
-
- self->_priv->sample=Mix_LoadWAV_RW(SDL_RWFromFile(filename, "rb"), 1);
- if (!self->_priv->sample) {
- g_warning("Sample music %s cannot be load", filename);
- return;
- }
-
- if ((item->volume == -1) || (item->volume > self->_priv->volume))
- Mix_VolumeChunk(self->_priv->sample, self->_priv->volume);
- else
- Mix_VolumeChunk(self->_priv->sample, item->volume);
-
- if (Mix_PlayChannel(self->_priv->channel, self->_priv->sample, 0)==-1) {
- g_warning("Channel cannot play music %s", filename);
- return;
- }
-
- g_warning("Playing %s on channel #%d", filename, self->_priv->channel);
-
-
- self->_priv->playing_item = item;
- }
-
-
- signal first NONE (POINTER)
- void play_finished (self, GC:Sound:Item *item (check null type))
- {
- //g_warning ("Channel finish item %s", item->nick);
- Mix_FreeChunk(self->_priv->sample);
- self->_priv->sample = NULL;
-
- gc_sound_item_play_next(item, self->_priv->stopped);
- }
-
- /* connected to do_play signal of item */
- protected void do_play (GC:Sound:Item *item, gpointer data)
- {
- GCSoundChannel *self = GC_SOUND_CHANNEL(data);
- GCSoundPolicy policy;
-
- /* item policy if it's set */
- if (gc_sound_item_get_policy(item) == GC_SOUND_POLICY_NONE)
- policy = self->_priv->policy;
- else
- policy = gc_sound_item_get_policy(item);
-
- //g_warning ("play_item %s with policy %d", item->nick, policy);
-
- switch (policy) {
- case GC_SOUND_PLAY_ONLY_IF_IDLE:
- if (self->_priv->sample || g_list_length (self->_priv->play_list)>0)
- return;
- break;
-
- case GC_SOUND_INTERRUPT_AND_PLAY:
- g_list_free (self->_priv->play_list);
- self->_priv->play_list = NULL;
- self->_priv->play_list = g_list_append (self->_priv->play_list, item);
- if (self->_priv->sample){
- self->_priv->stopped = TRUE;
- //g_warning("halting channel %d %d", self->_priv->channel, g_list_length(self->_priv->play_list));
- self_halt(self);
- }
- self_run(self);
- break;
-
- default:
- self->_priv->play_list = g_list_append (self->_priv->play_list, item);
- if (!self->_priv->sample)
- self_run(self);
- break;
- }
- }
-
- protected void play_first_item(self)
- {
- gboolean ret;
-
- while (g_list_length(self->_priv->play_list)>0)
- {
- self->_priv->playing_root = g_list_first (self->_priv->play_list);
- self->_priv->play_list = g_list_remove_link (self->_priv->play_list, self->_priv->playing_root);
-
- ret = gc_sound_item_play_next (GC_SOUND_ITEM(self->_priv->playing_root->data), FALSE);
- if (ret)
- return ;
- }
- }
-
- private void item_play_finished (GC:Sound:Item *item, gboolean stopped, gpointer data)
- {
- //g_warning("channel item_play_finished %s %s", item->nick, stopped ? "STOPPED":"normal");
-
- /* if item our our root item playing */
- if (item == GC_SOUND_ITEM(GC_SOUND_CHANNEL(data)->_priv->playing_root->data))
- {
- GC_SOUND_CHANNEL(data)->_priv->playing_root = NULL;
- /* do not call run if we are stopping */
- if (GC_SOUND_CHANNEL(data)->_priv->stopped)
- GC_SOUND_CHANNEL(data)->_priv->stopped = FALSE;
- else
- self_run(GC_SOUND_CHANNEL(data));
- }
- }
-
- public void connect_me (self, GC:Sound:Item *item )
- {
- gc_sound_item_connect__play_finished(item, self_item_play_finished, self);
- gc_sound_item_connect__do_play(item, self_do_play, self);
- gc_sound_item_connect__real_play(item, self_real_play, self);
-
- }
-
- private signal first NONE (NONE)
- void run (self)
- {
- //g_warning("channel run");
- self_play_first_item(self);
- }
-
- public signal first NONE (NONE)
- void halt (self)
- {
- //g_warning("halting channel %d", self->_priv->channel);
- Mix_HaltChannel(self->_priv->channel);
- }
-
- private signal first NONE (POINTER)
- void halt_and_play (self, GC:Sound:Item *item )
- {
- }
-
-}
diff --git a/src/gc_sound/src/gc-sound-channel.h b/src/gc_sound/src/gc-sound-channel.h
new file mode 100644
index 0000000..ca1769e
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-channel.h
@@ -0,0 +1,104 @@
+/* gcompris - gc-sound-channel.h
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ *
+ * 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
+ */
+#ifndef __GC_SOUND_CHANNEL_H__
+#define __GC_SOUND_CHANNEL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GCSoundChannel GCSoundChannel;
+typedef struct _GCSoundChannelClass GCSoundChannelClass;
+
+typedef enum {
+ GC_SOUND_POLICY_NONE,
+ GC_SOUND_PLAY_ONLY_IF_IDLE,
+ GC_SOUND_PLAY_AFTER_CURRENT,
+ GC_SOUND_INTERRUPT_AND_PLAY
+} GCSoundPolicy;
+
+G_END_DECLS
+
+#include <glib-object.h>
+#include <gc-sound-mixer.h>
+#include <gc-sound-item.h>
+
+G_BEGIN_DECLS
+
+#define GC_TYPE_SOUND_CHANNEL (gc_sound_channel_get_type())
+#define GC_SOUND_CHANNEL(i) (G_TYPE_CHECK_INSTANCE_CAST((i), GC_TYPE_SOUND_CHANNEL, GCSoundChannel))
+#define GC_SOUND_CHANNEL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), GC_TYPE_SOUND_CHANNEL, GCSoundChannelClass))
+#define GC_IS_SOUND_CHANNEL(i) (G_TYPE_CHECK_INSTANCE_TYPE((i), GC_TYPE_SOUND_CHANNEL))
+#define GC_IS_SOUND_CHANNEL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE((c), GC_TYPE_SOUND_CHANNEL))
+#define GC_SOUND_CHANNEL_GET_CLASS(i) (G_TYPE_INSTANCE_GET_CLASS((i), GC_TYPE_SOUND_CHANNEL, GCSoundChannelClass))
+
+GType gc_sound_channel_get_type(void);
+
+struct _GCSoundChannel {
+ GObject __parent__;
+
+ gdouble volume;
+ GCSoundPolicy policy;
+ //gint policy;
+
+ gboolean stopped;
+
+ GCSoundMixer* mixer;
+ GCSoundItem* root;
+
+ GList* playlist;
+ //this one is the item with the file
+ GCSoundItem* running_sample;
+ // this one is the group playing
+ GList* running_root;
+
+ gint channel_number;
+
+ //debug. will be removed.
+ gchar *nick;
+};
+
+struct _GCSoundChannelClass {
+ GObjectClass __parentClass__;
+
+ /* signal handlers */
+ void (* run) (GCSoundChannel * self);
+ void (* chunk_end) (GCSoundChannel * self);
+};
+
+GCSoundItem * gc_sound_channel_get_root (GCSoundChannel * self);
+
+gboolean gc_sound_channel_pause (GCSoundChannel * self);
+gboolean gc_sound_channel_resume (GCSoundChannel * self);
+gboolean gc_sound_channel_halt (GCSoundChannel * self);
+
+gboolean gc_sound_channel_play (GCSoundChannel * channel,
+ GCSoundItem *item);
+
+gboolean gc_sound_channel_play_item (GCSoundChannel * self,
+ GCSoundItem *item);
+
+GCSoundPolicy gc_sound_channel_get_policy (GCSoundChannel * self);
+gboolean gc_sound_channel_set_policy (GCSoundChannel * self,
+ GCSoundPolicy policy);
+
+G_END_DECLS
+
+#endif
diff --git a/src/gc_sound/src/gc-sound-item.c b/src/gc_sound/src/gc-sound-item.c
new file mode 100644
index 0000000..9820be5
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-item.c
@@ -0,0 +1,421 @@
+/* gcompris - gc-sound-item.c
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ *
+ * 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 <gc-sound-item.h>
+#include <gc-sound-marshallers.h>
+
+
+/* signals */
+enum {
+ REAL_PLAY, /* internal: real launch play*/
+
+ PLAY_START, /* Start real playing of item */
+ PLAY_END, /* end playing */
+ CHUNK_START, /* Start real playing of item */
+ CHUNK_END, /* Start real playing of item */
+ PAUSED, /* channel paused */
+ RESUMED, /* channel resumed */
+ HALTED, /* channel halted */
+ DESTROY,
+
+ N_SIGNALS
+};
+
+guint gc_sound_item_signals[N_SIGNALS] = {0};
+
+// internal use
+gboolean gc_sound_item_run_next (GCSoundItem *self,
+ gboolean stopped)
+{
+ gboolean ret;
+
+ g_warning("run_next %s %d", self->nick, stopped);
+
+ /* if we are stopped, we don't continue */
+ if (stopped) {
+ g_signal_emit(self, gc_sound_item_signals[PLAY_END], 0, stopped);
+ return TRUE;
+ }
+
+ /* If we are muted, we have nothing to do */
+ if (self->mute)
+ return FALSE;
+
+ /* mark if we are in play tree */
+ self->has_played = TRUE;
+
+ if (g_list_length(self->children) == 0)
+ return FALSE;
+
+ if (self->playing == NULL)
+ self->playing = g_list_first(self->children);
+ else
+ self->playing = g_list_next (self->playing );
+
+ if ((self->playing == NULL) && (self->loop)) {
+ g_warning ("looping on %s", self->nick);
+ self->playing = g_list_first (self->children );
+ }
+
+ while (self->playing) {
+ if ( GC_SOUND_ITEM(self->playing->data) == self){
+ if (!self->started)
+ g_signal_emit(self, gc_sound_item_signals[PLAY_START], 0);
+ g_signal_emit(self, gc_sound_item_signals[REAL_PLAY], 0);
+ return TRUE;
+ }
+ else {
+ ret= gc_sound_item_run_next ( GC_SOUND_ITEM(self->playing->data), FALSE);
+ if (ret)
+ return ret;
+ }
+ self->playing = g_list_next (self->playing );
+ }
+
+ /* if we have play, it's finished */
+ if (self->started) {
+ g_signal_emit(self, gc_sound_item_signals[PLAY_END], 0, FALSE);
+ }
+
+ return FALSE;
+}
+
+void gc_sound_item_set_loop(GCSoundItem *self, gboolean loop)
+{
+ self->loop = loop;
+}
+
+GCSoundPolicy gc_sound_item_get_policy (GCSoundItem * self)
+{
+ return self->policy;
+}
+gboolean gc_sound_item_set_policy (GCSoundItem * self,
+ GCSoundPolicy policy)
+{
+ self->policy = policy;
+ return TRUE;
+}
+
+void gc_sound_item_child_start( GCSoundItem *child, gpointer data)
+{
+ GCSoundItem *self = GC_SOUND_ITEM(data);
+
+ g_return_if_fail(GC_IS_SOUND_ITEM(self));
+
+ if (self->has_played){
+ self->started = TRUE;
+ g_signal_emit( self, gc_sound_item_signals[PLAY_START], 0);
+ }
+
+}
+
+void gc_sound_item_child_end( GCSoundItem *child, gboolean stopped, gpointer data)
+{
+ GCSoundItem *self = GC_SOUND_ITEM(data);
+
+ if (self->has_played)
+ gc_sound_item_run_next(self, stopped);
+}
+
+GCSoundItem * gc_sound_item_append_child (GCSoundItem *self)
+{
+ GCSoundItem *child;
+
+ child = GC_SOUND_ITEM(g_object_new(gc_sound_item_get_type(), "parent", self, "channel", self->channel, NULL));
+
+ /* Child is added to our lists */
+ self->children = g_list_append (self->children, child);
+
+ /* we get a ref */
+ g_object_ref (G_OBJECT(child));
+
+ g_signal_connect( child, "play-end", (GCallback) gc_sound_item_child_end, self);
+ g_signal_connect( child, "play-start", (GCallback) gc_sound_item_child_start, self);
+ return child;
+}
+
+gboolean gc_sound_item_play (GCSoundItem *self)
+{
+ return gc_sound_channel_play (self->channel, self);
+}
+
+void gc_sound_item_set_filename (GCSoundItem *self, gchar *filename)
+{
+ if (filename) {
+ self->filename = filename;
+
+ if ( (!self->children) || (self != self->children->data))
+ self->children = g_list_prepend( self->children, self);
+ } else {
+ self->filename = NULL;
+ if ( (self->children) && (self == self->children->data))
+ self->children = g_list_remove ( self->children, self);
+ }
+}
+
+gchar * gc_sound_item_get_filename (GCSoundItem *self)
+{
+ return self->filename;
+}
+
+static void
+gc_sound_item_signal_real_play (GCSoundItem *self)
+{
+ g_warning("item %s received real_play", self->nick);
+
+ g_signal_emit(self, gc_sound_item_signals[CHUNK_START], 0);
+ gc_sound_channel_play_item (self->channel, self);
+}
+
+static void
+gc_sound_item_signal_play_end (GCSoundItem *self, gboolean stopped)
+{
+ g_warning("item %s received play_end", self->nick);
+
+ if (self->has_played || stopped) {
+ self->started = FALSE;
+ self->has_played = FALSE;
+ }
+
+}
+
+static void
+gc_sound_item_signal_play_start (GCSoundItem *self)
+{
+ g_warning("item %s received play_start", self->nick);
+
+ self->started = TRUE;
+}
+
+static void
+gc_sound_item_signal_chunk_end (GCSoundItem *self, gboolean stopped)
+{
+ g_warning("item %s received chunk_end", self->nick);
+
+ /*
+ We receive this signal from channel when play of chunk if finished.
+ We have to continue play in our group.
+ */
+
+ gc_sound_item_run_next (self, stopped);
+}
+
+static void
+gc_sound_item_signal_chunk_start (GCSoundItem *self)
+{
+ g_warning("item %s received chunk_start", self->nick);
+
+ self->started = TRUE;
+}
+
+/* GType stuff */
+enum {
+ PROP_0,
+ PROP_CHANNEL,
+ PROP_PARENT,
+ PROP_FILENAME
+};
+
+/* GType */
+G_DEFINE_TYPE(GCSoundItem, gc_sound_item, G_TYPE_OBJECT);
+
+static void
+gc_sound_item_init(GCSoundItem* self)
+{
+ // initialisation des variables.
+ g_warning("gc_sound_item_init");
+
+ self->volume = -1.0;
+ self->mute = FALSE;
+
+ self->policy = GC_SOUND_PLAY_AFTER_CURRENT;
+ self->loop = FALSE;
+
+ self->filename = NULL;
+
+ self->channel = NULL;
+ self->parent = NULL;
+ self->children = NULL;
+
+ //debug. will be removed
+ gchar * nick;
+
+ //internal use
+ // TRUE if we are in running play tree.
+ self->has_played = FALSE;
+
+ // our group already started
+ self->started = FALSE;
+
+ // child we are playing
+ self->playing = NULL;
+
+}
+
+static void
+gc_sound_item_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
+{
+ GCSoundItem *self = GC_SOUND_ITEM(object);
+ switch(prop_id) {
+ case PROP_CHANNEL:
+ g_value_set_object(value, self->channel);
+ break;
+ case PROP_PARENT:
+ g_value_set_object(value, self->parent);
+ break;
+ case PROP_FILENAME:
+ g_value_set_string(value, self->filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gc_sound_item_set_property(GObject* object, guint prop_id, GValue const* value, GParamSpec* pspec)
+{
+ GCSoundItem *self = GC_SOUND_ITEM(object);
+
+ switch(prop_id) {
+ case PROP_CHANNEL:
+ self->channel = g_value_get_object(value);
+ break;
+ case PROP_PARENT:
+ self->parent = g_value_get_object(value);
+ break;
+ case PROP_FILENAME:
+ gc_sound_item_set_filename( self, (gchar *)g_value_get_string(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+
+}
+
+static void
+gc_sound_item_class_init(GCSoundItemClass* self_class)
+{
+ // c'est ici qu'il faut passer les properties et les signals.
+ g_warning("gc_sound_item_class_init");
+
+ GObjectClass* go_class;
+
+ /* GObjectClass */
+ go_class = G_OBJECT_CLASS(self_class);
+
+ go_class->get_property = gc_sound_item_get_property;
+ go_class->set_property = gc_sound_item_set_property;
+
+ g_object_class_install_property(go_class,
+ PROP_CHANNEL,
+ g_param_spec_object ("channel",
+ "GCompris channel",
+ "The channel where this channel stand",
+ GC_TYPE_SOUND_CHANNEL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property(go_class,
+ PROP_PARENT,
+ g_param_spec_object ("parent",
+ "GCompris parent",
+ "The parent where this channel stand",
+ GC_TYPE_SOUND_ITEM,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+/* signals */
+/* enum { */
+/* RUN, /\* internal: launch recursive playing of playlist *\/ */
+
+/* PLAY_START, /\* Start real playing of item *\/ */
+/* PLAY_END, /\* end playing *\/ */
+/* PAUSED, /\* channel paused *\/ */
+/* RESUMED, /\* channel resumed *\/ */
+/* HALTED, /\* channel halted *\/ */
+/* DESTROY, */
+
+/* N_SIGNALS */
+/* }; */
+
+ self_class->real_play = gc_sound_item_signal_real_play;
+ self_class->play_start = gc_sound_item_signal_play_start;
+ self_class->play_end = gc_sound_item_signal_play_end;
+ self_class->chunk_start = gc_sound_item_signal_chunk_start;
+ self_class->chunk_end = gc_sound_item_signal_chunk_end;
+
+ gc_sound_item_signals[REAL_PLAY] =
+ g_signal_new("real_play", /* name */
+ GC_TYPE_SOUND_ITEM, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundItemClass, real_play), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__VOID, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 0 /* n_params */
+ );
+ gc_sound_item_signals[PLAY_START] =
+ g_signal_new("play_start", /* name */
+ GC_TYPE_SOUND_ITEM, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundItemClass, play_start), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__VOID, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 0 /* n_params */
+ );
+ gc_sound_item_signals[PLAY_END] =
+ g_signal_new("play_end", /* name */
+ GC_TYPE_SOUND_ITEM, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundItemClass, play_end), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__BOOLEAN, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 1 /* n_params */,
+ G_TYPE_BOOLEAN
+ );
+ gc_sound_item_signals[CHUNK_START] =
+ g_signal_new("chunk_start", /* name */
+ GC_TYPE_SOUND_ITEM, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundItemClass, chunk_start), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__VOID, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 0 /* n_params */
+ );
+ gc_sound_item_signals[CHUNK_END] =
+ g_signal_new("chunk_end", /* name */
+ GC_TYPE_SOUND_ITEM, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundItemClass, chunk_end), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__BOOLEAN, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 1, /* n_params */
+ G_TYPE_BOOLEAN
+ );
+
+}
diff --git a/src/gc_sound/src/gc-sound-item.gob b/src/gc_sound/src/gc-sound-item.gob
deleted file mode 100644
index 6f8fa1d..0000000
--- a/src/gc_sound/src/gc-sound-item.gob
+++ /dev/null
@@ -1,310 +0,0 @@
-%alltop{/* gcompris - gc-sound-item.gob
- *
- * Copyright (C) 2006 Yves Combe
- *
- * 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
- */
-%}
-
-requires 2.0.0
-
-%h{
-#ifndef __TYPEDEF_GC_SOUND_CHANNEL__
-#define __TYPEDEF_GC_SOUND_CHANNEL__
-typedef struct _GCSoundChannel GCSoundChannel;
-#endif
-%}
-
-%{
-#include <gc-sound-item.h>
-#include <SDL.h>
-#include <SDL_thread.h>
-#include <SDL_mixer.h>
-#include <SDL_audio.h>
-#include <libintl.h>
-
-#define _(String) gettext (String)
-#define gettext_noop(String) String
-
-#ifndef N_
-#define N_(String) gettext_noop (String)
-#endif
-
-
-#include "gc-sound-item-private.h"
-
-%}
-
-%privateheader{
- /* because of GCSoundPolicy */
- #include "gc-sound-channel.h"
-%}
-class GC:Sound:Item from G:Object {
- /* debug */
- public gchar *nick = {NULL};
-
- /*************************/
- /* muted or not ? */
- public gboolean mute = { FALSE };
-
- property BOOLEAN mute
- ( nick=_("Mute"),
- blurb=_("Do not play me"),
- export, link );
-
- /*************************/
- /* loop or not ? */
- public gboolean loop = { FALSE };
-
- property BOOLEAN loop
- ( nick=_("Loop"),
- blurb=_("Play loop"),
- export, link );
-
- /*************************/
- /* channel where we play */
- private GC:Sound:Channel *channel = { NULL }
- destroywith g_object_unref ;
-
- property OBJECT channel
- ( nick=_("Channel playing for us"),
- blurb=_("Numero of channel"),
- object_type=GC:Sound:Channel,
- export )
- set { self->_priv->channel = GC_SOUND_CHANNEL(g_value_get_object
-(VAL));
- gc_sound_channel_connect_me( self->_priv->channel, self);
- }
- get { g_value_set_object (VAL, G_OBJECT(self->_priv->channel)); };
-
- /*******************************************************/
- /* Parent is another item. We receive channel from it. */
- private GC:Sound:Item *parent = { NULL }
- destroywith g_object_unref ;
-
- property OBJECT parent
- ( nick=_("Channel playing for us"),
- blurb=_("Numero of channel"),
- object_type=GC:Sound:Item,
- export)
- set { self->_priv->parent = GC_SOUND_ITEM(g_value_get_object
-(VAL));
- }
- get { g_value_set_object (VAL, G_OBJECT(self->_priv->parent)); }
- ;
-
- /********************************************/
- /* filename is the name of file we play */
- /* may be NULL, in case we are only a group */
- private gchar *filename = { NULL }
- destroywith g_free;
- property STRING filename
- ( nick=_("Filename of sound"),
- blurb=_("sound file to play"),
- export )
- set {
- if (self->_priv->filename==NULL)
- g_free(self->_priv->filename);
-
- self->_priv->filename = g_strdup(g_value_get_string(VAL));
- self->_priv->PlayList = g_list_remove ( self->_priv->PlayList, self);
-
- if (self->_priv->filename)
- self->_priv->PlayList = g_list_insert ( self->_priv->PlayList, self, 0);
-
- }
- get { g_value_set_string(VAL, g_strdup(self->_priv->filename));};
-
- /*******************************************/
- /* Volume for the sound */
- public int volume = { -1 };
-
- /****************************************/
- /* mark if item or one child is playing */
- private gboolean started = { FALSE };
-
- /*****************************/
- /* mark if is playing or not */
- private gboolean has_played = { FALSE };
-
- /* playing part of the child */
- private G:List *playing = { NULL };
-
- /* childs */
- private G:List *SoundItems = { NULL }
- destroy {
- GList *list;
-
- for (list = SoundItems; list != NULL; list = list->next)
- g_object_unref(G_OBJECT(list->data));
-
- g_list_free (SoundItems);
- };
-
- /* The default policy for the channel */
- private GC:Sound:Policy policy = {GC_SOUND_POLICY_NONE};
- property ENUM policy
- ( nick = _("Channel policy"),
- blurb = _("Default policy for this channel"),
- enum_type = GC:Sound:Policy,
- export, link);
-
-
- /* PlayList */
- private GList *PlayList = { NULL }
- destroy {
- g_list_free (PlayList);
- };
-
-
- /* Objects methods */
- init (self) {
- //g_warning("Item sound instance init");
- /* do nothing. We set up channel when property is set */
- }
-
- class_init (class) {
- //g_warning("item sound class init");
-
- }
-
- public GC:Sound:Item *
- new (self)
- {
- GCSoundItem *child;
-
- child = GC_SOUND_ITEM(g_object_new(gc_sound_item_get_type(), "parent", self, "channel", self->_priv->channel, NULL));
-
- /* Child is added to our lists */
- self->_priv->SoundItems = g_list_append (self->_priv->SoundItems, child);
- self->_priv->PlayList = g_list_append (self->_priv->PlayList, child);
-
- /* we get a ref */
- g_object_ref (G_OBJECT(child));
-
- /* we need to know if start play or end on it, to send the same signal (group start/end) */
- self_connect__play_finished ( child, self_child_play_finished, self);
- self_connect__play_started ( child, self_child_play_started, self);
-
- return child;
- }
-
- public void
- play (self)
- {
- /* Change that with policy */
- self->_priv->has_played = TRUE;
-
- /* we will be added in play list channel */
- self_do_play (self);
- }
-
- signal first NONE (NONE)
- void do_play (self)
- {
- //g_warning ("item %s received do_play signal", self->nick);
- }
-
- signal first NONE (NONE)
- void real_play (self)
- {
- //g_warning ("item %s received do_play signal", self->nick);
- }
-
-
- /* play */
- signal first NONE (BOOLEAN)
- void play_finished (self, gboolean stopped)
- {
- //g_warning("item : play_finished %s", self->nick);
- if ((!self->_priv->has_played) || (!self->_priv->playing) || stopped) {
- self->_priv->started = FALSE;
- self->_priv->has_played = FALSE;
- }
- }
-
- signal last NONE (NONE)
- void play_started (self)
- {
- self->_priv->started = TRUE;
- }
-
- private void child_play_finished (GC:Sound:Item *item, gboolean stopped, gpointer data)
- {
- if ( GC_SOUND_ITEM(data)->_priv->has_played )
- self_play_next(GC_SOUND_ITEM(data), stopped);
- }
-
- private void child_play_started (GC:Sound:Item *item, gpointer data)
- {
- if (! GC_SOUND_ITEM(data)->_priv->started)
- self_play_started(GC_SOUND_ITEM(data));
- }
-
- protected gboolean play_next (self, gboolean stopped)
- {
- gboolean ret;
-
- //g_warning("play_next %s %d", self->nick, stopped);
-
- if (stopped) {
- gc_sound_item_play_finished(self, TRUE);
- return TRUE;
- }
-
- if (self->mute)
- return FALSE;
-
- /* mark if we are in play tree */
- self->_priv->has_played = TRUE;
-
- if (g_list_length(self->_priv->PlayList) == 0)
- return FALSE;
-
- if (self->_priv->playing == NULL)
- self->_priv->playing = g_list_first(self->_priv->PlayList);
- else
- self->_priv->playing = g_list_next (self->_priv->playing );
-
- if ((self->_priv->playing == NULL) && (self->loop)) {
- //g_warning ("looping on %s", self->nick);
- self->_priv->playing = g_list_first (self->_priv->PlayList );
- }
-
- while (self->_priv->playing) {
- if ( GC_SOUND_ITEM(self->_priv->playing->data) == self){
- if (!self->_priv->started)
- self_play_started(self);
- self_real_play(self);
- return TRUE;
- }
- else {
- ret= self_play_next ( GC_SOUND_ITEM(self->_priv->playing->data), FALSE);
- if (ret)
- return ret;
- }
- self->_priv->playing = g_list_next (self->_priv->playing );
- }
-
- /* if we have play, it's finished */
- if (self->_priv->started) {
- self_play_finished(self, FALSE);
- }
-
- return FALSE;
- }
-
-
-}
diff --git a/src/gc_sound/src/gc-sound-item.h b/src/gc_sound/src/gc-sound-item.h
new file mode 100644
index 0000000..534252e
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-item.h
@@ -0,0 +1,104 @@
+/* gcompris - gc-sound-item.h
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ *
+ * 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
+ */
+#ifndef __GC_SOUND_ITEM_H__
+#define __GC_SOUND_ITEM_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _GCSoundItem GCSoundItem;
+typedef struct _GCSoundItemClass GCSoundItemClass;
+
+
+G_END_DECLS
+#include <gc-sound-channel.h>
+G_BEGIN_DECLS
+
+
+#define GC_TYPE_SOUND_ITEM (gc_sound_item_get_type())
+#define GC_SOUND_ITEM(i) (G_TYPE_CHECK_INSTANCE_CAST((i), GC_TYPE_SOUND_ITEM, GCSoundItem))
+#define GC_SOUND_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), GC_TYPE_SOUND_ITEM, GCSoundItemClass))
+#define GC_IS_SOUND_ITEM(i) (G_TYPE_CHECK_INSTANCE_TYPE((i), GC_TYPE_SOUND_ITEM))
+#define GC_IS_SOUND_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE((c), GC_TYPE_SOUND_ITEM))
+#define GC_SOUND_ITEM_GET_CLASS(i) (G_TYPE_INSTANCE_GET_CLASS((i), GC_TYPE_SOUND_ITEM, GCSoundItemClass))
+
+GType gc_sound_item_get_type(void);
+
+struct _GCSoundItem {
+ GObject __parent__;
+
+ gdouble volume;
+ gboolean mute;
+
+ GCSoundPolicy policy;
+ //gint policy;
+ gboolean loop;
+
+ gchar* filename;
+
+ GCSoundChannel* channel;
+ GCSoundItem* parent;
+ GList* children;
+
+ //debug. will be removed
+ gchar * nick;
+
+ //internal use
+ // TRUE if we are in running play tree.
+ gboolean has_played;
+
+ // our group already started
+ gboolean started;
+
+ // child we are playing
+ GList *playing;
+};
+
+struct _GCSoundItemClass {
+ GObjectClass __parentClass__;
+
+ /* signal handlers */
+ void (* real_play) (GCSoundItem * self);
+ void (* play_start) (GCSoundItem * self);
+ void (* play_end) (GCSoundItem * self, gboolean stopped);
+ void (* chunk_start) (GCSoundItem * self);
+ void (* chunk_end) (GCSoundItem * self, gboolean stopped);
+
+};
+
+// internal use
+gboolean gc_sound_item_run_next (GCSoundItem *self,
+ gboolean stopped);
+
+GCSoundItem * gc_sound_item_append_child (GCSoundItem *self);
+
+gboolean gc_sound_item_play (GCSoundItem *self);
+
+void gc_sound_item_set_filename (GCSoundItem *self, gchar *filename);
+
+gchar * gc_sound_item_get_filename (GCSoundItem *self);
+
+void gc_sound_item_set_loop(GCSoundItem *self, gboolean loop);
+
+G_END_DECLS
+
+#endif
diff --git a/src/gc_sound/src/gc-sound-marshallers.c b/src/gc_sound/src/gc-sound-marshallers.c
new file mode 100644
index 0000000..6666255
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-marshallers.c
@@ -0,0 +1,56 @@
+#include <gc-sound-marshallers.h>
+
+#include <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:VOID (marshallers.list:1) */
+
+/* VOID:BOOLEAN (marshallers.list:2) */
+
+/* VOID:OBJECT (marshallers.list:3) */
+
diff --git a/src/gc_sound/src/gc-sound-marshallers.h b/src/gc_sound/src/gc-sound-marshallers.h
new file mode 100644
index 0000000..17bf6c5
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-marshallers.h
@@ -0,0 +1,21 @@
+
+#ifndef __gc_sound_marshal_MARSHAL_H__
+#define __gc_sound_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:VOID (marshallers.list:1) */
+#define gc_sound_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID
+
+/* VOID:BOOLEAN (marshallers.list:2) */
+#define gc_sound_marshal_VOID__BOOLEAN g_cclosure_marshal_VOID__BOOLEAN
+
+/* VOID:OBJECT (marshallers.list:3) */
+#define gc_sound_marshal_VOID__OBJECT g_cclosure_marshal_VOID__OBJECT
+
+G_END_DECLS
+
+#endif /* __gc_sound_marshal_MARSHAL_H__ */
+
diff --git a/src/gc_sound/src/gc-sound-mixer-SDL.c b/src/gc_sound/src/gc-sound-mixer-SDL.c
new file mode 100644
index 0000000..d389301
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-mixer-SDL.c
@@ -0,0 +1,456 @@
+/* gcompris - gc-sound-mixer-SDL.c
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ * 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 <gc-sound-mixer-SDL.h>
+#include <gc-sound-marshallers.h>
+
+#include <SDL.h>
+#include <SDL_thread.h>
+#include <SDL_mixer.h>
+#include <SDL_audio.h>
+
+/* signals */
+enum {
+ CHANNEL_FINISHED, /* internal: real launch play*/
+
+ PAUSED,
+ RESUMED,
+ HALTED,
+ DESTROY,
+
+ N_SIGNALS
+};
+
+guint gc_sound_mixer_SDL_signals[N_SIGNALS] = {0};
+
+static GCSoundMixerSDL *running_mixer = NULL;
+
+GCSoundMixer *gc_sound_mixer_SDL_new(void)
+{
+ return GC_SOUND_MIXER(g_object_new(GC_TYPE_SOUND_MIXER_SDL, NULL));
+}
+
+gboolean
+gc_sound_mixer_SDL_open_audio (GCSoundMixer* mixer)
+{
+ int audio_rate,audio_channels;
+ Uint16 audio_format;
+ int audio_buffers=2048;
+ int bits = 0;
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ if (self->audio_opened){
+ g_warning("Audio already opened !");
+ return FALSE;
+ }
+
+ // initialize sdl mixer, open up the audio device
+ if(Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,audio_buffers)<0){
+ g_warning("GCSoundMixer can not open audio dev");
+ return FALSE;
+ }
+
+ self->audio_opened = FALSE;
+
+ // print out some info on the audio device and stream
+ Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
+ bits=audio_format&0xFF;
+ Mix_AllocateChannels(g_hash_table_size(self->channels_from_pointer));
+ g_warning("Opened audio at %d Hz %d bit %s, %d bytes audio buffer number of channels %d",
+ audio_rate,
+ bits,
+ audio_channels>1?"stereo":"mono",
+ audio_buffers,
+ g_hash_table_size(self->channels_from_pointer));
+ return TRUE;
+}
+
+gboolean
+gc_sound_mixer_SDL_close_audio (GCSoundMixer * mixer)
+{
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ if (!self->audio_opened)
+ {
+ g_warning ("Audio is not opened !");
+ return FALSE;
+ }
+ Mix_CloseAudio();
+ g_warning("Closing audio");
+ self->audio_opened = FALSE;
+ return TRUE;
+}
+
+static GCSoundChannel *gc_sound_mixer_SDL_new_channel (GCSoundMixer * mixer)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ g_warning ("gc_sound_mixer_SDL_new_channel");
+
+ GCSoundChannel *channel = GC_SOUND_CHANNEL(g_object_new(GC_TYPE_SOUND_CHANNEL,
+ "mixer", self, NULL));
+
+ g_assert (channel != 0);
+
+ channel->channel_number = g_hash_table_size(self->channels_from_pointer);
+
+ g_warning ("inserting channel %d into tables", channel->channel_number);
+ g_hash_table_insert (self->channels_from_pointer,
+ channel,
+ GINT_TO_POINTER(channel->channel_number));
+
+ g_hash_table_insert (self->channels_to_pointer,
+ &(channel->channel_number),
+ channel);
+
+ Mix_AllocateChannels(channel->channel_number + 1);
+
+ g_warning ("Numbers of channels allocated %d", Mix_AllocateChannels(-1));
+
+ return channel;
+ }
+
+
+gboolean gc_sound_mixer_SDL_pause (GCSoundMixer * mixer)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ if (self->paused){
+ g_warning ("gc_sound_mixer_SDL_pause : Already paused !");
+ return FALSE;
+ }
+
+ Mix_Pause(-1);
+ self->paused = TRUE;
+ }
+
+gboolean
+gc_sound_mixer_SDL_resume (GCSoundMixer * mixer)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ if (!self->paused){
+ g_warning ("gc_sound_mixer_SDL_resume : Not paused !");
+ return FALSE;
+ }
+ Mix_Resume(-1);
+ self->paused = FALSE;
+ }
+
+gboolean
+gc_sound_mixer_SDL_halt (GCSoundMixer * mixer)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ Mix_HaltChannel(-1);
+ }
+
+gboolean
+gc_sound_mixer_SDL_pause_channel (GCSoundMixer * mixer, GCSoundChannel * channel)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+ g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+ int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
+ channel);
+
+ Mix_Pause (channel_number);
+ }
+
+gboolean
+gc_sound_mixer_SDL_resume_channel (GCSoundMixer * mixer, GCSoundChannel * channel)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+ g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
+ channel);
+
+ Mix_Resume (channel_number);
+ return TRUE;
+ }
+
+
+gboolean
+gc_sound_mixer_SDL_halt_channel (GCSoundMixer * mixer, GCSoundChannel * channel)
+ {
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+ g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
+ channel);
+
+ Mix_HaltChannel (channel_number);
+
+ return TRUE;
+ }
+
+
+gboolean
+gc_sound_mixer_SDL_play_item (GCSoundMixer * mixer, GCSoundChannel * channel, GCSoundItem *item )
+ {
+ Mix_Chunk *sample;
+
+ GCSoundMixerSDL* self;
+
+ g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
+ g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
+
+ self = GC_SOUND_MIXER_SDL(mixer);
+
+ int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
+ channel);
+
+ if (Mix_Playing(channel_number)){
+ g_warning("Channel busy ? no play!");
+ return FALSE;
+ }
+
+ if (item->filename == NULL){
+ g_warning("No filename ? no play!");
+ return FALSE;
+ }
+
+ sample = Mix_LoadWAV_RW(SDL_RWFromFile(item->filename, "rb"), 1);
+ if (!sample) {
+ g_warning("Sample music %s cannot be load", item->filename);
+ return FALSE;
+ }
+
+ if ((item->volume == -1.0) || (item->volume > channel->volume))
+ Mix_VolumeChunk(sample, (int ) channel->volume * MIX_MAX_VOLUME);
+ else
+ Mix_VolumeChunk(sample, (int) item->volume * MIX_MAX_VOLUME);
+
+ if (Mix_PlayChannel(channel_number, sample, 0)==-1) {
+ g_warning("Channel cannot play music %s", item->filename);
+ Mix_FreeChunk (sample);
+ return FALSE;
+ }
+
+ g_hash_table_insert( self->samples, channel, sample);
+
+ g_warning("Playing %s on channel #%d", item->filename, channel_number);
+
+ return TRUE;
+ }
+
+void channel_finished_cb (int channel_number)
+ {
+ GCSoundMixerSDL* self = running_mixer;
+
+ g_warning("Channel number %d size %d",
+ channel_number,
+ g_hash_table_size(self->channels_to_pointer));
+
+ int cn = channel_number;
+
+ GCSoundChannel *channel = GC_SOUND_CHANNEL(g_hash_table_lookup (self->channels_to_pointer,
+ &cn));
+
+ g_return_if_fail(channel != NULL);
+ g_return_if_fail(GC_IS_SOUND_MIXER_SDL(self));
+ g_return_if_fail(GC_IS_SOUND_CHANNEL(channel));
+
+ g_signal_emit(self, gc_sound_mixer_SDL_signals[CHANNEL_FINISHED], 0, channel, NULL);
+
+ }
+
+
+static
+void gc_sound_mixer_SDL_channel_finished (GCSoundMixerSDL* self,
+ GCSoundChannel* channel)
+{
+ Mix_Chunk *sample;
+
+ sample = g_hash_table_lookup (self->samples, channel);
+ Mix_FreeChunk (sample);
+
+ g_signal_emit_by_name (channel, "chunk_end", 0, channel->stopped);
+}
+
+static void
+gc_sound_mixer_SDL_init (GCSoundMixerSDL* self)
+ {
+ /* SDL_mixer limitation */
+ if (running_mixer != NULL)
+ g_error("Sorry, i can't allocate more than one mixer !!!");
+ running_mixer = self;
+
+ self->channels_from_pointer = g_hash_table_new (g_direct_hash,
+ g_direct_equal);
+ self->channels_to_pointer = g_hash_table_new (g_int_hash,
+ g_int_equal);
+ self->samples = g_hash_table_new (g_direct_hash,
+ g_direct_equal);
+ self->paused = FALSE;
+
+ if(SDL_Init(SDL_INIT_AUDIO)<0){
+ g_warning("SDL_init failed");
+ }
+ Mix_ChannelFinished(channel_finished_cb);
+
+ self->audio_opened = FALSE;
+
+ if (!gc_sound_mixer_SDL_open_audio (GC_SOUND_MIXER(self))) {
+ g_warning("gc_sound_mixer_SDL_init: cannot open audio !");
+ }
+
+
+
+ }
+
+enum {
+ PROP_0,
+ PROP_DEVICE,
+};
+
+
+static void
+gc_sound_mixer_SDL_finalize (GObject* object)
+ {
+ GCSoundMixerSDL * self = GC_SOUND_MIXER_SDL(object);
+
+ running_mixer = NULL;
+
+ g_hash_table_destroy (self->channels_from_pointer);
+ g_hash_table_destroy (self->channels_to_pointer);
+ g_hash_table_destroy (self->samples);
+
+ if (self->audio_opened)
+ Mix_CloseAudio();
+
+ SDL_Quit();
+ }
+
+
+static void
+gc_sound_mixer_SDL_get_property() {}
+
+static void
+gc_sound_mixer_SDL_set_property() {}
+
+static void
+gc_sound_mixer_SDL_class_init (GCSoundMixerSDLClass* self_class)
+ {
+ g_warning("gc_sound_mixer_SDL_class_init");
+
+ GObjectClass* go_class;
+
+ /* GObjectClass */
+ go_class = G_OBJECT_CLASS(self_class);
+ go_class->finalize = gc_sound_mixer_SDL_finalize;
+ go_class->get_property = gc_sound_mixer_SDL_get_property;
+ go_class->set_property = gc_sound_mixer_SDL_set_property;
+
+ _gc_sound_mixer_install_property( go_class, PROP_DEVICE);
+
+/* signals */
+/* enum { */
+/* CHANNEL_FINISHED, /\* internal: real launch play*\/ */
+
+/* PAUSED, */
+/* RESUMED, */
+/* HALTED, */
+/* DESTROY, */
+
+/* N_SIGNALS */
+/* }; */
+
+
+ self_class->channel_finished = gc_sound_mixer_SDL_channel_finished;
+
+ gc_sound_mixer_SDL_signals[CHANNEL_FINISHED] =
+ g_signal_new("channel_finished", /* name */
+ GC_TYPE_SOUND_MIXER_SDL, /* itype */
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION), /* flags */
+ G_STRUCT_OFFSET (GCSoundMixerSDLClass, channel_finished), /* offset function */
+ NULL, /* accumulator */
+ NULL, /* accu data */
+ gc_sound_marshal_VOID__OBJECT, /* marshal */
+ G_TYPE_NONE, /* return value */
+ 1, /* n_params */
+ GC_TYPE_SOUND_CHANNEL
+ );
+
+
+
+ }
+
+static void gc_init_sound_mixer (GCSoundMixerIface* iface);
+
+G_DEFINE_TYPE_WITH_CODE(GCSoundMixerSDL, gc_sound_mixer_SDL, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE(GC_TYPE_SOUND_MIXER, gc_init_sound_mixer));
+
+ void gc_init_sound_mixer (GCSoundMixerIface* iface)
+{
+ g_warning("Sound Mixer is initalized from SDL! ");
+
+ /* vtable */
+ iface->open_audio = gc_sound_mixer_SDL_open_audio;
+ iface->close_audio = gc_sound_mixer_SDL_close_audio;
+
+ iface->new_channel = gc_sound_mixer_SDL_new_channel;
+
+ iface->pause = gc_sound_mixer_SDL_pause;
+ iface->resume = gc_sound_mixer_SDL_resume;
+ iface->halt = gc_sound_mixer_SDL_halt;
+
+ iface->pause_channel = gc_sound_mixer_SDL_pause_channel;
+ iface->resume_channel = gc_sound_mixer_SDL_resume_channel;
+ iface->halt_channel = gc_sound_mixer_SDL_halt_channel;
+
+ iface->play_item = gc_sound_mixer_SDL_play_item;
+
+}
diff --git a/src/gc_sound/src/gc-sound-mixer-SDL.h b/src/gc_sound/src/gc-sound-mixer-SDL.h
new file mode 100644
index 0000000..59190bb
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-mixer-SDL.h
@@ -0,0 +1,110 @@
+/* gcompris - gc-sound-mixer-SDL.h
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ * 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
+ */
+
+#ifndef __GC_SOUND_MIXER_SDL_H__
+#define __GC_SOUND_MIXER_SDL_H__
+
+#include <gc-sound-mixer.h>
+#include <gc-sound-channel.h>
+#include <gc-sound-item.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GCSoundMixerSDL GCSoundMixerSDL;
+typedef struct _GCSoundMixerSDLClass GCSoundMixerSDLClass;
+
+#define GC_TYPE_SOUND_MIXER_SDL (gc_sound_mixer_SDL_get_type())
+#define GC_SOUND_MIXER_SDL(i) (G_TYPE_CHECK_INSTANCE_CAST((i), GC_TYPE_SOUND_MIXER_SDL, GCSoundMixerSDL))
+#define GC_SOUND_MIXER_SDL_CLASS(c) (G_TYPE_CHECK_CLASS_CAST((c), GC_TYPE_SOUND_MIXER_SDL, GCSoundMixerSDLClass))
+#define GC_IS_SOUND_MIXER_SDL(i) (G_TYPE_CHECK_INSTANCE_TYPE((i), GC_TYPE_SOUND_MIXER_SDL))
+#define GC_IS_SOUND_MIXER_SDL_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE((c), GC_TYPE_SOUND_MIXER_SDL))
+#define GC_SOUND_MIXER_SDL_GET_CLASS(i) (G_TYPE_INSTANCE_GET_CLASS((i), GC_TYPE_SOUND_MIXER_SDL, GCSoundMixerSDLClass))
+
+GType gc_sound_mixer_SDL_get_type(void);
+
+GCSoundMixer * gc_sound_mixer_SDL_new(void);
+
+/*
+gboolean gc_sound_mixer_SDL_open_audio (GCSoundMixerSDL * self);
+gboolean gc_sound_mixer_SDL_close_audio (GCSoundMixerSDL * self);
+
+GCSoundChannel * gc_sound_mixer_SDL_new_channel (GCSoundMixer * self);
+
+gboolean gc_sound_mixer_SDL_pause (GCSoundMixerSDL * self);
+gboolean gc_sound_mixer_SDL_resume (GCSoundMixerSDL * self);
+gboolean gc_sound_mixer_SDL_halt (GCSoundMixerSDL * self);
+
+gboolean gc_sound_mixer_SDL_pause_channel (GCSoundMixerSDL * self, GCSoundChannel * channel);
+gboolean gc_sound_mixer_SDL_resume_channel (GCSoundMixerSDL * self, GCSoundChannel * channel);
+gboolean gc_sound_mixer_SDL_halt_channel (GCSoundMixerSDL * self, GCSoundChannel * channel);
+
+gboolean gc_sound_mixer_SDL_play_item (GCSoundMixerSDL * self, GCSoundChannel * channel, GCSoundItem *item);
+*/
+
+struct _GCSoundMixerSDL {
+ GObject __parent__;
+
+ /* Is audio initiallised correctly */
+ gboolean audio_opened;
+ gboolean paused;
+
+ /* List of channels */
+ GHashTable *channels_from_pointer;
+ GHashTable *channels_to_pointer;
+ GHashTable *samples;
+
+ gboolean stopped;
+
+ // debug only. will be removed.
+ gchar* nick;
+};
+
+struct _GCSoundMixerSDLClass {
+ GInitiallyUnownedClass base_class;
+
+ /* vtable */
+ gboolean (* open_audio) (GCSoundMixerSDL * self);
+ gboolean (* close_audio) (GCSoundMixerSDL * self);
+
+ GCSoundChannel * (* new_channel) (GCSoundMixer * self);
+
+ gboolean (* pause) (GCSoundMixerSDL * self);
+ gboolean (* resume) (GCSoundMixerSDL * self);
+ gboolean (* halt) (GCSoundMixerSDL * self);
+
+ gboolean (* pause_channel) (GCSoundMixerSDL * self,
+ GCSoundChannel * channel);
+
+ gboolean (* resume_channel) (GCSoundMixerSDL * self,
+ GCSoundChannel * channel);
+
+ gboolean (* halt_channel) (GCSoundMixerSDL * self,
+ GCSoundChannel * channel);
+
+ gboolean (* play_item) (GCSoundMixerSDL * self,
+ GCSoundChannel * channel,
+ GCSoundItem * item);
+
+ void (* channel_finished) (GCSoundMixerSDL * self,
+ GCSoundChannel * channel);
+};
+
+G_END_DECLS
+
+#endif
diff --git a/src/gc_sound/src/gc-sound-mixer-private.h b/src/gc_sound/src/gc-sound-mixer-private.h
new file mode 100644
index 0000000..41ad6b6
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-mixer-private.h
@@ -0,0 +1,52 @@
+/* Generated by GOB (v2.0.14) (do not edit directly) */
+
+
+/* gcompris - gc-sound-mixer.gob
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ * 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
+ */
+
+#line 1 "gc-sound-mixer-SDL.gob"
+#line 25 "gc-sound-mixer-private.h"
+#ifndef __GC_SOUND_MIXER_PRIVATE_H__
+#define __GC_SOUND_MIXER_PRIVATE_H__
+
+#include "gc-sound-mixer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct _GCSoundMixerPrivate {
+#line 52 "gc-sound-mixer-SDL.gob"
+ int audio_buffers;
+#line 53 "gc-sound-mixer-SDL.gob"
+ int bits;
+#line 55 "gc-sound-mixer-SDL.gob"
+ GList * channels_list;
+#line 65 "gc-sound-mixer-SDL.gob"
+ gboolean audio_device;
+#line 108 "gc-sound-mixer-SDL.gob"
+ gboolean sdl_ok;
+#line 46 "gc-sound-mixer-private.h"
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/src/gc_sound/src/gc-sound-mixer.c b/src/gc_sound/src/gc-sound-mixer.c
new file mode 100644
index 0000000..703e2e9
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-mixer.c
@@ -0,0 +1,125 @@
+/* gcompris - gc-sound-mixer.c
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ * 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 <gc-sound-mixer.h>
+#include <gc-sound-mixer-SDL.h>
+
+gboolean
+gc_sound_mixer_open_audio (GCSoundMixer * self)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->open_audio (self);
+}
+
+gboolean
+gc_sound_mixer_close_audio (GCSoundMixer * self)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->close_audio (self);
+}
+
+GCSoundChannel *
+gc_sound_mixer_new_channel (GCSoundMixer * self)
+{
+ g_return_val_if_fail (GC_IS_SOUND_MIXER_SDL (self), (GCSoundChannel * )NULL);
+ g_assert (GC_SOUND_MIXER_GET_CLASS(self)->new_channel != 0);
+
+ return GC_SOUND_MIXER_GET_CLASS(self)->new_channel (self);
+}
+
+
+gboolean
+gc_sound_mixer_pause (GCSoundMixer * self)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->pause (self);
+}
+
+
+gboolean
+gc_sound_mixer_resume (GCSoundMixer * self)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->resume (self);
+}
+
+gboolean
+gc_sound_mixer_halt (GCSoundMixer * self)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->halt (self);
+}
+
+gboolean
+gc_sound_mixer_pause_channel (GCSoundMixer * self, GCSoundChannel * channel)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->pause_channel (self, channel);
+}
+
+gboolean
+gc_sound_mixer_resume_channel (GCSoundMixer * self, GCSoundChannel * channel)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->resume_channel (self, channel);
+}
+
+gboolean
+gc_sound_mixer_halt_channel (GCSoundMixer * self, GCSoundChannel * channel)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->halt_channel (self, channel);
+}
+
+gboolean
+gc_sound_mixer_play_item (GCSoundMixer * self, GCSoundChannel * channel, GCSoundItem *item)
+{
+ return GC_SOUND_MIXER_GET_CLASS(self)->play_item (self, channel, item);
+}
+
+
+/* GType stuff */
+static void gc_sound_mixer_iface_init(gpointer iface);
+
+GType
+gc_sound_mixer_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (GCSoundMixerIface),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gc_sound_mixer_iface_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_INTERFACE, "GCSoundMixer", &info, 0);
+ g_type_interface_add_prerequisite(type, G_TYPE_OBJECT);
+ }
+ return type;
+}
+
+void _gc_sound_mixer_install_property(GObjectClass* go_class, gboolean device_id){
+ g_object_class_override_property(go_class, device_id, "device");
+}
+
+static void
+gc_sound_mixer_iface_init(gpointer iface) {
+ g_object_interface_install_property(iface,
+ g_param_spec_boolean ("device",
+ "device",
+ "Device",
+ FALSE,
+ G_PARAM_READABLE));
+}
diff --git a/src/gc_sound/src/gc-sound-mixer.gob b/src/gc_sound/src/gc-sound-mixer.gob
deleted file mode 100644
index 3fca60f..0000000
--- a/src/gc_sound/src/gc-sound-mixer.gob
+++ /dev/null
@@ -1,156 +0,0 @@
-%alltop{/* gcompris - gc-sound-mixer.gob
- *
- * Copyright (C) 2006 Yves Combe
- *
- * 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
- */
-%}
-
-requires 2.0.0
-
-%{
-#include "gc-sound-mixer.h"
-#include "gc-sound-channel.h"
-#include "SDL.h"
-#include "SDL_thread.h"
-#include "SDL_mixer.h"
-#include "SDL_audio.h"
-#include "libintl.h"
-
-#define _(String) gettext (String)
-#define gettext_noop(String) String
-
-#ifndef N_
-#define N_(String) gettext_noop (String)
-#endif
-
-#include "gc-sound-mixer-private.h"
-%}
-
-%h{
-#ifndef __TYPEDEF_GC_SOUND_CHANNEL__
-#define __TYPEDEF_GC_SOUND_CHANNEL__
-typedef struct _GCSoundChannel GCSoundChannel;
-#endif
-%}
-class GC:Sound:Mixer from G:Object {
- public gchar *nick = {NULL};
- protected int channels = { 0 };
-
- private int audio_buffers=2048;
- private int bits = 0;
-
- private G:List *channels_list = { NULL }
- destroy {
- GList *chan;
- for (chan = channels_list; chan != NULL; chan = g_list_next (chan)) {
- g_object_unref (chan);
- }
-
- g_list_free (channels_list);
- };
-
- private gboolean audio_device = { FALSE}
- destroy {
- self_set_audio_device(self, FALSE);
- if (self->_priv->sdl_ok)
- SDL_Quit();
- };
-
- property BOOLEAN audio_device
- ( nick = _("Audio device opened"),
- blurb = _("Open and close the audio device"),
- export )
- set {
- int audio_rate,audio_channels;
- Uint16 audio_format;
-
- gboolean val = g_value_get_boolean (VAL);
- if ( val != self->_priv->audio_device) {
- if (val) {
- // initialize sdl mixer, open up the audio device
- if(Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,self->_priv->audio_buffers)<0){
- g_warning("GCSoundMixer can not open audio dev");
- return;
- }
-
- // print out some info on the audio device and stream
- Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
- self->_priv->bits=audio_format&0xFF;
- Mix_AllocateChannels(self->channels );
- g_warning("Opened audio at %d Hz %d bit %s, %d bytes audio buffer\n Number of channels %d", audio_rate,
- self->_priv->bits, audio_channels>1?"stereo":"mono", self->_priv->audio_buffers, self->channels);
-
- Mix_AllocateChannels(self->channels );
- } else {
- Mix_CloseAudio();
- g_warning("Closing audio");
- }
-
- self->_priv->audio_device = val;
- }
- }
- get { g_value_set_boolean (VAL, self->_priv->audio_device); };
-
-
- private gboolean sdl_ok = { FALSE };
-
- init (self) {
- //g_warning("gc mixer init");
-
- // initialize SDL for audio
- if(SDL_Init(SDL_INIT_AUDIO)<0){
- g_warning("SDL_init failed");
- self->_priv->sdl_ok = FALSE;
- } else
- self->_priv->sdl_ok = TRUE;
-
- self_set_audio_device(self, TRUE);
-}
-
- class_init (class) {
- //g_warning("gc mixer class init");
-
- }
-
- public GC:Sound:Mixer *
- new (void)
- {
- return (GCSoundMixer *)GET_NEW;
- }
-
- public void close_audio(self)
- {
- self_set_audio_device( self, FALSE);
- }
- public void open_audio(self)
- {
- self_set_audio_device( self, TRUE);
- }
-
- public GC:Sound:Channel *
- new_channel(self)
- {
- GCSoundChannel *new_channel;
-
- new_channel = GC_SOUND_CHANNEL(g_object_new(gc_sound_channel_get_type(), "mixer", self, NULL));
- g_object_ref (new_channel);
-
- self->_priv->channels_list = g_list_append(self->_priv->channels_list, new_channel);
-
- return new_channel;
- }
-
-}
diff --git a/src/gc_sound/src/gc-sound-mixer.h b/src/gc_sound/src/gc-sound-mixer.h
new file mode 100644
index 0000000..8bb8a9e
--- /dev/null
+++ b/src/gc_sound/src/gc-sound-mixer.h
@@ -0,0 +1,97 @@
+/* gcompris - gc-sound-mixer.h
+ *
+ * Copyright (C) 2006 Yves Combe
+ *
+ * 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
+ */
+
+#ifndef __GC_SOUND_MIXER_H__
+#define __GC_SOUND_MIXER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Main interface structure
+ */
+typedef struct _GCSoundMixer GCSoundMixer;
+typedef struct _GCSoundMixerIface GCSoundMixerIface;
+
+G_END_DECLS
+
+#include <gc-sound-channel.h>
+#include <gc-sound-item.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GC_TYPE_SOUND_MIXER (gc_sound_mixer_get_type())
+#define GC_SOUND_MIXER(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), GC_TYPE_SOUND_MIXER, GCSoundMixer)
+#define GC_IS_SOUND_MIXER(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), GC_TYPE_SOUND_MIXER)
+#define GC_SOUND_MIXER_GET_CLASS(obj) G_TYPE_INSTANCE_GET_INTERFACE((obj), GC_TYPE_SOUND_MIXER, GCSoundMixerIface)
+
+GType gc_sound_mixer_get_type(void);
+
+void _gc_sound_mixer_install_property (GObjectClass* go_class,
+ gboolean device_id);
+
+gboolean gc_sound_mixer_open_audio (GCSoundMixer * self);
+gboolean gc_sound_mixer_close_audio (GCSoundMixer * self);
+
+GCSoundChannel * gc_sound_mixer_new_channel (GCSoundMixer * self);
+
+gboolean gc_sound_mixer_pause (GCSoundMixer * self);
+gboolean gc_sound_mixer_resume (GCSoundMixer * self);
+gboolean gc_sound_mixer_halt (GCSoundMixer * self);
+
+gboolean gc_sound_mixer_pause_channel (GCSoundMixer * self, GCSoundChannel * channel);
+gboolean gc_sound_mixer_resume_channel (GCSoundMixer * self, GCSoundChannel * channel);
+gboolean gc_sound_mixer_halt_channel (GCSoundMixer * self, GCSoundChannel * channel);
+
+gboolean gc_sound_mixer_play_item (GCSoundMixer * self, GCSoundChannel * channel, GCSoundItem *item);
+
+struct _GCSoundMixerIface {
+ GTypeInterface base_iface;
+
+ /* vtable */
+ gboolean (* open_audio) (GCSoundMixer * self);
+ gboolean (* close_audio) (GCSoundMixer * self);
+
+ GCSoundChannel * (* new_channel) (GCSoundMixer * self);
+
+ gboolean (* pause) (GCSoundMixer * self);
+ gboolean (* resume) (GCSoundMixer * self);
+ gboolean (* halt) (GCSoundMixer * self);
+
+ gboolean (* pause_channel) (GCSoundMixer * self,
+ GCSoundChannel * channel);
+
+ gboolean (* resume_channel) (GCSoundMixer * self,
+ GCSoundChannel * channel);
+
+ gboolean (* halt_channel) (GCSoundMixer * self,
+ GCSoundChannel * channel);
+
+ gboolean (* play_item) (GCSoundMixer * self,
+ GCSoundChannel * channel,
+ GCSoundItem *item);
+};
+
+G_END_DECLS
+
+#endif
diff --git a/src/gc_sound/src/gc-sound.h b/src/gc_sound/src/gc-sound.h
index f87863f..228b193 100644
--- a/src/gc_sound/src/gc-sound.h
+++ b/src/gc_sound/src/gc-sound.h
@@ -21,5 +21,6 @@
*/
#include <gc-sound-mixer.h>
+#include <gc-sound-mixer-SDL.h>
#include <gc-sound-channel.h>
#include <gc-sound-item.h>
diff --git a/src/gc_sound/src/marshallers.list b/src/gc_sound/src/marshallers.list
new file mode 100644
index 0000000..2fbec7d
--- /dev/null
+++ b/src/gc_sound/src/marshallers.list
@@ -0,0 +1,3 @@
+VOID:VOID
+VOID:BOOLEAN
+VOID:OBJECT
diff --git a/src/gc_sound/src/test_gc_sound.c b/src/gc_sound/src/test_gc_sound.c
index 8ae03cc..6ae45d0 100644
--- a/src/gc_sound/src/test_gc_sound.c
+++ b/src/gc_sound/src/test_gc_sound.c
@@ -16,12 +16,12 @@ main (int argc, char *argv)
{
GCSoundMixer *gcmix;
GCSoundChannel* gcchan1, *gcchan2;
- GCSoundItem *item1, *item2, *item3, *root1, *root2, *item1_1, *item1_2;
- g_type_init ();
+ GCSoundItem *item1, *item2, *item3, *root1, *root2, *item1_1, *item1_2;
+ g_type_init ();
/* Sound mixer opens SDL and audio device */
- gcmix = gc_sound_mixer_new();
- gcmix->nick = "gcmix";
+ gcmix = gc_sound_mixer_SDL_new();
+ GC_SOUND_MIXER_SDL(gcmix)->nick = "gcmix";
/* We open two chans to play simultaneously */
gcchan1 = gc_sound_mixer_new_channel(gcmix);
@@ -29,20 +29,34 @@ main (int argc, char *argv)
gcchan1->nick = "gcchan1";
gcchan2->nick = "gcchan2";
+ //g_warning ("nick of mixer %s %s", GC_SOUND_MIXER_SDL(gcchan1->mixer)->nick,
+ // GC_SOUND_MIXER_SDL(gcchan2->mixer)->nick);
+ GCSoundMixer *gcmix2;
+
+ g_object_get(G_OBJECT(gcchan2), "mixer", &gcmix2, NULL);
+
+ g_warning ("g_object_get return mixer %s", GC_SOUND_MIXER_SDL(gcmix2)->nick);
/* Each chan has a root item, where we group the sounds to play in that channel*/
- root1 = GC_SOUND_ITEM(gc_sound_channel_get_rootItem(gcchan1));
- root2 = GC_SOUND_ITEM(gc_sound_channel_get_rootItem(gcchan2));
+ root1 = GC_SOUND_ITEM(gc_sound_channel_get_root(gcchan1));
+ root2 = GC_SOUND_ITEM(gc_sound_channel_get_root(gcchan2));
root1->nick="root1";
root2->nick="root2";
/* create new item for our sounds */
- item1 = gc_sound_item_new (root1);
- item2 = gc_sound_item_new (root2);
- item3 = gc_sound_item_new (root2);
- item1_1 = gc_sound_item_new (item1);
+ item1 = gc_sound_item_append_child (root1);
+ item2 = gc_sound_item_append_child (root2);
+ item3 = gc_sound_item_append_child (root2);
+ item1_1 = gc_sound_item_append_child (item1);
+
+ item1_2 = gc_sound_item_append_child (item1);
+
+ GCSoundChannel *gcc2;
+ g_object_get(G_OBJECT(item2), "channel", &gcc2, NULL);
+
+ g_warning ("g_object_get return channel %s", GC_SOUND_CHANNEL(gcc2)->nick);
+
- item1_2 = gc_sound_item_new (item1);
item1->nick = "item1";
item2->nick = "item2";
item3->nick = "item3";
@@ -64,31 +78,37 @@ main (int argc, char *argv)
gc_sound_item_set_policy(item3, GC_SOUND_INTERRUPT_AND_PLAY);
// callback connection
- gc_sound_item_connect__play_finished(item2, finish, NULL);
- gc_sound_item_connect__play_finished(item3, finish, NULL);
- gc_sound_item_connect__play_started(item1_1, start, NULL);
- gc_sound_item_connect__play_started(item1_2, start, NULL);
+ //gc_sound_item_connect__play_finished(item2, finish, NULL);
+ //gc_sound_item_connect__play_finished(item3, finish, NULL);
+ //gc_sound_item_connect__play_started(item1_1, start, NULL);
+ //gc_sound_item_connect__play_started(item1_2, start, NULL);
+ g_signal_connect( item2, "play_end", finish, NULL);
+ g_signal_connect( item2, "play_end", finish, NULL);
+ g_signal_connect( item1_1, "play_start", start, NULL);
+ g_signal_connect( item1_2, "play_start", start, NULL);
+
- // test mute
- //gc_sound_item_set_mute(item1_1, TRUE);
+/* // test mute */
+/* //gc_sound_item_set_mute(item1_1, TRUE); */
- gc_sound_item_set_loop(item1, TRUE);
+ gc_sound_item_set_loop(item1, TRUE);
- //play
- gc_sound_item_play(item2);
- g_usleep(1000000);
+ //play
+ gc_sound_item_play(item2);
+ g_usleep(1000000);
- /* will loop with the two sounds of group */
- gc_sound_item_play(item1);
+ /* will loop with the two sounds of group */
+ gc_sound_item_play(item1);
- g_usleep(8000000);
+ g_usleep(8000000);
- //stopping loop after next
- gc_sound_item_set_loop(item1, FALSE);
- g_usleep(3000000);
+ //stopping loop after next
+ g_warning("stopping loop on item1");
+ gc_sound_item_set_loop(item1, FALSE);
+ g_usleep(3000000);
- //this will sop item2 because of policy
- gc_sound_item_play(item3);
+ //this will stop item2 because of policy
+ gc_sound_item_play(item3);
/* infinite loop */
g_main_loop_run(g_main_loop_new (NULL, FALSE));