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