Index: README
===================================================================
RCS file: /cvs/gnome/gnome-games/README,v
retrieving revision 1.21
diff -u -r1.21 README
--- README	17 Jun 2006 06:03:14 -0000	1.21
+++ README	9 Jul 2006 10:54:20 -0000
@@ -194,6 +200,8 @@
 To compile these packages, we recommend using the baseline GNOME 2.14
 development packages. While gnome-games may compile with older versions,
 we will not accept bug reports for games used under those conditions.
+
+GStreamer 0.10 is required by gnome-games, and is used to play sounds.
 
 CVS checkouts will require the latest intltool.
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-games/configure.in,v
retrieving revision 1.356
diff -u -r1.356 configure.in
--- configure.in	12 Jun 2006 05:11:07 -0000	1.356
+++ configure.in	9 Jul 2006 10:54:20 -0000
@@ -83,9 +83,11 @@
 CAIRO_REQUIRED=1.0
 # This ones not actually required, but it is the minimum usable version.
 AVAHI_REQUIRED=0.6.6
+GSTREAMER_REQUIRED=0.10.4
+
 
 ## Common flags for libraries that all games use.
-PKG_CHECK_MODULES(GNOME_GAMES, libgnome-2.0 >= $LIBGNOME_REQUIRED gconf-2.0 >= $GCONF_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED gtk+-2.0 >= $GTK_REQUIRED librsvg-2.0 >= $LIBRSVG_REQUIRED)
+PKG_CHECK_MODULES(GNOME_GAMES, libgnome-2.0 >= $LIBGNOME_REQUIRED gconf-2.0 >= $GCONF_REQUIRED libgnomeui-2.0 >= $LIBGNOMEUI_REQUIRED gtk+-2.0 >= $GTK_REQUIRED librsvg-2.0 >= $LIBRSVG_REQUIRED gstreamer-0.10 >= $GSTREAMER_REQUIRED)
 AC_SUBST(GNOME_GAMES_CFLAGS)
 AC_SUBST(GNOME_GAMES_LIBS)
 
@@ -195,12 +197,6 @@
      *-*-osf1-* ) OS_FLAGS="-D_POSIX_PII_SOCKET" ;;
 esac
 GNOME_GAMES_CFLAGS="$OS_FLAGS $GNOME_GAMES_CFLAGS"
-
-PKG_CHECK_MODULES(ESD, esound, , [
-  GNOME_GAMES_CFLAGS="$GNOME_GAMES_CFLAGS -DNO_ESD"
-  GNOME_GAMES_CXXFLAGS="$GNOME_GAMES_CXXFLAGS -DNO_ESD" ])
-AC_SUBST(ESD_CFLAGS)
-AC_SUBST(ESD_LIBS)
 
 GETTEXT_PACKAGE=gnome-games
 AC_SUBST(GETTEXT_PACKAGE)
Index: gnometris/sound.cpp
===================================================================
RCS file: /cvs/gnome/gnome-games/gnometris/sound.cpp,v
retrieving revision 1.3
diff -u -r1.3 sound.cpp
--- gnometris/sound.cpp	8 Sep 2005 10:34:13 -0000	1.3
+++ gnometris/sound.cpp	9 Jul 2006 10:54:21 -0000
@@ -21,39 +21,22 @@
  */
 
 #include <gnome.h>
-#ifndef NO_ESD
-# include <esd.h>
-#endif
 
+#include "games-sound.h"
 #include "sound.h"
 
 /* The master sound object for the game. */
 Sound *sound = NULL;
+Player *player = NULL;
 
