1 /*
2  * games-sound.c: common sound player for gnome-games
3  *
4  * Copyright © 2007-2008 Andreas Røsdal
5  * Copyright © 2009 Christian Persch
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include <config.h>
24 
25 #include <glib.h>
26 #include <glib/gi18n.h>
27 
28 #ifdef ENABLE_SOUND
29 #include <canberra-gtk.h>
30 #endif
31 
32 #include "ar-debug.h"
33 #include "ar-runtime.h"
34 
35 #include "ar-sound.h"
36 
37 #ifdef ENABLE_SOUND
38 
39 static gboolean sound_enabled = FALSE;
40 
41 typedef enum {
42   GAMES_SOUND_PLAIN,
43   GAMES_SOUND_FOR_EVENT,
44   GAMES_SOUND_FOR_WIDGET
45 } GamesSoundCanberraType;
46 
47 static void
ar_sound_canberra_play(const char * sound_name,GamesSoundCanberraType type,gpointer data)48 ar_sound_canberra_play (const char *sound_name,
49                            GamesSoundCanberraType type,
50                            gpointer data)
51 {
52   char *name, *path;
53   int rv;
54 
55   if (!sound_enabled)
56     return;
57 
58   name = g_strdup_printf ("%s.ogg", sound_name);
59   path = ar_runtime_get_file (AR_RUNTIME_SOUND_DIRECTORY, name);
60   g_free (name);
61 
62   switch (type) {
63     case GAMES_SOUND_PLAIN:
64 #if 1
65       /* FIXMEchpe: instead, make sure all games call ar_sound_init()
66        * themselves!
67        */
68       ar_sound_init (data);
69 #endif
70 
71 #ifdef GNOME_ENABLE_DEBUG
72       _AR_DEBUG_IF (AR_DEBUG_SOUND) {
73         if (!GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "games-sound-initialised")))
74           ar_debug_print (AR_DEBUG_SOUND,
75                               "ar_sound_play_for_screen called for display %s screen %d but canberra-gtk context not initialised!",
76                               gdk_display_get_name (gdk_screen_get_display (data)),
77                               gdk_screen_get_number (data));
78       }
79 #endif /* GNOME_ENABLE_DEBUG */
80 
81       rv =  ca_context_play (
82                              ca_gtk_context_get_for_screen (data),
83                              0,
84                              CA_PROP_MEDIA_NAME, sound_name,
85                              CA_PROP_MEDIA_FILENAME, path,
86                              NULL);
87       break;
88     case GAMES_SOUND_FOR_EVENT:
89       rv =  ca_gtk_play_for_event (data,
90                                    0,
91                                    CA_PROP_MEDIA_NAME, sound_name,
92                                    CA_PROP_MEDIA_FILENAME, path,
93                                    NULL);
94       break;
95     case GAMES_SOUND_FOR_WIDGET:
96       rv =  ca_gtk_play_for_widget (data,
97                                     0,
98                                     CA_PROP_MEDIA_NAME, sound_name,
99                                     CA_PROP_MEDIA_FILENAME, path,
100                                     NULL);
101       break;
102     default:
103       g_assert_not_reached ();
104   }
105 
106   ar_debug_print (AR_DEBUG_SOUND,
107                       "libcanberra playing sound %s [file %s]: %s\n",
108                       sound_name, path, ca_strerror (rv));
109 
110   g_free (path);
111 }
112 
113 #endif /* ENABLE_SOUND */
114 
115 /**
116  * ar_sound_init:
117  * @screen: a #GdkScreen
118  *
119  * Initialises the sound context of @screen. Should be called
120  * when creating a window on @screen, or when a window is moved to
121  * @screen. It is safe to call this multiple times for the same
122  * @screen.
123  */
124 void
ar_sound_init(GdkScreen * screen)125 ar_sound_init (GdkScreen *screen)
126 {
127 #ifdef ENABLE_SOUND
128   ca_context *context;
129 
130   if (screen == NULL)
131     screen = gdk_screen_get_default ();
132 
133   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (screen), "games-sound-initialised")))
134     return;
135 
136   ar_debug_print (AR_DEBUG_SOUND,
137                       "Initialising canberra-gtk context for display %s screen %d\n",
138                       gdk_display_get_name (gdk_screen_get_display (screen)),
139                       gdk_screen_get_number (screen));
140 
141   context = ca_gtk_context_get_for_screen (screen);
142   if (!context)
143     return;
144 
145   ca_context_change_props (context,
146                            CA_PROP_MEDIA_ROLE, "game",
147                            NULL);
148 
149   g_object_set_data (G_OBJECT (screen), "games-sound-initialised", GINT_TO_POINTER (TRUE));
150 #endif /* ENABLE_SOUND */
151 }
152 
153 /**
154  * ar_sound_play:
155  * @sound_name: the sound file to player
156  *
157  * Plays a sound with the given filename from the
158  * AR_RUNTIME_SOUND_DIRECTORY directory in .ogg format.
159  * Sound is played asynchronously; i.e. this function does not block
160  * until the sound has finished playing.
161  *
162  * Use ar_sound_play_for_screen(), ar_sound_play_for_event()
163  * or ar_sound_play_for_widget() instead.
164  */
165 void
ar_sound_play(const gchar * sound_name)166 ar_sound_play (const gchar * sound_name)
167 {
168   ar_sound_play_for_screen (sound_name, gdk_screen_get_default ());
169 }
170 
171 /**
172  * ar_sound_play_for_screen:
173  * @sound_name: the sound file to player
174  *
175  * Plays a sound with the given filename from the
176  * AR_RUNTIME_SOUND_DIRECTORY directory in .ogg format.
177  * Sound is played asynchronously; i.e. this function does not block
178  * until the sound has finished playing.
179  *
180  * Consider using ar_sound_play_for_event() or ar_sound_play_for_widget()
181  * instead.
182  */
183 void
ar_sound_play_for_screen(const gchar * sound_name,GdkScreen * screen)184 ar_sound_play_for_screen (const gchar * sound_name,
185                              GdkScreen *screen)
186 {
187 #if defined(ENABLE_SOUND)
188   ar_sound_canberra_play (sound_name, GAMES_SOUND_PLAIN, screen);
189 #endif
190 }
191 
192 /**
193  * ar_sound_play_for_event:
194  * @sound_name: the name of the sound to play
195  * @event: the #GdkEvent associated with the sound
196  *
197  * Plays a sound for @event.
198  * See ar_sound_play() for more information.
199  */
200 void
ar_sound_play_for_event(const gchar * sound_name,GdkEvent * event)201 ar_sound_play_for_event (const gchar *sound_name,
202                             GdkEvent *event)
203 {
204 #ifdef ENABLE_SOUND
205   ar_sound_canberra_play (sound_name, GAMES_SOUND_FOR_EVENT, event);
206 #endif /* ENABLE_SOUND */
207 }
208 
209 /**
210  * ar_sound_play_for_widget:
211  * @sound_name: the name of the sound to play
212  * @widget: the #GtkWidget to play the sound for
213  *
214  * Plays a sound for @widget. Use ar_sound_play_for_event() instead
215  * if the sound is associated with an event.
216  *
217  * See ar_sound_play() for more information.
218  */
219 void
ar_sound_play_for_widget(const gchar * sound_name,GtkWidget * widget)220 ar_sound_play_for_widget (const gchar *sound_name,
221                              GtkWidget *widget)
222 {
223 #ifdef ENABLE_SOUND
224   ar_sound_canberra_play (sound_name, GAMES_SOUND_FOR_WIDGET, widget);
225 #endif /* ENABLE_SOUND */
226 }
227 
228 /**
229  * ar_sound_enable:
230  * @enabled:
231  *
232  * Enables or disables sound support.
233  */
234 void
ar_sound_enable(gboolean enabled)235 ar_sound_enable (gboolean enabled)
236 {
237 #ifdef ENABLE_SOUND
238   sound_enabled = enabled;
239 #endif /* ENABLE_SOUND */
240 }
241 
242 /**
243  * ar_sound_is_enabled:
244  *
245  * Returns: %TRUE iff sound support is enabled.
246  */
247 gboolean
ar_sound_is_enabled(void)248 ar_sound_is_enabled (void)
249 {
250 #ifdef ENABLE_SOUND
251   return sound_enabled;
252 #else
253   return FALSE;
254 #endif /* ENABLE_SOUND */
255 }
256 
257 /**
258  * ar_sound_is_available:
259  *
260  * Returns: whether sound is available
261  */
262 gboolean
ar_sound_is_available(void)263 ar_sound_is_available (void)
264 {
265 #ifdef ENABLE_SOUND
266   return TRUE;
267 #else
268   return FALSE;
269 #endif /* ENABLE_SOUND */
270 }
271