Mercurial > pidgin
annotate src/gtksound.c @ 11157:f068eaabe332
[gaim-migrate @ 13242]
Patch submitted to gaim-devel...
"Marcin Owsiany sent you a draft advisory regarding multiple libgadu
vulnerabilities. "Fortunately" gaim contains an extremely old version of
libgadu and is affected only by memory alignment bug, which cannot be
exploited on x86. No other critical vulnerabilities are known in gaim's
version of libgadu.
You'll find the patch in attachment.
Regards,
Wojtek Kaniewski
ekg/libgadu maintainer"
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Mon, 25 Jul 2005 21:20:14 +0000 |
parents | e25575a59f01 |
children | bb0d7b719af2 |
rev | line source |
---|---|
5684 | 1 /* |
10297
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10158
diff
changeset
|
2 * @file gtksound.h GTK+ Sound |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10158
diff
changeset
|
3 * @ingroup gtkui |
ec140184437b
[gaim-migrate @ 11480]
Luke Schierer <lschiere@pidgin.im>
parents:
10158
diff
changeset
|
4 * |
5684 | 5 * gaim |
6 * | |
8046 | 7 * Gaim is the legal property of its developers, whose names are too numerous |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
5684 | 10 * |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 * | |
25 */ | |
9791 | 26 #include "internal.h" |
27 #include "gtkgaim.h" | |
5684 | 28 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
29 #ifdef _WIN32 |
5684 | 30 #include <windows.h> |
31 #include <mmsystem.h> | |
32 #endif | |
33 | |
34 #ifdef USE_AO | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
35 # include <ao/ao.h> |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
36 # include <audiofile.h> |
5684 | 37 #endif /* USE_AO */ |
38 | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
39 #include "debug.h" |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
40 #include "notify.h" |
5684 | 41 #include "prefs.h" |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
42 #include "sound.h" |
7465 | 43 #include "util.h" |
5684 | 44 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
45 #include "gtksound.h" |
5684 | 46 |
47 struct gaim_sound_event { | |
48 char *label; | |
49 char *pref; | |
50 char *def; | |
51 }; | |
52 | |
10074 | 53 #define PLAY_SOUND_TIMEOUT 15000 |
5684 | 54 |
10320 | 55 static guint mute_login_sounds_timeout = 0; |
5684 | 56 static gboolean mute_login_sounds = FALSE; |
6199 | 57 static gboolean sound_initialized = FALSE; |
5684 | 58 |
59 static struct gaim_sound_event sounds[GAIM_NUM_SOUNDS] = { | |
10158 | 60 {N_("Buddy logs in"), "login", "login.wav"}, |
61 {N_("Buddy logs out"), "logout", "logout.wav"}, | |
5684 | 62 {N_("Message received"), "im_recv", "receive.wav"}, |
63 {N_("Message received begins conversation"), "first_im_recv", "receive.wav"}, | |
64 {N_("Message sent"), "send_im", "send.wav"}, | |
10158 | 65 {N_("Person enters chat"), "join_chat", "login.wav"}, |
66 {N_("Person leaves chat"), "left_chat", "logout.wav"}, | |
5684 | 67 {N_("You talk in chat"), "send_chat_msg", "send.wav"}, |
68 {N_("Others talk in chat"), "chat_msg_recv", "receive.wav"}, | |
69 /* this isn't a terminator, it's the buddy pounce default sound event ;-) */ | |
10158 | 70 {NULL, "pounce_default", "alert.wav"}, |
71 {N_("Someone says your name in chat"), "nick_said", "alert.wav"} | |
5684 | 72 }; |
73 | |
74 #ifdef USE_AO | |
75 static int ao_driver = -1; | |
76 #endif /* USE_AO */ | |
77 | |
10320 | 78 static gboolean |
79 mute_login_sounds_cb(gpointer data) | |
80 { | |
81 mute_login_sounds = FALSE; | |
82 mute_login_sounds_timeout = 0; | |
83 return FALSE; | |
84 } | |
85 | |
86 /* | |
87 * We mute sounds for the 10 seconds after you log in so that | |
88 * you don't get flooded with sounds when the blist shows all | |
89 * your buddies logging in. | |
90 */ | |
91 static void | |
92 account_signon_cb(GaimConnection *gc, gpointer data) | |
93 { | |
94 if (mute_login_sounds_timeout != 0) | |
95 g_source_remove(mute_login_sounds_timeout); | |
96 mute_login_sounds = TRUE; | |
97 mute_login_sounds_timeout = gaim_timeout_add(10000, mute_login_sounds_cb, NULL); | |
98 } | |
99 | |
10322 | 100 static void |
101 _pref_sound_method_changed(const char *name, GaimPrefType type, | |
102 gpointer val, gpointer data) { | |
103 if(type != GAIM_PREF_STRING || strcmp(name, "/gaim/gtk/sound/method")) | |
104 return; | |
105 | |
106 sound_initialized = TRUE; | |
107 | |
108 #ifdef USE_AO | |
109 ao_driver = -1; | |
110 | |
111 if(!strcmp(val, "esd")) | |
112 ao_driver = ao_driver_id("esd"); | |
113 else if(!strcmp(val, "arts")) | |
114 ao_driver = ao_driver_id("arts"); | |
11082 | 115 else if(!strcmp(val, "nas")) |
116 ao_driver = ao_driver_id("nas"); | |
10322 | 117 else if(!strcmp(val, "automatic")) |
118 ao_driver = ao_default_driver_id(); | |
119 | |
120 if(ao_driver != -1) { | |
121 ao_info *info = ao_driver_info(ao_driver); | |
122 gaim_debug_info("sound", | |
123 "Sound output driver loaded: %s\n", info->name); | |
124 } | |
125 #endif /* USE_AO */ | |
126 } | |
127 | |
128 const char * | |
129 gaim_gtk_sound_get_event_option(GaimSoundEventID event) | |
130 { | |
131 if(event >= GAIM_NUM_SOUNDS) | |
132 return 0; | |
133 | |
134 return sounds[event].pref; | |
135 } | |
136 | |
137 char * | |
138 gaim_gtk_sound_get_event_label(GaimSoundEventID event) | |
139 { | |
140 if(event >= GAIM_NUM_SOUNDS) | |
141 return NULL; | |
142 | |
143 return sounds[event].label; | |
144 } | |
145 | |
146 void * | |
147 gaim_gtk_sound_get_handle() | |
148 { | |
149 static int handle; | |
150 | |
151 return &handle; | |
152 } | |
153 | |
154 static void | |
155 gaim_gtk_sound_init(void) | |
5684 | 156 { |
10320 | 157 void *gtk_sound_handle = gaim_gtk_sound_get_handle(); |
158 | |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10922
diff
changeset
|
159 gaim_debug_register_category("sound"); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10922
diff
changeset
|
160 |
10320 | 161 gaim_signal_connect(gaim_connections_get_handle(), "signed-on", |
162 gtk_sound_handle, GAIM_CALLBACK(account_signon_cb), | |
163 NULL); | |
164 | |
5684 | 165 gaim_prefs_add_none("/gaim/gtk/sound"); |
166 gaim_prefs_add_none("/gaim/gtk/sound/enabled"); | |
167 gaim_prefs_add_none("/gaim/gtk/sound/file"); | |
168 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/login", TRUE); | |
169 gaim_prefs_add_string("/gaim/gtk/sound/file/login", ""); | |
170 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/logout", TRUE); | |
171 gaim_prefs_add_string("/gaim/gtk/sound/file/logout", ""); | |
172 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/im_recv", TRUE); | |
173 gaim_prefs_add_string("/gaim/gtk/sound/file/im_recv", ""); | |
174 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/first_im_recv", FALSE); | |
175 gaim_prefs_add_string("/gaim/gtk/sound/file/first_im_recv", ""); | |
176 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/send_im", TRUE); | |
177 gaim_prefs_add_string("/gaim/gtk/sound/file/send_im", ""); | |
178 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/join_chat", FALSE); | |
179 gaim_prefs_add_string("/gaim/gtk/sound/file/join_chat", ""); | |
180 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/left_chat", FALSE); | |
181 gaim_prefs_add_string("/gaim/gtk/sound/file/left_chat", ""); | |
182 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/send_chat_msg", FALSE); | |
183 gaim_prefs_add_string("/gaim/gtk/sound/file/send_chat_msg", ""); | |
184 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/chat_msg_recv", FALSE); | |
185 gaim_prefs_add_string("/gaim/gtk/sound/file/chat_msg_recv", ""); | |
186 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/nick_said", FALSE); | |
187 gaim_prefs_add_string("/gaim/gtk/sound/file/nick_said", ""); | |
7460
3973a09525b3
[gaim-migrate @ 8073]
Christian Hammond <chipx86@chipx86.com>
parents:
7035
diff
changeset
|
188 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/pounce_default", TRUE); |
3973a09525b3
[gaim-migrate @ 8073]
Christian Hammond <chipx86@chipx86.com>
parents:
7035
diff
changeset
|
189 gaim_prefs_add_string("/gaim/gtk/sound/file/pounce_default", ""); |
8633 | 190 gaim_prefs_add_bool("/gaim/gtk/sound/conv_focus", TRUE); |
10074 | 191 gaim_prefs_add_bool("/gaim/gtk/sound/mute", FALSE); |
5684 | 192 gaim_prefs_add_string("/gaim/gtk/sound/command", ""); |
193 gaim_prefs_add_string("/gaim/gtk/sound/method", "automatic"); | |
194 | |
195 #ifdef USE_AO | |
10322 | 196 gaim_debug_info("sound", "Initializing sound output drivers.\n"); |
5684 | 197 ao_initialize(); |
198 #endif /* USE_AO */ | |
199 | |
10087 | 200 gaim_prefs_connect_callback(gaim_gtk_sound_get_handle(), "/gaim/gtk/sound/method", |
5794
5e93fc46d1af
[gaim-migrate @ 6219]
Christian Hammond <chipx86@chipx86.com>
parents:
5684
diff
changeset
|
201 _pref_sound_method_changed, NULL); |
5684 | 202 } |
203 | |
10322 | 204 static void |
205 gaim_gtk_sound_uninit(void) | |
5684 | 206 { |
207 #ifdef USE_AO | |
208 ao_shutdown(); | |
209 #endif | |
6199 | 210 sound_initialized = FALSE; |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10922
diff
changeset
|
211 |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10922
diff
changeset
|
212 gaim_debug_unregister_category("sound"); |
5684 | 213 } |
214 | |
11082 | 215 #if defined(USE_AO) |
10322 | 216 static gboolean |
217 expire_old_child(gpointer data) | |
10074 | 218 { |
219 int ret; | |
220 pid_t pid = GPOINTER_TO_INT(data); | |
221 | |
222 ret = waitpid(pid, NULL, WNOHANG | WUNTRACED); | |
223 | |
224 if(ret == 0) { | |
225 if(kill(pid, SIGKILL) < 0) | |
10322 | 226 gaim_debug_error("gtksound", "Killing process %d failed (%s)\n", |
227 pid, strerror(errno)); | |
10074 | 228 } |
229 | |
230 return FALSE; /* do not run again */ | |
231 } | |
232 #endif | |
233 | |
10322 | 234 static void |
235 gaim_gtk_sound_play_file(const char *filename) | |
5684 | 236 { |
237 const char *method; | |
11082 | 238 #if defined(USE_AO) |
5684 | 239 pid_t pid; |
240 #ifdef USE_AO | |
241 AFfilehandle file; | |
242 #endif | |
243 #endif | |
244 | |
6199 | 245 if (!sound_initialized) |
246 gaim_prefs_trigger_callback("/gaim/gtk/sound/method"); | |
247 | |
10074 | 248 if (gaim_prefs_get_bool("/gaim/gtk/sound/mute")) |
5684 | 249 return; |
250 | |
251 method = gaim_prefs_get_string("/gaim/gtk/sound/method"); | |
252 | |
10074 | 253 if (!strcmp(method, "none")) { |
254 return; | |
255 } else if (!strcmp(method, "beep")) { | |
5684 | 256 gdk_beep(); |
257 return; | |
258 } | |
259 | |
260 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { | |
261 char *tmp = g_strdup_printf(_("Unable to play sound because the chosen file (%s) does not exist."), filename); | |
262 gaim_notify_error(NULL, NULL, tmp, NULL); | |
263 g_free(tmp); | |
264 return; | |
265 } | |
266 | |
267 #ifndef _WIN32 | |
268 if (!strcmp(method, "custom")) { | |
269 const char *sound_cmd; | |
270 char *command; | |
271 GError *error = NULL; | |
272 | |
273 sound_cmd = gaim_prefs_get_string("/gaim/gtk/sound/command"); | |
274 | |
275 if (!sound_cmd || *sound_cmd == '\0') { | |
276 gaim_notify_error(NULL, NULL, | |
277 _("Unable to play sound because the " | |
278 "'Command' sound method has been chosen, " | |
279 "but no command has been set."), NULL); | |
280 return; | |
281 } | |
282 | |
7464 | 283 if(strstr(sound_cmd, "%s")) |
284 command = gaim_strreplace(sound_cmd, "%s", filename); | |
285 else | |
286 command = g_strdup_printf("%s %s", sound_cmd, filename); | |
5684 | 287 |
288 if(!g_spawn_command_line_async(command, &error)) { | |
289 char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message); | |
290 gaim_notify_error(NULL, NULL, tmp, NULL); | |
291 g_free(tmp); | |
292 g_error_free(error); | |
293 } | |
294 | |
295 g_free(command); | |
296 return; | |
297 } | |
11082 | 298 #if defined(USE_AO) |
5684 | 299 pid = fork(); |
300 if (pid < 0) | |
301 return; | |
302 else if (pid == 0) { | |
303 #ifdef USE_AO | |
304 file = afOpenFile(filename, "rb", NULL); | |
305 if(file) { | |
306 ao_device *device; | |
307 ao_sample_format format; | |
308 int in_fmt; | |
309 int bytes_per_frame; | |
310 | |
311 format.rate = afGetRate(file, AF_DEFAULT_TRACK); | |
312 format.channels = afGetChannels(file, AF_DEFAULT_TRACK); | |
313 afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt, | |
314 &format.bits); | |
315 | |
316 /* XXX: libao doesn't seem to like 8-bit sounds, so we'll | |
317 * let libaudiofile make them a bit better for us */ | |
318 if(format.bits == 8) | |
319 format.bits = 16; | |
320 | |
321 afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, | |
322 AF_SAMPFMT_TWOSCOMP, format.bits); | |
323 | |
324 #if __BYTE_ORDER == __BIG_ENDIAN | |
325 format.byte_format = AO_FMT_BIG; | |
326 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
327 AF_BYTEORDER_BIGENDIAN); | |
328 #elif __BYTE_ORDER == __LITTLE_ENDIAN | |
329 format.byte_format = AO_FMT_LITTLE; | |
330 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
331 AF_BYTEORDER_LITTLEENDIAN); | |
332 #endif | |
333 | |
334 bytes_per_frame = format.bits * format.channels / 8; | |
335 | |
336 device = ao_open_live(ao_driver, &format, NULL); | |
337 | |
338 if(device) { | |
339 int frames_read; | |
340 char buf[4096]; | |
341 int buf_frames = sizeof(buf) / bytes_per_frame; | |
342 | |
343 while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK, | |
344 buf, buf_frames))) { | |
345 if(!ao_play(device, buf, frames_read * bytes_per_frame)) | |
346 break; | |
347 } | |
348 ao_close(device); | |
349 } | |
350 afCloseFile(file); | |
351 } | |
352 ao_shutdown(); | |
353 #endif /* USE_AO */ | |
354 _exit(0); | |
10074 | 355 } else { |
356 gaim_timeout_add(PLAY_SOUND_TIMEOUT, expire_old_child, GINT_TO_POINTER(pid)); | |
5684 | 357 } |
11082 | 358 #else /* USE_AO */ |
5684 | 359 gdk_beep(); |
360 return; | |
11082 | 361 #endif /* USE_AO */ |
5684 | 362 #else /* _WIN32 */ |
10322 | 363 gaim_debug_info("sound", "Playing %s\n", filename); |
5684 | 364 |
10922
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
365 if (G_WIN32_HAVE_WIDECHAR_API ()) { |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
366 wchar_t *wc_filename = g_utf8_to_utf16(filename, |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
367 -1, NULL, NULL, NULL); |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
368 if (!PlaySoundW(wc_filename, NULL, SND_ASYNC | SND_FILENAME)) |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
369 gaim_debug(GAIM_DEBUG_ERROR, "sound", "Error playing sound.\n"); |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
370 g_free(wc_filename); |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
371 } else { |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
372 char *l_filename = g_locale_from_utf8(filename, |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
373 -1, NULL, NULL, NULL); |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
374 if (!PlaySoundA(l_filename, NULL, SND_ASYNC | SND_FILENAME)) |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
375 gaim_debug(GAIM_DEBUG_ERROR, "sound", "Error playing sound.\n"); |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
376 g_free(l_filename); |
68083504217c
[gaim-migrate @ 12691]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
10322
diff
changeset
|
377 } |
5684 | 378 #endif /* _WIN32 */ |
379 } | |
380 | |
10322 | 381 static void |
382 gaim_gtk_sound_play_event(GaimSoundEventID event) | |
5684 | 383 { |
384 char *enable_pref; | |
385 char *file_pref; | |
386 | |
387 if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds) | |
388 return; | |
389 | |
390 if (event >= GAIM_NUM_SOUNDS) { | |
10322 | 391 gaim_debug_error("sound", "got request for unknown sound: %d\n", event); |
5684 | 392 return; |
393 } | |
394 | |
395 enable_pref = g_strdup_printf("/gaim/gtk/sound/enabled/%s", | |
396 sounds[event].pref); | |
397 file_pref = g_strdup_printf("/gaim/gtk/sound/file/%s", sounds[event].pref); | |
398 | |
399 /* check NULL for sounds that don't have an option, ie buddy pounce */ | |
400 if (gaim_prefs_get_bool(enable_pref)) { | |
401 char *filename = g_strdup(gaim_prefs_get_string(file_pref)); | |
402 if(!filename || !strlen(filename)) { | |
403 if(filename) g_free(filename); | |
404 filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL); | |
405 } | |
406 | |
407 gaim_sound_play_file(filename); | |
408 g_free(filename); | |
409 } | |
410 | |
411 g_free(enable_pref); | |
412 g_free(file_pref); | |
413 } | |
414 | |
415 static GaimSoundUiOps sound_ui_ops = | |
416 { | |
417 gaim_gtk_sound_init, | |
10322 | 418 gaim_gtk_sound_uninit, |
5684 | 419 gaim_gtk_sound_play_file, |
420 gaim_gtk_sound_play_event | |
421 }; | |
422 | |
7035
feb3d21a7794
[gaim-migrate @ 7598]
Christian Hammond <chipx86@chipx86.com>
parents:
6778
diff
changeset
|
423 GaimSoundUiOps * |
feb3d21a7794
[gaim-migrate @ 7598]
Christian Hammond <chipx86@chipx86.com>
parents:
6778
diff
changeset
|
424 gaim_gtk_sound_get_ui_ops(void) |
5684 | 425 { |
426 return &sound_ui_ops; | |
427 } |