-const char *soundFiles[] = { "gnometris/gameover.wav", 
-			     "gnometris/gnometris.wav", 
-			     "gnometris/land.wav",
-			     "gnometris/lines1.wav", 
-			     "gnometris/lines2.wav", 
-			     "gnometris/lines3.wav",
-			     "gnometris/slide.wav", 
-			     "gnometris/turn.wav" };
-
-#ifdef NO_ESD
-
-// In the event of no sound support we just use dummy functions.
-
-Sound::Sound () { }
-
-void Sound::turnOn () { }
-
-void Sound::turnOff () { }
-
-gboolean Sound::isOn () { return FALSE; }
-
-void Sound::playSound (int soundId) { }
-
-#else
+const char *soundFiles[] = { "gnometris/gameover.ogg", 
+			     "gnometris/gnometris.ogg", 
+			     "gnometris/land.ogg",
+			     "gnometris/lines1.ogg", 
+			     "gnometris/lines2.ogg", 
+			     "gnometris/lines3.ogg",
+			     "gnometris/slide.ogg", 
+			     "gnometris/turn.ogg" };
 
 Sound::Sound ()
 {
@@ -65,20 +48,17 @@
 {
   int i;
   gchar * fullName;
+  char * error;
 
   if (soundOn)
     return;
 
   if (!soundInit) {
-    gnome_sound_init (NULL);
-    for (i=0; i<N_SOUNDS; i++) {
-      fullName = gnome_program_locate_file (NULL, 
-					    GNOME_FILE_DOMAIN_APP_SOUND,
-					    soundFiles[i], FALSE, NULL);
-      sampleIds[i] = gnome_sound_sample_load ("Dummy", fullName);
-      g_free (fullName);
+
+    player = games_sound_new (&error);
+    if (error) {
+      printf(error);
     }
-    connection = gnome_sound_connection_get ();
   }
 
   soundOn = TRUE;
@@ -99,10 +79,24 @@
 
 void Sound::playSound (int soundId)
 {
+  char *error;
+  gchar * fullName;
+
   if (!soundOn)
     return;
 
-  esd_sample_play (connection, sampleIds[soundId]);
+  fullName = gnome_program_locate_file (NULL, 
+					GNOME_FILE_DOMAIN_APP_SOUND,
+					soundFiles[soundId], FALSE, NULL);
+  games_sound_set_file (player, fullName, &error);
+  g_free (fullName);
+
+  if (error) {
+    printf (error);
+  }
+
+  games_sound_play (player);
+  games_sound_tell (player);
+
 }
 
-#endif
Index: gnometris/sounds/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-games/gnometris/sounds/Makefile.am,v
retrieving revision 1.1
diff -u -r1.1 Makefile.am
--- gnometris/sounds/Makefile.am	18 Jul 2004 07:50:21 -0000	1.1
+++ gnometris/sounds/Makefile.am	9 Jul 2006 10:54:21 -0000
@@ -1,7 +1,7 @@
 sounddir=$(datadir)/sounds/gnometris
 
 sound_DATA = \
-	gameover.wav gnometris.wav land.wav lines1.wav lines2.wav \
-	lines3.wav slide.wav turn.wav
+	gameover.ogg gnometris.ogg land.ogg lines1.ogg lines2.ogg \
+	lines3.ogg slide.ogg turn.ogg
 
 EXTRA_DIST = $(sound_DATA)
Index: libgames-support/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-games/libgames-support/Makefile.am,v
retrieving revision 1.41
diff -u -r1.41 Makefile.am
--- libgames-support/Makefile.am	14 Apr 2006 04:54:14 -0000	1.41
+++ libgames-support/Makefile.am	9 Jul 2006 10:54:21 -0000
@@ -79,6 +79,8 @@
 	games-scores.h			\
 	games-scores-backend.c		\
 	games-scores-backend.h		\
+	games-sound.c			\
+	games-sound.h			\
 	$(NULL)
 
 %.c %.h %-private.h: %.gob
Index: libgames-support/games-sound.c
===================================================================
RCS file: libgames-support/games-sound.c
diff -N libgames-support/games-sound.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgames-support/games-sound.c	9 Jul 2006 10:54:22 -0000
@@ -0,0 +1,397 @@
+
+/* games-sound.c  - Common sound code for gnome-games.
+ *
+ * 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 <config.h>
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gnome.h>
+
+#include "games-sound.h"
+
+static void player_class_init (PlayerClass * klass);
+static void player_init (Player * player);
+static void player_finalize (GObject * object);
+static gboolean bus_message_cb (GstBus * bus,
+				GstMessage * message, gpointer data);
+static gboolean tick_timeout (Player * player);
+static void player_construct (Player * player, char **error);
+
+enum
+{
+  END_OF_STREAM,
+  TICK,
+  ERROR,
+  LAST_SIGNAL
+};
+
+struct _PlayerPriv
+{
+  GstElement *play;
+
+  char *current_file;
+
+  guint iterate_idle_id;
+  guint tick_timeout_id;
+
+  GTimer *timer;
+  long timer_add;
+};
+
+static GObjectClass *parent_class;
+static guint signals[LAST_SIGNAL];
+
+/**
+ * games_sound_new:
+ * @error: Possible errors are set to this pointer.
+ *
+ * This function creates a new Player instance.
+ *
+ **/
+Player *
+games_sound_new (char **error)
+{
+  Player *player;
+
+  player = g_object_new (TYPE_PLAYER, NULL);
+
+  *error = NULL;
+
+  player_construct (player, error);
+
+  return player;
+}
+
+/**
+ * games_sound_set_file:
+ * @player: Player instance to configure.
+ * @file: Filename of a valid sound file, such as .ogg og .wav
+ * @error: Possible errors are set to this pointer.
+ *
+ * This function configures the Player instance to set the sound
+ * file to be played. 
+ *
+ **/
+gboolean
+games_sound_set_file (Player * player, const char *file, char **error)
+{
+
+  g_return_val_if_fail (IS_PLAYER (player), FALSE);
+
+  *error = NULL;
+
+  games_sound_stop (player);
+
+  if (!file)
+    return FALSE;
+
+  g_timer_stop (player->priv->timer);
+  g_timer_reset (player->priv->timer);
+  player->priv->timer_add = 0;
+
+  // FIXME get rid of this one when the switch to gnome-vfs is made
+  player->priv->current_file = g_strdup_printf ("file://%s", file);
+
+  g_object_set (G_OBJECT (player->priv->play), "uri",
+		player->priv->current_file, NULL);
+
+  return TRUE;
+}
+
+/**
+ * games_sound_start:
+ * @player: Player instance to start playing.
+ *
+ * This function starts the Player instance to play a sound.
+ * Must be followed by a call to games_sound_tell ().
+ *
+ **/
+void
+games_sound_play (Player * player)
+{
+  g_return_if_fail (IS_PLAYER (player));
+
+  gst_element_set_state (GST_ELEMENT (player->priv->play), GST_STATE_PLAYING);
+
+  g_timer_start (player->priv->timer);
+}
+
+/**
+ * games_sound_stop:
+ * @player: Player instance to stop playing.
+ *
+ * This function stops the sound being played by the Player instance.
+ *
+ **/
+
+void
+games_sound_stop (Player * player)
+{
+  g_return_if_fail (IS_PLAYER (player));
+
+  g_free (player->priv->current_file);
+  player->priv->current_file = NULL;
+
+  g_timer_stop (player->priv->timer);
+  g_timer_reset (player->priv->timer);
+  player->priv->timer_add = 0;
+
+  gst_element_set_state (GST_ELEMENT (player->priv->play), GST_STATE_READY);
+}
+
+/**
+ * games_sound_tell:
+ * @player: Player instance to play the sound.
+ *
+ * This function triggers the Player instance to play a sound.
+ *
+ **/
+
+int
+games_sound_tell (Player * player)
+{
+  g_return_val_if_fail (IS_PLAYER (player), -1);
+
+  return (int) floor (g_timer_elapsed (player->priv->timer, NULL) + 0.5) +
+    player->priv->timer_add;
+}
+
+/**
+ * Returns the games sound type, of the current player instance.
+ **/
+GType
+games_sound_get_type (void)
+{
+  static GType type = 0;
+
+  if (!type)
+    {
+      static const GTypeInfo info = {
+	sizeof (PlayerClass),
+	NULL,			/* base_init */
+	NULL,			/* base_finalize */
+	(GClassInitFunc) player_class_init,
+	NULL,			/* class_finalize */
+	NULL,			/* class_data */
+	sizeof (Player),
+	0,
+	(GInstanceInitFunc) player_init,
+	NULL
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, "Player", &info, 0);
+    }
+
+  return type;
+}
+
+static gboolean
+tick_timeout (Player * player)
+{
+  GstState state;
+
+  gst_element_get_state (player->priv->play, &state, NULL, 0);
+  if (state != GST_STATE_PLAYING)
+    return TRUE;
+
+  g_signal_emit (player, signals[TICK], 0, games_sound_tell (player));
+
+  return TRUE;
+}
+
+static gboolean
+iterate_cb (Player * player)
+{
+  gboolean res;
+  GstState state;
+
+  g_usleep (100);
+
+  gst_element_get_state (player->priv->play, &state, NULL, 0);
+
+  res = (state == GST_STATE_PLAYING);
+
+  if (!res)
+    player->priv->iterate_idle_id = 0;
+
+  return res;
+}
+
+static gboolean
+bus_message_cb (GstBus * UNUSED (bus), GstMessage * message, gpointer data)
+{
+  Player *player = (Player *) data;
+  char *debug;
+  GError *err;
+  GstState old_state, new_state;
+
+  switch (GST_MESSAGE_TYPE (message))
+    {
+    case GST_MESSAGE_ERROR:
+      gst_message_parse_error (message, &err, &debug);
+
+      /* Stop playing so we don't get repeated error messages. 
+         Might lead to troubles with threads, not sure.
+       */
+      games_sound_stop (player);
+
+      g_signal_emit (player, signals[ERROR], 0, g_strdup (err->message));
+      break;
+
+    case GST_MESSAGE_EOS:
+      player->priv->timer_add +=
+	floor (g_timer_elapsed (player->priv->timer, NULL) + 0.5);
+      g_timer_stop (player->priv->timer);
+      g_timer_reset (player->priv->timer);
+
+      g_signal_emit (player, signals[END_OF_STREAM], 0);
+      break;
+
+    case GST_MESSAGE_STATE_CHANGED:
+      gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
+
+      if (old_state == GST_STATE_PLAYING)
+	{
+	  if (player->priv->iterate_idle_id != 0)
+	    {
+	      g_source_remove (player->priv->iterate_idle_id);
+	      player->priv->iterate_idle_id = 0;
+	    }
+	}
+      else if (new_state == GST_STATE_PLAYING)
+	{
+	  if (player->priv->iterate_idle_id != 0)
+	    g_source_remove (player->priv->iterate_idle_id);
+	  player->priv->iterate_idle_id =
+	    g_idle_add ((GSourceFunc) iterate_cb, player);
+	}
+
+      break;
+
+    default:
+      break;
+    }
+
+  return TRUE;
+}
+
+static void
+player_class_init (PlayerClass * klass)
+{
+  GObjectClass *object_class;
+
+  parent_class = g_type_class_peek_parent (klass);
+  object_class = (GObjectClass *) klass;
+
+  object_class->finalize = player_finalize;
+
+  signals[END_OF_STREAM] =
+    g_signal_new ("end_of_stream",
+		  G_TYPE_FROM_CLASS (klass),
+		  G_SIGNAL_RUN_LAST,
+		  0,
+		  NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+  signals[TICK] =
+    g_signal_new ("tick",
+		  G_TYPE_FROM_CLASS (klass),
+		  G_SIGNAL_RUN_LAST,
+		  0,
+		  NULL, NULL,
+		  g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+
+  signals[ERROR] =
+    g_signal_new ("error",
+		  G_TYPE_FROM_CLASS (klass),
+		  G_SIGNAL_RUN_LAST,
+		  0,
+		  NULL, NULL,
+		  g_cclosure_marshal_VOID__STRING,
+		  G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
+static void
+player_init (Player * UNUSED (player))
+{
+}
+
+static void
+player_construct (Player * player, char **error)
+{
+  PlayerPriv *priv;
+  GstElement *sink;
+
+  gst_init (NULL, NULL);
+
+  priv = g_new0 (PlayerPriv, 1);
+  player->priv = priv;
+
+  priv->timer = g_timer_new ();
+  g_timer_stop (priv->timer);
+  priv->timer_add = 0;
+
+  priv->tick_timeout_id =
+    g_timeout_add (200, (GSourceFunc) tick_timeout, player);
+
+  priv->play = gst_element_factory_make ("playbin", "play");
+  if (!priv->play)
+    {
+      *error = g_strdup (_("Failed to create a GStreamer play object."));
+
+      return;
+    }
+
+  sink = gst_element_factory_make ("gconfaudiosink", "sink");
+  if (!sink)
+    {
+      *error =
+	g_strdup (_("Could not render default GStreamer audio output sink."));
+
+      return;
+    }
+
+  g_object_set (G_OBJECT (priv->play), "audio-sink", sink, NULL);
+
+  gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (priv->play)),
+		     bus_message_cb, player);
+}
+
+static void
+player_finalize (GObject * object)
+{
+  Player *player = PLAYER (object);
+
+  games_sound_stop (player);
+
+  g_timer_destroy (player->priv->timer);
+
+  if (player->priv->iterate_idle_id > 0)
+    g_source_remove (player->priv->iterate_idle_id);
+  if (player->priv->tick_timeout_id > 0)
+    g_source_remove (player->priv->tick_timeout_id);
+
+  g_object_unref (player->priv->play);
+
+  g_free (player->priv);
+
+  if (G_OBJECT_CLASS (parent_class)->finalize)
+    (*G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+
Index: libgames-support/games-sound.h
===================================================================
RCS file: libgames-support/games-sound.h
diff -N libgames-support/games-sound.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgames-support/games-sound.h	9 Jul 2006 10:54:22 -0000
@@ -0,0 +1,77 @@
+
+/* games-sound.h  - Common sound code for gnome-games.
+ * 
+ * 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 __GAMES_SOUND_H__
+#define __GAMES_SOUND_H__
+
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif  /* __cplusplus */
+
+
+#define TYPE_PLAYER            (games_sound_get_type ())
+#define PLAYER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PLAYER, Player))
+#define PLAYER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PLAYER, PlayerClass))
+#define IS_PLAYER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PLAYER))
+#define IS_PLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PLAYER))
+#define PLAYER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PLAYER, PlayerClass))
+
+typedef struct _Player Player;
+typedef struct _PlayerClass PlayerClass;
+typedef struct _PlayerPriv PlayerPriv;
+
+struct _Player
+{
+  GObject parent;
+  PlayerPriv *priv;
+};
+
+struct _PlayerClass
+{
+  GObjectClass parent_class;
+};
+
+Player *games_sound_new (char **error);
+gboolean games_sound_set_file (Player * player,
+			  const char *filename, char **error);
+void games_sound_play (Player * player);
+void games_sound_stop (Player * player);
+int games_sound_tell (Player * player);
+GType games_sound_get_type (void);
+
+#ifdef UNUSED
+#elif defined(__GNUC__)
+# define UNUSED(x) UNUSED_ ##x __attribute__((unused))
+#elif defined(__LCLINT__)
+# define UNUSED(x) /*@unused@*/ x
+#else
+# define UNUSED(x) x
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif	/* __cplusplus */
+
+
+#endif	/* __GAMES_SOUND_H__ */
+
Index: po/POTFILES.in
===================================================================
RCS file: /cvs/gnome/gnome-games/po/POTFILES.in,v
retrieving revision 1.101
diff -u -r1.101 POTFILES.in
--- po/POTFILES.in	17 Jun 2006 06:08:05 -0000	1.101
+++ po/POTFILES.in	9 Jul 2006 10:54:22 -0000
@@ -175,6 +175,7 @@
 libgames-support/games-preimage.c
 libgames-support/games-scores-dialog.c
 libgames-support/games-scores-dialog.gob
+libgames-support/games-sound.c
 libgames-support/games-stock.c
 libgames-support/libgnomegames.schemas.in
 mahjongg/drawing.c
