diff options
author | Yves Combe <ycombe@src.gnome.org> | 2006-12-15 00:19:21 (GMT) |
---|---|---|
committer | Yves Combe <ycombe@src.gnome.org> | 2006-12-15 00:19:21 (GMT) |
commit | 140dc546466033a2ca7b96dd2384bc19b59e99f6 (patch) | |
tree | 71df8095ed5d619f500a7034350f1f584dde30ae | |
parent | 859668e6b119d86f593d81ee33482289575d1ecd (diff) |
GC_SOUND gc_sound_append_child now accepts varargs for item properties.
GC_SOUND
gc_sound_append_child now accepts varargs for item properties.
add destroy_after_play property to play and destroy and item.
fix GcSoundPOlicy names (NONE -> POLICY_NONE)
GCOMPRIS
change soundutil to use gc_sound
change config.c to use gc_sound
add mixer, channels music and fx in properties
change memory to use gc_sound (BROKEN now)
TODO
fix memory (policy and cards comparaison broken)
add gc_sound_item_from_gc_filename in python bindings
28 files changed, 389 insertions, 527 deletions
@@ -1,3 +1,59 @@ +2006-12-15 Yves Combe <yves@ycombe.net> + + GC_SOUND + gc_sound_append_child now accepts varargs for item properties. + add destroy_after_play property to play and destroy and item. + fix GcSoundPOlicy names (NONE -> POLICY_NONE) + + GCOMPRIS + change soundutil to use gc_sound + change config.c to use gc_sound + add mixer, channels music and fx in properties + change memory to use gc_sound (BROKEN now) + + TODO + fix memory (policy and cards comparaison broken) + add gc_sound_item_from_gc_filename in python bindings + + * boards/sounds/README: + * configure.in: + * src/boards/click_on_letter.c: (repeat): + * src/boards/erase.c: (start_board): + * src/boards/memory.c: (start_board), (end_board), (create_item), + (display_card), (sound_callback), (start_callback): + * src/boards/py-gcompris-properties.c: + (pyGcomprisPropertiesType_getattr): + * src/boards/py-mod-sound.c: (py_gc_sound_policy_set), + (py_gc_sound_policy_get), (python_gcompris_sound_module_init): + * src/gc_sound/ChangeLog: + * src/gc_sound/configure.in_ALONE: + * src/gc_sound/python/Makefile.am: + * src/gc_sound/python/demo.py: + * src/gc_sound/python/gc_sound.defs: + * src/gc_sound/python/gc_sound.override: + * src/gc_sound/src/Makefile.am: + * src/gc_sound/src/gc-sound-channel.c: (gc_sound_channel_play), + (root_destroyed): + * src/gc_sound/src/gc-sound-channel.h: + * src/gc_sound/src/gc-sound-item.c: (gc_sound_item_append_child), + (gc_sound_item_signal_play_end), (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.h: + * src/gc_sound/src/gc-sound-mixer-SDL.c: + (gc_sound_mixer_sdl_destroy): + * src/gc_sound/src/test_gc_sound.c: (main): + * src/gcompris/Makefile.am: + * src/gcompris/config.c: (item_event_ok): + * src/gcompris/gcompris.h: + * src/gcompris/properties.c: (gc_prop_new): + * src/gcompris/properties.h: + * src/gcompris/soundutil.c: (gc_sound_init), (gc_sound_close), + (gc_sound_reopen), (gc_sound_pause), (gc_sound_resume), + (gc_sound_policy_set), (gc_sound_policy_get), (gc_music_play), + (gc_sound_play_ogg_list), (gc_sound_item_from_gc_filename): + * src/gcompris/soundutil.h: + 2006-12-13 Yves Combe <yves@ycombe.net> Merge code with HEAD before integrating gc_sound in gcompris. diff --git a/boards/sounds/README b/boards/sounds/README index de0fad7..c0ed49b 100644 --- a/boards/sounds/README +++ b/boards/sounds/README @@ -4,4 +4,3 @@ From OpenOffice.org: apert2.wav From lincity-ng: Water5.wav Harbor1.wav Harbor3.wav From gaim: receive.wav From childsplay: eat.wav - diff --git a/configure.in b/configure.in index 75002ac..9c14085 100644 --- a/configure.in +++ b/configure.in @@ -46,6 +46,22 @@ LIBGNOMECANVAS_REQUIRED=2.3.6 PKG_CHECK_MODULES(GCOMPRIS, gtk+-2.0 >= $GTK_REQUIRED gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQUIRED libgnomecanvas-2.0 >= $LIBGNOMECANVAS_REQUIRED gthread-2.0) AC_CHECK_LIB(SDL_mixer, Mix_OpenAudio,, AC_MSG_ERROR([*** SDL_mixer not found. Visit http://www.libsdl.org and get it])) +AC_MSG_CHECKING([for gc_sound]) +pwd=`pwd` +GC_SOUND_CFLAGS="-I$pwd/src/gc_sound/src" +GC_SOUND_LIBS="$pwd/src/gc_sound/src/libgcsound-2.la" +AC_SUBST(GC_SOUND_CFLAGS) +AC_SUBST(GC_SOUND_LIBS) +AC_MSG_RESULT([$GC_SOUND_CFLAGS]) + +PKG_CHECK_MODULES(GOBJECT,[ + glib-2.0 >= 2.10.0 + gobject-2.0 >= 2.8.0 + ]) + +GCOMPRIS_CFLAGS="$GCOMPRIS_CFLAGS $GC_SOUND_CFLAGS" +GCOMPRIS_LIBS="$GCOMPRIS_LIBS $GC_SOUND_LIBS" + AC_SUBST(GCOMPRIS_CFLAGS) AC_SUBST(GCOMPRIS_LIBS) diff --git a/src/boards/click_on_letter.c b/src/boards/click_on_letter.c index 409d1cc..4e42fe3 100644 --- a/src/boards/click_on_letter.c +++ b/src/boards/click_on_letter.c @@ -78,8 +78,6 @@ static gchar *right_letter; static gchar *alphabet; -static void sound_played(gchar *file); - static gboolean uppercase_only; /* Description of this plugin */ @@ -241,7 +239,7 @@ static void repeat () g_free(str1); if(right_letter_ogg) { - gc_sound_play_ogg_cb(right_letter_ogg, sound_played); + gc_sound_play_ogg(right_letter_ogg); } g_free(right_letter_ogg); @@ -659,8 +657,3 @@ config_stop() { } -static void -sound_played (gchar *file) -{ - g_warning ("Sound_played %s\n", file); -} diff --git a/src/boards/erase.c b/src/boards/erase.c index 174c0cb..0a07713 100644 --- a/src/boards/erase.c +++ b/src/boards/erase.c @@ -28,7 +28,7 @@ typedef struct {gint count; gint max;} counter; static GcomprisBoard *gcomprisBoard = NULL; static gboolean board_paused = TRUE; -static SoundPolicy sound_policy; +static GcSoundPolicy sound_policy; static void start_board (GcomprisBoard *agcomprisBoard); @@ -219,7 +219,7 @@ static void start_board (GcomprisBoard *agcomprisBoard) /* initial state to restore */ sound_policy = gc_sound_policy_get(); - gc_sound_policy_set(PLAY_AND_INTERRUPT); + gc_sound_policy_set(INTERRUPT_AND_PLAY); gc_cursor_set(GCOMPRIS_DEL_CURSOR); diff --git a/src/boards/memory.c b/src/boards/memory.c index df51ad0..f69a162 100644 --- a/src/boards/memory.c +++ b/src/boards/memory.c @@ -108,6 +108,7 @@ typedef struct { GnomeCanvasItem *frontcardItem; gboolean hidden; gchar *second_value; + GcSoundItem *sound_item; } MemoryItem; static MemoryItem *firstCard = NULL; @@ -156,8 +157,8 @@ static void player_win(); static void display_card(MemoryItem *memoryItem, CardStatus cardStatus); -static void sound_callback(gchar *file); -static void start_callback(gchar *file); +static void sound_callback(GcSoundItem *item, gboolean stopped, gpointer data); +static void start_callback(GcSoundItem *item, gboolean stopped, gpointer data); static gboolean playing_sound = FALSE; // Number of images for x and y by level @@ -276,7 +277,7 @@ static gchar *soundList[] = #define NUMBER_OF_SOUNDS G_N_ELEMENTS(soundList) -static SoundPolicy sound_policy; +static GcSoundPolicy sound_policy; /* Description of this plugin */ static BoardPlugin menu_bp = @@ -685,6 +686,7 @@ static void pause_board (gboolean pause) */ static void start_board (GcomprisBoard *agcomprisBoard) { + GcSoundItem *item; if(agcomprisBoard!=NULL) { @@ -819,7 +821,7 @@ static void start_board (GcomprisBoard *agcomprisBoard) /* initial state to restore */ sound_policy = gc_sound_policy_get(); - gc_sound_policy_set(PLAY_AND_INTERRUPT); + gc_sound_policy_set(INTERRUPT_AND_PLAY); gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "images/gcompris_band.png"); base_x1 = BASE_SOUND_X1; @@ -891,7 +893,10 @@ static void start_board (GcomprisBoard *agcomprisBoard) to_tux = FALSE; if (currentUiMode == UIMODE_SOUND){ playing_sound = TRUE; - gc_sound_play_ogg_cb("sounds/LuneRouge/musique/LRBuddhist_gong_05_by_Lionel_Allorge.ogg",start_callback); + item = gc_sound_item_from_gc_filename("sounds/LuneRouge/musique/LRBuddhist_gong_05_by_Lionel_Allorge.ogg", NULL); + + g_object_connect(G_OBJECT(item), "play_end",(GCallback) start_callback, NULL); + gc_sound_item_play(item); } else playing_sound = FALSE; @@ -904,6 +909,7 @@ end_board () { if (currentUiMode == UIMODE_SOUND) { gc_sound_policy_set(sound_policy); + gc_sound_object_destroy(GC_SOUND_OBJECT(gc_sound_channel_get_root(gc_prop_get()->fx_chan))); gc_sound_resume(); } @@ -1340,6 +1346,10 @@ static void create_item(GnomeCanvasGroup *parent) "height_set", TRUE, NULL); gdk_pixbuf_unref(pixmap); + + memoryItem->sound_item = \ + gc_sound_item_from_gc_filename( memoryItem->data, NULL); + g_object_connect(memoryItem->sound_item, "play_end", (GCallback) sound_callback, NULL); } else { if(memoryItem->type == TYPE_IMAGE) { @@ -1425,7 +1435,7 @@ static void display_card(MemoryItem *memoryItem, CardStatus cardStatus) gnome_canvas_item_hide(memoryItem->backcardItem); gnome_canvas_item_show(memoryItem->frontcardItem); playing_sound = TRUE; - gc_sound_play_ogg_cb (memoryItem->data, sound_callback); + gc_sound_item_play(memoryItem->sound_item); break; case ON_BACK: gnome_canvas_item_show(memoryItem->backcardItem); @@ -1806,13 +1816,11 @@ static gint tux_play(){ return FALSE; } -static void sound_callback(gchar *file) +static void sound_callback(GcSoundItem *item, gboolean stopped, gpointer data) { if (! gcomprisBoard) return; - g_warning("sound_callback %s", file); - playing_sound = FALSE; if (currentMode == MODE_TUX){ if (to_tux) { @@ -1841,7 +1849,8 @@ static void sound_callback(gchar *file) } -static void start_callback(gchar *file){ +static void start_callback(GcSoundItem *item, gboolean stopped, gpointer data) +{ if (!gcomprisBoard) return; @@ -1849,4 +1858,5 @@ static void start_callback(gchar *file){ return; playing_sound = FALSE; + gc_sound_object_destroy(GC_SOUND_OBJECT(item)); } diff --git a/src/boards/py-gcompris-properties.c b/src/boards/py-gcompris-properties.c index 883eebc..91a24b1 100644 --- a/src/boards/py-gcompris-properties.c +++ b/src/boards/py-gcompris-properties.c @@ -160,6 +160,33 @@ pyGcomprisPropertiesType_getattr(pyGcomprisPropertiesObject *self, char *name) if(strcmp(name,"default_context")==0) return Py_BuildValue("s", self->cdata->default_context); + if(strcmp(name,"mixer")==0){ + if (self->cdata->mixer) + return (PyObject*) pygobject_new((GObject*)self->cdata->mixer); + else { + Py_INCREF(Py_None); + return Py_None; + } + } + + if(strcmp(name,"fx_chan")==0){ + if (self->cdata->fx_chan) + return (PyObject*) pygobject_new((GObject*)self->cdata->fx_chan); + else { + Py_INCREF(Py_None); + return Py_None; + } + } + + if(strcmp(name,"music_chan")==0){ + if (self->cdata->music_chan) + return (PyObject*) pygobject_new((GObject*)self->cdata->music_chan); + else { + Py_INCREF(Py_None); + return Py_None; + } + } + } return Py_FindMethod(pyGcomprisPropertiesType_methods, (PyObject *)self, name); } diff --git a/src/boards/py-mod-sound.c b/src/boards/py-mod-sound.c index 5cf3423..b88e857 100644 --- a/src/boards/py-mod-sound.c +++ b/src/boards/py-mod-sound.c @@ -165,57 +165,20 @@ void pyGcomprisSoundCallback(gchar *file){ } -static PyObject* -py_gc_sound_play_ogg_cb(PyObject* self, PyObject* args) -{ - gchar *file; - PyObject* pyCallback; - - /* Parse arguments */ - if(!PyArg_ParseTuple(args, - "sO:gc_sound_play_ogg_cb", - &file, - &pyCallback)) - return NULL; - - if(!PyCallable_Check(pyCallback)) - { - PyErr_SetString(PyExc_TypeError, - "gc_sound_play_ogg_cb second argument must be callable"); - return NULL; - } - - if (!py_sound_callbacks) - py_sound_callbacks = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - - g_hash_table_replace (py_sound_callbacks, - g_strdup(file), - pyCallback); - Py_INCREF(pyCallback); - - g_warning("py_gc_sound_play_ogg_cb %s", file); - - gc_sound_play_ogg_cb( file, - (GcomprisSoundCallback) pyGcomprisSoundCallback); - - /* Create and return the result */ - Py_INCREF(Py_None); - return Py_None; - -} - /* void gc_sound_policy_set(guint); */ static PyObject* py_gc_sound_policy_set(PyObject* self, PyObject* args) { - guint policy; + GcSoundPolicy policy; + PyObject *py_policy = NULL; + /* Parse arguments */ - if(!PyArg_ParseTuple(args, "i:gc_sound_policy_set",&policy)) + if(!PyArg_ParseTuple(args, "O:gc_sound_policy_set",&py_policy)) return NULL; + if (pyg_enum_get_value(GC_TYPE_SOUND_POLICY, py_policy, (gpointer)&policy)) + return NULL; + /* Call the corresponding C function */ gc_sound_policy_set(policy); @@ -228,16 +191,16 @@ py_gc_sound_policy_set(PyObject* self, PyObject* args) static PyObject* py_gc_sound_policy_get(PyObject* self, PyObject* args) { - guint policy; + GcSoundPolicy policy; + /* Parse arguments */ - if(!PyArg_ParseTuple(args, ":gc_sound_policy_set")) + if(!PyArg_ParseTuple(args, ":gc_sound_policy_get")) return NULL; /* Call the corresponding C function */ policy = gc_sound_policy_get(); - - /* Create and return the result */ - return Py_BuildValue("i", policy); + + return pyg_enum_from_gtype(GC_TYPE_SOUND_POLICY, policy); } @@ -248,7 +211,6 @@ static PyMethodDef PythonGcomprisSoundModule[] = { { "close", py_gc_sound_close, METH_VARARGS, "gc_sound_close" }, { "pause", py_gc_sound_pause, METH_VARARGS, "gc_sound_pause" }, { "resume", py_gc_sound_resume, METH_VARARGS, "gc_sound_resume" }, - { "play_ogg_cb", py_gc_sound_play_ogg_cb, METH_VARARGS, "gc_sound_play_ogg_cb" }, { "policy_get", py_gc_sound_policy_get, METH_VARARGS, "gc_sound_policy_get" }, { "policy_set", py_gc_sound_policy_set, METH_VARARGS, "gc_sound_policy_set" }, { NULL, NULL, 0, NULL} @@ -258,10 +220,6 @@ void python_gcompris_sound_module_init(void) { PyObject* module; module = Py_InitModule("_gcompris_sound", PythonGcomprisSoundModule); - - PyModule_AddIntConstant(module, "PLAY_ONLY_IF_IDLE", PLAY_ONLY_IF_IDLE ); - PyModule_AddIntConstant(module, "PLAY_AFTER_CURRENT", PLAY_AFTER_CURRENT ); - PyModule_AddIntConstant(module, "PLAY_AND_INTERRUPT", PLAY_AND_INTERRUPT ); } /* Some usefull code parts ... */ diff --git a/src/gc_sound/ChangeLog b/src/gc_sound/ChangeLog index f228e8f..d2f9a76 100644 --- a/src/gc_sound/ChangeLog +++ b/src/gc_sound/ChangeLog @@ -1,3 +1,26 @@ +2006-12-15 Yves Combe <yves@ycombe.net> + + gc_sound_append_child now accepts varargs for item properties. + add destroy_after_play property to play and destroy and item. + fix GcSoundPOlicy names (NONE -> POLICY_NONE) + + * configure.in_ALONE: + * python/Makefile.am: + * python/demo.py: + * python/gc_sound.defs: + * python/gc_sound.override: + * src/Makefile.am: + * src/gc-sound-channel.c: (gc_sound_channel_play), + (root_destroyed): + * src/gc-sound-channel.h: + * src/gc-sound-item.c: (gc_sound_item_append_child), + (gc_sound_item_signal_play_end), (gc_sound_item_init), + (gc_sound_item_get_property), (gc_sound_item_set_property), + (gc_sound_item_class_init): + * src/gc-sound-item.h: + * src/gc-sound-mixer-SDL.c: (gc_sound_mixer_sdl_destroy): + * src/test_gc_sound.c: (main): + 2006-12-12 Yves Combe <yves@ycombe.net> add demo.py little python demo. diff --git a/src/gc_sound/configure.in_ALONE b/src/gc_sound/configure.in_ALONE index 0401257..503b971 100644 --- a/src/gc_sound/configure.in_ALONE +++ b/src/gc_sound/configure.in_ALONE @@ -24,7 +24,7 @@ GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) AC_MSG_RESULT($GLIB_GENMARSHAL) -PKG_CHECK_MODULES(GC_SOUND,[ +PKG_CHECK_MODULES(GOBJECT,[ glib-2.0 >= 2.10.0 gobject-2.0 >= 2.8.0 ]) @@ -81,6 +81,9 @@ AM_CHECK_PYTHON_HEADERS([have_python="yes"],[have_python="no"]) if test x$have_python = xno; then AC_MSG_NOTICE([Python binding is disabled.]) else + # hack for gcompris + PYTHON_CFLAGS=$PYTHON_INCLUDES + AC_SUBST(PYTHON_CFLAGS) dnl check for pygtk PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= pygtk_required_version,[ @@ -91,7 +94,7 @@ else AC_MSG_RESULT(not found) ]) if test x$have_python = xyes; then - AC_SUBST(PYGTK_CFLAGS) + AC_SUBST(PYGTK_CFLAGS) AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no) if test "x$PYGTK_CODEGEN" = xno; then AC_MSG_NOTICE(could not find pygtk-codegen-2.0 script, Python binding is disabled.) diff --git a/src/gc_sound/python/Makefile.am b/src/gc_sound/python/Makefile.am index 53498f4..1d92dd2 100644 --- a/src/gc_sound/python/Makefile.am +++ b/src/gc_sound/python/Makefile.am @@ -13,10 +13,10 @@ common_ldflags = -module -avoid-version # gc_sound binding pkgpyexec_LTLIBRARIES = gc_sound.la -gc_sound_la_CFLAGS = $(GC_SOUND_CFLAGS) -I../src +gc_sound_la_CFLAGS = $(GOBJECT_CFLAGS) -I../src gc_sound_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initgc_sound -gc_sound_la_LIBADD = $(GC_SOUND_LIBS) -L../src/.libs -lgcsound-2 -nodist_gc_sound_la_CFLAGS = $(GC_SOUNDS_CFLAGS) -I../src +gc_sound_la_LIBADD = $(GOBJECT_LIBS) -L../src/.libs -lgcsound-2 +nodist_gc_sound_la_CFLAGS = $(GOBJECT_CFLAGS) -I../src gc_sound_la_SOURCES = gc_sound_module.c nodist_gc_sound_la_SOURCES = gc_sound.c CLEANFILES = gc_sound.c diff --git a/src/gc_sound/python/demo.py b/src/gc_sound/python/demo.py index cd09d18..1722717 100644 --- a/src/gc_sound/python/demo.py +++ b/src/gc_sound/python/demo.py @@ -1,5 +1,5 @@ import sys -sys.path.append('.libs') +sys.path.insert(0, '.libs') import gc_sound import gtk @@ -17,8 +17,10 @@ if __name__ == "__main__": chan = mix.new_channel() item = chan.get_root().append_child() - item.set_filename("/home/ycombe/Win32/gcompris_main/gcompris/boards/sounds/youcannot.wav") + #item.set_filename("/home/ycombe/Win32/gcompris_main/gcompris/boards/sounds/youcannot.wav") + print item.get_filename() + item.set_property("filename", "/home/ycombe/Win32/gcompris_main/gcompris/boards/sounds/youcannot.wav") item.connect("play_start", cb_start) item.connect("play_end", cb_stop) item.play() diff --git a/src/gc_sound/python/gc_sound.defs b/src/gc_sound/python/gc_sound.defs index 2df0386..6ae664d 100644 --- a/src/gc_sound/python/gc_sound.defs +++ b/src/gc_sound/python/gc_sound.defs @@ -41,7 +41,7 @@ (c-name "GcSoundPolicy") (gtype-id "GC_TYPE_SOUND_POLICY") (values - '("none" "NONE") + '("policy_none" "POLICY_NONE") '("play-only-if-idle" "PLAY_ONLY_IF_IDLE") '("play-after-current" "PLAY_AFTER_CURRENT") '("interrupt-and-play" "INTERRUPT_AND_PLAY") @@ -133,6 +133,10 @@ (of-object "GcSoundItem") (c-name "gc_sound_item_append_child") (return-type "GcSoundItem*") + (parameters + '("const-gchar*" "first_arg_name") + ) + (varargs #t) ) (define-method play diff --git a/src/gc_sound/python/gc_sound.override b/src/gc_sound/python/gc_sound.override index d705eb3..6f0e427 100644 --- a/src/gc_sound/python/gc_sound.override +++ b/src/gc_sound/python/gc_sound.override @@ -116,3 +116,73 @@ _wrap_gc_sound_mixer_sdl_new(PyGObject *self, PyObject *args, PyObject *kwargs) g_object_ref(G_OBJECT(self->obj)); return 0; } +%% +override gc_sound_item_append_child kwargs +static PyObject * +_wrap_gc_sound_item_append_child (PyGObject *self, PyObject *args, + PyObject *kwargs) +{ + GcSoundItem *item; + GObjectClass *class; + guint pos; + PyObject *value; + PyObject *key; + GType type; + + if (!PyArg_ParseTuple (args, ":gc_sound.item.append_child")) { + return NULL; + } + + item = gc_sound_item_append_child(GC_SOUND_ITEM(self->obj), NULL); + + if (!item) { + PyErr_SetString (PyExc_RuntimeError, + "could not create GcSoundItem object"); + return NULL; + } + + type = GC_TYPE_SOUND_ITEM; + + class = G_OBJECT_GET_CLASS(item); + g_object_freeze_notify (G_OBJECT(item)); + pos = 0; + /* For each keyword ... */ + while (kwargs && PyDict_Next (kwargs, (int *) &pos, &key, &value)) { + gchar *key_str = PyString_AsString (key); + g_warning("kwargs %s", key_str); + GParamSpec *pspec; + GValue gvalue ={ 0, }; + + pspec = g_object_class_find_property (class, key_str); + if (!pspec) { + gchar buf[512]; + + g_snprintf(buf, sizeof(buf), + "canvas item `%s' doesn't support property `%s'", + g_type_name(type), key_str); + PyErr_SetString(PyExc_TypeError, buf); + gc_sound_object_destroy(GC_SOUND_OBJECT(item)); + return NULL; + } + + g_value_init(&gvalue, G_PARAM_SPEC_VALUE_TYPE(pspec)); + if (pyg_value_from_pyobject(&gvalue, value)) { + gchar buf[512]; + + g_snprintf(buf, sizeof(buf), + "could not convert value for property `%s'", key_str); + PyErr_SetString(PyExc_TypeError, buf); + gc_sound_object_destroy(GC_SOUND_OBJECT(item)); + return NULL; + } + g_object_set_property(G_OBJECT(item), key_str, &gvalue); + g_value_unset(&gvalue); + } + + g_object_thaw_notify (G_OBJECT(item)); + + return pygobject_new ((GObject *)item); + + +} + diff --git a/src/gc_sound/src/Makefile.am b/src/gc_sound/src/Makefile.am index 15292c8..4a902b0 100644 --- a/src/gc_sound/src/Makefile.am +++ b/src/gc_sound/src/Makefile.am @@ -3,11 +3,11 @@ # lib_LTLIBRARIES = libgcsound-2.la -#libgcsound_2_la_CFLAGS= $(SDL_CFLAGS) $(GC_SOUND_CFLAGS) -#libgcsound_2_la_LDFLAGS= $(SDL_LIBS) $(GC_SOUND_LIBS) +libgcsound_2_la_CFLAGS= $(SDL_CFLAGS) $(GOBJECT_CFLAGS) +libgcsound_2_la_LDFLAGS= $(SDL_LIBS) $(GOBJECT_LIBS) -libgcsound_2_la_CFLAGS= $(SDL_CFLAGS) $(GCOMPRIS_CFLAGS) -libgcsound_2_la_LDFLAGS= $(SDL_LIBS) $(GCOMPRIS_LIBS) +#libgcsound_2_la_CFLAGS= $(SDL_CFLAGS) $(GCOMPRIS_CFLAGS) +#libgcsound_2_la_LDFLAGS= $(SDL_LIBS) $(GCOMPRIS_LIBS) libgcsoundincludedir = $(includedir)/gcompris/gcsound @@ -47,9 +47,9 @@ libgcsound_2_la_SOURCES = \ check_PROGRAMS = test_gc_sound -test_gc_sound_CFLAGS = $(GC_SOUND_CFLAGS) +test_gc_sound_CFLAGS = $(GOBJECT_CFLAGS) -test_gc_sound_LDFLAGS = -L. -lgcsound-2 $(GC_SOUND_LIBS) +test_gc_sound_LDFLAGS = -L. -lgcsound-2 $(GOBJECT_LIBS) test_gc_sound_SOURCES = \ test_gc_sound.c diff --git a/src/gc_sound/src/gc-sound-channel.c b/src/gc_sound/src/gc-sound-channel.c index 9c2bf17..28fe33c 100644 --- a/src/gc_sound/src/gc-sound-channel.c +++ b/src/gc_sound/src/gc-sound-channel.c @@ -83,7 +83,7 @@ gboolean gc_sound_channel_play (GcSoundChannel *self, GcSoundPolicy policy; /* item policy if it's set */ - if (gc_sound_item_get_policy(item) == NONE) + if (gc_sound_item_get_policy(item) == POLICY_NONE) policy = self->policy; else policy = gc_sound_item_get_policy(item); @@ -130,10 +130,12 @@ static void gc_sound_channel_destroy (GcSoundObject *self); static void root_destroyed (GcSoundObject *root, gpointer data) { - if (!(GC_SOUND_OBJECT_FLAGS (GC_SOUND_OBJECT(data)) & GC_SOUND_IN_DESTRUCTION)) - gc_sound_channel_destroy (GC_SOUND_OBJECT(data)); - // direct call claas destroy because root is already destroyed. - //GC_SOUND_OBJECT_GET_CLASS(data)->destroy (GC_SOUND_OBJECT(data)); + GcSoundChannel *self = GC_SOUND_CHANNEL(data); + if (!(GC_SOUND_OBJECT_FLAGS (GC_SOUND_OBJECT(data)) & GC_SOUND_IN_DESTRUCTION)) { + g_object_unref(self->root); + self->root = GC_SOUND_ITEM(g_object_new(GC_TYPE_SOUND_ITEM, "channel", self, NULL)); + g_object_ref_sink(G_OBJECT(self->root)); + } } static void diff --git a/src/gc_sound/src/gc-sound-channel.h b/src/gc_sound/src/gc-sound-channel.h index 9f80033..05fc76e 100644 --- a/src/gc_sound/src/gc-sound-channel.h +++ b/src/gc_sound/src/gc-sound-channel.h @@ -28,7 +28,7 @@ typedef struct _GcSoundChannel GcSoundChannel; typedef struct _GcSoundChannelClass GcSoundChannelClass; typedef enum { - NONE, + POLICY_NONE, PLAY_ONLY_IF_IDLE, PLAY_AFTER_CURRENT, INTERRUPT_AND_PLAY diff --git a/src/gc_sound/src/gc-sound-item.c b/src/gc_sound/src/gc-sound-item.c index 05b6fa0..e8b5a35 100644 --- a/src/gc_sound/src/gc-sound-item.c +++ b/src/gc_sound/src/gc-sound-item.c @@ -138,14 +138,19 @@ void gc_sound_item_child_destroyed( GcSoundItem *child, gpointer data) g_object_unref (G_OBJECT(child)); } -GcSoundItem * gc_sound_item_append_child (GcSoundItem *self) +GcSoundItem * gc_sound_item_append_child (GcSoundItem *self, const gchar *first_arg_name, ...) { GcSoundItem *child; + va_list args; child = GC_SOUND_ITEM(g_object_new(GC_TYPE_SOUND_ITEM, "parent", self, - "channel", self->channel, + "channel", self->channel, NULL)); + va_start (args, first_arg_name); + g_object_set_valist( G_OBJECT(child), + first_arg_name, args); + va_end (args); /* Child is added to our lists */ self->children = g_list_append (self->children, child); @@ -196,6 +201,10 @@ gc_sound_item_signal_real_play (GcSoundItem *self) static void gc_sound_item_signal_play_end (GcSoundItem *self, gboolean stopped) { + if (self->destroy_after_play){ + gc_sound_object_destroy(GC_SOUND_OBJECT(self)); + } + if (self->has_played || stopped) { self->started = FALSE; self->has_played = FALSE; @@ -230,7 +239,8 @@ gc_sound_item_signal_chunk_start (GcSoundItem *self) enum { PROP_0, PROP_CHANNEL, - PROP_FILENAME + PROP_FILENAME, + PROP_DESTROY_AFTER_PLAY }; /* GType */ @@ -264,6 +274,7 @@ gc_sound_item_init(GcSoundItem* self) // child we are playing self->playing = NULL; + self->destroy_after_play = FALSE; } static void @@ -275,7 +286,10 @@ gc_sound_item_get_property(GObject* object, guint prop_id, GValue* value, GParam g_value_set_object(value, self->channel); break; case PROP_FILENAME: - g_value_set_string(value, self->filename); + g_value_set_string(value, g_strdup(self->filename)); + break; + case PROP_DESTROY_AFTER_PLAY: + g_value_set_boolean(value, self->destroy_after_play); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -295,6 +309,9 @@ gc_sound_item_set_property(GObject* object, guint prop_id, GValue const* value, case PROP_FILENAME: gc_sound_item_set_filename( self, (gchar *)g_value_get_string(value)); break; + case PROP_DESTROY_AFTER_PLAY: + self->destroy_after_play = g_value_get_boolean(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -328,6 +345,13 @@ gc_sound_item_class_init(GcSoundItemClass* self_class) "The sound file to play", NULL, G_PARAM_READWRITE)); + g_object_class_install_property(go_class, + PROP_DESTROY_AFTER_PLAY, + g_param_spec_boolean ("destroy_after_play", + "destroy the item when played", + "Destroy the item when played", + FALSE, + G_PARAM_READWRITE)); /* signals */ /* enum { */ @@ -363,7 +387,7 @@ gc_sound_item_class_init(GcSoundItemClass* self_class) 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 */ + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), /* flags */ G_STRUCT_OFFSET (GcSoundItemClass, play_start), /* offset function */ NULL, /* accumulator */ NULL, /* accu data */ @@ -374,7 +398,7 @@ gc_sound_item_class_init(GcSoundItemClass* self_class) 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 */ + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), /* flags */ G_STRUCT_OFFSET (GcSoundItemClass, play_end), /* offset function */ NULL, /* accumulator */ NULL, /* accu data */ @@ -386,7 +410,7 @@ gc_sound_item_class_init(GcSoundItemClass* self_class) 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 */ + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), /* flags */ G_STRUCT_OFFSET (GcSoundItemClass, chunk_start), /* offset function */ NULL, /* accumulator */ NULL, /* accu data */ @@ -397,7 +421,7 @@ gc_sound_item_class_init(GcSoundItemClass* self_class) 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 */ + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), /* flags */ G_STRUCT_OFFSET (GcSoundItemClass, chunk_end), /* offset function */ NULL, /* accumulator */ NULL, /* accu data */ diff --git a/src/gc_sound/src/gc-sound-item.h b/src/gc_sound/src/gc-sound-item.h index cf06e62..48d411b 100644 --- a/src/gc_sound/src/gc-sound-item.h +++ b/src/gc_sound/src/gc-sound-item.h @@ -69,6 +69,8 @@ struct _GcSoundItem { // child we are playing GList *playing; + + gboolean destroy_after_play; }; struct _GcSoundItemClass { @@ -87,7 +89,7 @@ struct _GcSoundItemClass { gboolean gc_sound_item_run_next (GcSoundItem *self, gboolean stopped); -GcSoundItem * gc_sound_item_append_child (GcSoundItem *self); +GcSoundItem * gc_sound_item_append_child (GcSoundItem *self, const gchar *first_arg_name, ...); gboolean gc_sound_item_play (GcSoundItem *self); diff --git a/src/gc_sound/src/gc-sound-mixer-SDL.c b/src/gc_sound/src/gc-sound-mixer-SDL.c index 3092d0f..6c06c06 100644 --- a/src/gc_sound/src/gc-sound-mixer-SDL.c +++ b/src/gc_sound/src/gc-sound-mixer-SDL.c @@ -401,7 +401,8 @@ gc_sound_mixer_sdl_destroy (GcSoundObject *object) { g_signal_handlers_disconnect_by_func(GC_SOUND_OBJECT(g_ptr_array_index(self->channels,i)), channel_destroyed, self); gc_sound_object_destroy (GC_SOUND_OBJECT(g_ptr_array_index(self->channels,i))); - g_object_unref(G_OBJECT(g_ptr_array_index(self->channels,i))); + // will be unref on signal receipt + //g_object_unref(G_OBJECT(g_ptr_array_index(self->channels,i))); } running_mixer = NULL; diff --git a/src/gc_sound/src/test_gc_sound.c b/src/gc_sound/src/test_gc_sound.c index afa36dd..745cfff 100644 --- a/src/gc_sound/src/test_gc_sound.c +++ b/src/gc_sound/src/test_gc_sound.c @@ -38,13 +38,15 @@ main (int argc, char *argv) GC_SOUND_OBJECT(root2)->nick="root2"; /* create new item for our sounds */ - 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 = gc_sound_item_append_child (root1, NULL); + // item2 = gc_sound_item_append_child (root2, "filename", "../../../../../gcompris_main/gcompris/boards/music/background/LRLaPause.ogg", NULL); + + item2 = gc_sound_item_append_child (root2, NULL); + g_object_set( G_OBJECT(item2), "filename", "../../../../../gcompris_main/gcompris/boards/music/background/LRLaPause.ogg", NULL); + item3 = gc_sound_item_append_child (root2, "filename", "../../../../../gcompris_main/gcompris/boards/sounds/bonus.ogg", NULL); + item1_1 = gc_sound_item_append_child (item1, "filename", "../../../../../gcompris_main/gcompris/boards/sounds/train.ogg", NULL); + item1_2 = gc_sound_item_append_child (item1, "filename", "../../../../../gcompris_main/gcompris/boards/sounds/wahoo.ogg", "destroy_after_play", TRUE, NULL); - item1_2 = gc_sound_item_append_child (item1); - GC_SOUND_OBJECT(item1)->nick = "item1"; GC_SOUND_OBJECT(item2)->nick = "item2"; GC_SOUND_OBJECT(item3)->nick = "item3"; @@ -52,10 +54,11 @@ main (int argc, char *argv) GC_SOUND_OBJECT(item1_2)->nick = "item1_2"; /* set file sound name */ - gc_sound_item_set_filename(item1_1, "../../../../../gcompris_main/gcompris/boards/sounds/wahoo.ogg"); + /* gc_sound_item_set_filename(item1_1, "../../../../../gcompris_main/gcompris/boards/sounds/wahoo.ogg"); gc_sound_item_set_filename(item1_2, "../../../../../gcompris_main/gcompris/boards/sounds/wahoo.ogg"); gc_sound_item_set_filename(item2, "../../../../../gcompris_main/gcompris/boards/music/background/LRLaPause.ogg"); gc_sound_item_set_filename(item3, "../../../../../gcompris_main/gcompris/boards/sounds/bonus.ogg"); + */ // test gc_sound_item_set_filename(item1_1, NULL); diff --git a/src/gcompris/Makefile.am b/src/gcompris/Makefile.am index 70f3ff3..cdc5927 100644 --- a/src/gcompris/Makefile.am +++ b/src/gcompris/Makefile.am @@ -56,7 +56,7 @@ INCLUDES = \ $(XML_CFLAGS) \ $(SDL_CFLAGS) \ -DGNOME_DISABLE_DEPRECATED \ - $(sqlite_cflags) \ + $(sqlite_cflags) \ $(GNET_CFLAGS) \ $(cairo_cflags) @@ -70,9 +70,11 @@ gcompris_LDFLAGS = \ gcompris_LDADD = \ $(top_builddir)/src/gcompris/libgcompris-1.la \ $(LIBICONV) \ - $(INTLLIBS) \ + $(INTLLIBS) \ $(python_ldadd) \ - $(LIBPOPT) + $(LIBPOPT) \ + $(GC_SOUND_LIBS) + # # Gcompris library @@ -142,7 +144,6 @@ libgcompris_1_la_SOURCES = \ profile.c \ properties.c \ score.c \ - sdlplayer.c \ skin.c \ soundutil.c \ timer.c \ diff --git a/src/gcompris/config.c b/src/gcompris/config.c index f3a1b5d..1d2f362 100644 --- a/src/gcompris/config.c +++ b/src/gcompris/config.c @@ -746,10 +746,10 @@ item_event_ok(GnomeCanvasItem *item, GdkEvent *event, gpointer data) else { if(!properties->music) - sdlplayer_halt_music(); + gc_sound_channel_halt(properties->music_chan); if(!properties->fx) - sdlplayer_halt_fx(); + gc_sound_channel_halt(properties->fx_chan); } gc_prop_save(properties); } @@ -781,12 +781,12 @@ item_event_ok(GnomeCanvasItem *item, GdkEvent *event, gpointer data) NULL); if(!properties->music) { - sdlplayer_halt_music(); + gc_sound_channel_halt(properties->music_chan); } else { gc_sound_init(); - sdlplayer_resume_music(); + gc_music_play(); } } else if(!strcmp((char *)data, "effect")) diff --git a/src/gcompris/gcompris.h b/src/gcompris/gcompris.h index 5223e3d..0f57119 100644 --- a/src/gcompris/gcompris.h +++ b/src/gcompris/gcompris.h @@ -26,6 +26,8 @@ # include <config.h> #endif +#include <gc-sound.h> + #include <libgnomecanvas/libgnomecanvas.h> #include <gtk/gtk.h> diff --git a/src/gcompris/properties.c b/src/gcompris/properties.c index a632c00..d3f854c 100644 --- a/src/gcompris/properties.c +++ b/src/gcompris/properties.c @@ -174,6 +174,11 @@ gc_prop_new () tmp->cache_dir = NULL; tmp->drag_mode = GC_DRAG_MODE_GRAB; + /* initialised in soundutil.c (gc_sound_init) */ + tmp->mixer = NULL; + tmp->music_chan = NULL; + tmp->fx_chan = NULL; + user_dir = gc_prop_user_root_directory_get() ; gc_util_create_rootdir( user_dir ); diff --git a/src/gcompris/properties.h b/src/gcompris/properties.h index 225d0c6..6f0561c 100644 --- a/src/gcompris/properties.h +++ b/src/gcompris/properties.h @@ -65,6 +65,11 @@ typedef struct { gchar *menu_position; gchar *server; gint drag_mode; + + /* GcSound API */ + GcSoundMixer *mixer; + GcSoundChannel *music_chan; + GcSoundChannel *fx_chan; } GcomprisProperties; GcomprisProperties *gc_prop_get (void); diff --git a/src/gcompris/soundutil.c b/src/gcompris/soundutil.c index 29d0e44..b5b22f0 100644 --- a/src/gcompris/soundutil.c +++ b/src/gcompris/soundutil.c @@ -26,41 +26,18 @@ #include <signal.h> #include <glib.h> -static GList *pending_queue = NULL; -static int sound_policy; static gboolean music_paused = FALSE; static gboolean sound_closed = FALSE; -/* mutex */ -GMutex *lock = NULL; -GMutex *lock_music = NULL; -GMutex *lock_fx = NULL; -GCond *cond = NULL; - /* Singleton */ static guint sound_init = 0; -/* Forward function declarations */ -GThread *thread_scheduler_fx, *thread_scheduler_music; - -static void *thread_play_ogg (gchar *file); -static char *get_next_sound_to_play( ); - -static gpointer scheduler_fx (gpointer user_data); -static gpointer scheduler_music (gpointer user_data); - -/* sound control */ -GObject *gc_sound_controller = NULL; -void gc_sound_callback(GcomprisSound *ctl, gchar *file, gpointer user_data); -GHashTable *sound_callbacks = NULL; - /* ===================================================================== * * =====================================================================*/ void gc_sound_init() { - /* Check to run the init once only */ if(sound_init == 1) { @@ -71,40 +48,18 @@ gc_sound_init() } sound_init = 1; - gc_sound_controller = g_object_new (GCOMPRIS_SOUND_TYPE, NULL); - - g_signal_connect( gc_sound_controller, - "sound-played", - (GCallback) gc_sound_callback, - NULL); - - g_assert( gc_sound_controller != NULL ); - - /* Initialize the thread system */ - if (!g_thread_supported ()) g_thread_init (NULL); - - lock = g_mutex_new (); - lock_music = g_mutex_new (); - lock_fx = g_mutex_new (); - cond = g_cond_new (); - - sound_policy = PLAY_AFTER_CURRENT; +#ifdef HAVE_LIBSDL_MIXER + gc_prop_get()->mixer = gc_sound_mixer_sdl_new(); +#endif - if(sdlplayer_init()!=0) { + if(!gc_prop_get()->mixer) { /* Sound init failed. Desactivate the sound */ gc_prop_get()->music = 0; gc_prop_get()->fx = 0; return; } - - thread_scheduler_fx = g_thread_create((GThreadFunc)scheduler_fx, NULL, FALSE, NULL); - if (thread_scheduler_fx == NULL) - perror("create failed for fx scheduler"); - - thread_scheduler_music = g_thread_create((GThreadFunc)scheduler_music, NULL, FALSE, NULL); - if (thread_scheduler_music == NULL) - perror("create failed for music scheduler"); - + gc_prop_get()->music_chan = gc_sound_mixer_new_channel(gc_prop_get()->mixer); + gc_prop_get()->fx_chan = gc_sound_mixer_new_channel(gc_prop_get()->mixer); } void @@ -113,15 +68,7 @@ gc_sound_close() if ( !sound_closed ) { sound_closed = TRUE; - if ( music_paused ) { - music_paused = FALSE; - gc_sound_resume(); - } - g_mutex_lock(lock_fx); - sdlplayer_halt_music(); - sdlplayer_halt_fx(); - g_mutex_lock(lock_music); - sdlplayer_close(); + gc_sound_mixer_close_audio(gc_prop_get()->mixer); } } @@ -131,11 +78,8 @@ gc_sound_reopen() if (gc_prop_get()->fx || gc_prop_get()->music) { if (sound_closed) { - sdlplayer_reopen(); - g_mutex_unlock(lock_fx); - g_mutex_unlock(lock_music); + gc_sound_mixer_open_audio(gc_prop_get()->mixer); sound_closed = FALSE; - music_paused = FALSE; } } } @@ -143,14 +87,14 @@ gc_sound_reopen() void gc_sound_pause() { - sdlplayer_pause_music(); + gc_sound_channel_pause(gc_prop_get()->music_chan); music_paused = TRUE; } void gc_sound_resume() { - sdlplayer_resume_music(); + gc_sound_channel_resume(gc_prop_get()->music_chan); music_paused = FALSE; } @@ -158,32 +102,25 @@ gc_sound_resume() * * =====================================================================*/ void -gc_sound_policy_set(int policy) +gc_sound_policy_set(GcSoundPolicy policy) { - switch (policy) - { - case PLAY_ONLY_IF_IDLE : sound_policy = PLAY_ONLY_IF_IDLE; break; - case PLAY_AFTER_CURRENT : sound_policy = PLAY_AFTER_CURRENT; break; - case PLAY_AND_INTERRUPT : sound_policy = PLAY_AND_INTERRUPT; break; - default : sound_policy = PLAY_AFTER_CURRENT; - } + gc_sound_channel_set_policy(gc_prop_get()->fx_chan, policy); } + /* ===================================================================== * * =====================================================================*/ -int +GcSoundPolicy gc_sound_policy_get() { - return sound_policy; + return gc_sound_channel_get_policy(gc_prop_get()->fx_chan); } + /* ===================================================================== - * Thread scheduler background : - * - launches a single thread for playing and play any file found - * in the gcompris music directory ======================================================================*/ -static gpointer -scheduler_music (gpointer user_data) +void +gc_music_play () { GcomprisProperties *properties = gc_prop_get(); gint i; @@ -204,7 +141,7 @@ scheduler_music (gpointer user_data) if (!dir) { g_warning ("Couldn't open music dir: %s", music_dir); g_free(music_dir); - return NULL; + return; } /* Fill up the music list */ @@ -222,143 +159,26 @@ scheduler_music (gpointer user_data) if(g_slist_length(musiclist)==0) { g_free(music_dir); - return NULL; + return; } /* Now loop over all our music files */ - while (TRUE) - { - for(i=0; i<g_slist_length(musiclist); i++) - { - /* Music can be disabled at any time */ - while(!gc_prop_get()->music || music_paused || sound_closed) - g_usleep(1000000); - - /* WARNING Displaying stuff in a thread seems to make gcompris unstable */ - /* display_ogg_file_credits((char *)g_list_nth_data(musiclist, i)); */ - // if(decode_ogg_file((char *)g_list_nth_data(musiclist, i))!=0) - g_mutex_lock(lock_music); - if(sdlplayer_music((char *)g_slist_nth_data(musiclist, i), 128)!=0){ - g_warning("sdlplayer_music failed, try again in 5 seconds"); - g_usleep(5000000); - } - g_mutex_unlock(lock_music); - - } - } - - /* Never happen */ - g_slist_free(musiclist); - g_warning( "The background thread music is stopped now. "\ - "The files in %s are not ogg vorbis OR the sound output failed", - music_dir); - g_free(music_dir); - return NULL; -} -/* ===================================================================== - * Thread scheduler : - * - launches a single thread for playing a file - * - joins the previous thread at its end - * - then launches another thread if some sounds are pending - * - the thread never ends - ======================================================================*/ -static gpointer -scheduler_fx (gpointer user_data) -{ - char *sound = NULL; - - while (TRUE) - { - if ( ( sound = get_next_sound_to_play( ) ) != NULL ) - { - thread_play_ogg(sound); - g_free(sound); - } - else - { - g_mutex_lock (lock); - g_cond_wait (cond, lock); - g_mutex_unlock (lock); - } - } - return NULL; -} -/* ===================================================================== - * Thread function for playing a single file - ======================================================================*/ -static void* -thread_play_ogg (gchar *file) -{ - gchar *absolute_file; - - g_warning(" Thread_play_ogg %s", file); - - absolute_file = gc_file_find_absolute(file); - - if (!absolute_file) - return NULL; - - g_warning(" Calling gcompris internal sdlplayer_file (%s)", absolute_file); - g_mutex_lock(lock_fx); - sdlplayer_fx(absolute_file, 128); - g_mutex_unlock(lock_fx); - g_signal_emit (gc_sound_controller, - GCOMPRIS_SOUND_GET_CLASS (gc_sound_controller)->sound_played_signal_id, - 0 /* details */, - g_strdup(file)); - g_warning(" sdlplayer_fx(%s) ended.", absolute_file); - - g_free(absolute_file); - - return NULL; -} - -/* ===================================================================== - * Returns the next sound play, or NULL if there is no - ======================================================================*/ -static char* -get_next_sound_to_play( ) -{ - char* tmpSound = NULL; - - g_mutex_lock (lock); - if ( g_list_length(pending_queue) > 0 ) + for(i=0; i<g_slist_length(musiclist); i++) { - tmpSound = g_list_nth_data( pending_queue, 0 ); - pending_queue = g_list_remove( pending_queue, tmpSound ); - g_warning( "... get_next_sound_to_play : %s\n", tmpSound ); + GcSoundItem *item = gc_sound_item_append_child( gc_sound_channel_get_root ( gc_prop_get()->music_chan ), NULL); + + gc_sound_item_set_filename( item, g_slist_nth_data(musiclist, i)); + } - g_mutex_unlock (lock); + g_object_set( G_OBJECT(gc_sound_channel_get_root ( gc_prop_get()->music_chan )), + "destroy_after_play", TRUE, NULL); + gc_sound_item_set_loop(gc_sound_channel_get_root ( gc_prop_get()->music_chan ), TRUE); + gc_sound_item_play(gc_sound_channel_get_root ( gc_prop_get()->music_chan )); - return tmpSound; -} - -/* ===================================================================== - * Play a OGG sound file. - * gc_sound_play_ogg function to process the sounds. - ======================================================================*/ -void -gc_sound_play_ogg_cb(const gchar *file, GcomprisSoundCallback cb) -{ - - g_assert ( cb != NULL); - - /* g_intern_string is in 2.10 */ - const gchar *intern_file = g_quark_to_string( g_quark_from_string(file)); - - if (!sound_callbacks) - sound_callbacks = g_hash_table_new_full (g_str_hash, - g_str_equal, - NULL, - NULL); - - /* i suppose there will not be two call of that function with same sound file before sound is played */ - g_hash_table_replace (sound_callbacks, - (gpointer)intern_file, - cb); - gc_sound_play_ogg(intern_file, NULL); + g_slist_free(musiclist); + return; } /* ===================================================================== @@ -392,59 +212,48 @@ gc_sound_play_ogg(const gchar *sound, ...) g_list_free(list); } -/* ===================================================================== - * Play a list of OGG sound files. - * The given ogg files will be first tested as a locale dependant sound file: - * sounds/<current gcompris locale>/<sound> - * If it doesn't exists, then the test is done with a music file: - * music/<sound> - =====================================================================*/ -void free_string(gpointer data, gpointer user_data) -{ - g_free(data); -} void gc_sound_play_ogg_list( GList* files ) { GList* list; - char* tmpSound = NULL; if ( !gc_prop_get()->fx ) return; - if ( sound_policy == PLAY_ONLY_IF_IDLE && - g_list_length( pending_queue ) > 0 ) - return; - - if ( sound_policy == PLAY_AND_INTERRUPT ) { - g_warning("halt music"); - while ( g_list_length(pending_queue) > 0 ) - { - tmpSound = g_list_nth_data( pending_queue, 0 ); - pending_queue = g_list_remove( pending_queue, tmpSound ); - g_free(tmpSound); - } - sdlplayer_halt_fx(); - } - - g_mutex_lock (lock); - list = g_list_first( files ); while( list!=NULL ) { - if (g_list_length(pending_queue) < MAX_QUEUE_LENGTH) - { - pending_queue = g_list_append(pending_queue, g_strdup( (gchar*)(list->data) )); - } + GcSoundItem *item = gc_sound_item_from_gc_filename((gchar*)(list->data), + "destroy_after_play", TRUE, + NULL); + + if (!item) continue; + + gc_sound_item_play(item); list = g_list_next(list); } - g_mutex_unlock (lock); +} + +GcSoundItem *gc_sound_item_from_gc_filename(gchar *filename, const gchar *first_arg_name, ...) +{ + gchar *absolute_file = gc_file_find_absolute(filename); + va_list args; + + if (!absolute_file) + return NULL; - // Tell the scheduler to check for new sounds to play - g_warning("Tell the scheduler to check for new sounds to play\n"); - g_cond_signal (cond); + GcSoundItem *item = gc_sound_item_append_child( gc_sound_channel_get_root (gc_prop_get()->fx_chan), NULL); + gc_sound_item_set_filename (item, absolute_file); + va_start (args, first_arg_name); + g_object_set_valist( G_OBJECT(item), + first_arg_name, args); + va_end (args); + + g_free(absolute_file); + + return item; } /** return a string representing a letter or number audio file @@ -488,89 +297,3 @@ gc_sound_alphabet(gchar *chars) return result2; } - -void gc_sound_callback(GcomprisSound *ctl, gchar *file, gpointer user_data) -{ - GcomprisSoundCallback cb; - - if (!sound_callbacks) - return; - - cb = g_hash_table_lookup (sound_callbacks, file); - - if (cb){ - g_warning("calling callback for %s", file); - cb(file); - } - else - g_warning("%s has no callback", file); - g_hash_table_remove(sound_callbacks, file); - -} - -/*************************************/ -/* GObject control sound */ -struct _GcomprisSoundPrivate -{ -}; - -#include "gcompris-marshal.h" - -static void -gc_sound_instance_init (GTypeInstance *instance, - gpointer g_class) -{ - GcomprisSound *self = (GcomprisSound *)instance; - self->private = g_new (GcomprisSoundPrivate, 1); -} - -static void -default_sound_played_signal_handler (GcomprisSound *obj, gchar *file, gpointer user_data) -{ - /* Here, we trigger the real file write. */ - g_warning ("sound_played: %s\n", file); -} - -static void -gc_sound_class_init (gpointer g_class, - gpointer g_class_data) -{ - GcomprisSoundClass *klass = GCOMPRIS_SOUND_CLASS (g_class); - - klass->sound_played = default_sound_played_signal_handler; - - klass->sound_played_signal_id = - g_signal_new ("sound-played", - G_TYPE_FROM_CLASS (g_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, - G_STRUCT_OFFSET (GcomprisSoundClass, sound_played), - NULL /* accumulator */, - NULL /* accu_data */, - gnome_canvas_marshal_VOID__POINTER, - G_TYPE_NONE /* return_type */, - 1 /* n_params */, - G_TYPE_POINTER /* param_types */); - -} - -GType gc_sound_get_type (void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (GcomprisSoundClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - gc_sound_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GcomprisSound), - 0, /* n_preallocs */ - gc_sound_instance_init /* instance_init */ - }; - type = g_type_register_static (G_TYPE_OBJECT, - "GcomprisSoundType", - &info, 0); - } - return type; -} diff --git a/src/gcompris/soundutil.h b/src/gcompris/soundutil.h index 13a5c89..4c75a8e 100644 --- a/src/gcompris/soundutil.h +++ b/src/gcompris/soundutil.h @@ -27,89 +27,22 @@ #define MAX_QUEUE_LENGTH 5 #define MAX_SOUND_FILES 20 -typedef enum -{ - PLAY_ONLY_IF_IDLE = 0, - PLAY_AFTER_CURRENT = 1, - PLAY_AND_INTERRUPT = 2, -} SoundPolicy; - -typedef void (*GcomprisSoundCallback) (gchar *); - -void gc_sound_play_ogg(const gchar *, ...); -void gc_sound_play_ogg_cb(const gchar *, GcomprisSoundCallback); +void gc_sound_play_ogg(const gchar *, ...); void gc_sound_play_ogg_list( GList* files ); -void gc_sound_policy_set(int); -int gc_sound_policy_get(void); + void gc_sound_init(void); void gc_sound_reopen(void); void gc_sound_close(void); void gc_sound_pause(void); void gc_sound_resume(void); -int decode_ogg_file(char *infile); -void display_ao_devices(); - -/* - * SDL PLAYER - */ -int sdlplayer_init(); -void sdlplayer_close(); -void sdlplayer_reopen(); +void gc_music_play(); -int sdlplayer_music(char *filename, int volume); -void sdlplayer_halt_music(); -void sdlplayer_pause_music(); -void sdlplayer_resume_music(); - -void sdlplayer_halt_fx(); -void sdlplayer_resume_fx(); -int sdlplayer_fx(char *filename, int volume); +GcSoundItem *gc_sound_item_from_gc_filename(gchar *filename, const gchar *first_arg_name, ...); gchar *gc_sound_alphabet(gchar *chars); - -/*************************************************************/ -/* GObject to control sound. code get from maman-file.h */ -/*************************************************************/ -/* - * Potentially, include other headers on which this header depends. - */ -#include <glib-object.h> - -#define GCOMPRIS_SOUND_TYPE (gc_sound_get_type ()) -#define GCOMPRIS_SOUND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCOMPRIS_SOUND_TYPE, GcomprisSound)) -#define GCOMPRIS_SOUND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCOMPRIS_SOUND_TYPE, GcomprisSoundClass)) -#define GCOMPRIS_SOUND_IS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCOMPRIS_SOUND_TYPE)) -#define GCOMPRIS_SOUND_IS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCOMPRIS_SOUND_TYPE)) -#define GCOMPRIS_SOUND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCOMPRIS_SOUND_TYPE, GcomprisSoundClass)) - -typedef struct _GcomprisSound GcomprisSound; -typedef struct _GcomprisSoundClass GcomprisSoundClass; -typedef struct _GcomprisSoundPrivate GcomprisSoundPrivate; - -struct _GcomprisSound { - GObject parent; - /* instance members */ - GcomprisSoundPrivate *private; -}; - -struct _GcomprisSoundClass { - GObjectClass parent; - - guint sound_played_signal_id; - void (*sound_played) (GcomprisSound *self, gchar *file, gpointer user_data); -}; - -/* used by MAMAN_TYPE_FILE */ -GType gc_sound_get_type (void); - -/* API. */ - -/* empty for now */ - - -/* Declaration of GCompris Sound Controller */ -extern GObject *gc_sound_controller; +void gc_sound_policy_set(GcSoundPolicy policy); +GcSoundPolicy gc_sound_policy_get(void); #endif |