Mercurial > pidgin
annotate src/sound.c @ 5105:4cfc49e31c2e
[gaim-migrate @ 5468]
David Brigada (jsi) writes:
" This patch changes GTK_WRAP_WORD to GTK_WRAP_WORD_CHAR
throughout the sources. That fixes a bug where long
single-word input into GtkTextViews and similar would
cause the textview to expand, causing the window to
expand. This fix depends on a patch to GTK+ that is in
current CVS but not yet released. To address the
backwards-compatibility issue, GTK_WRAP_WORD_CHAR is
#defined to GTK_WRAP_WORD when not defined by GTK+'s
header files.
The only problem I can forsee is binary compatibility;
if Gaim is compiled under a GTK+ CVS (or a future
release) environment, and then run under a GTK+ 2.2.1
or earlier environment, behavior is undefined; the text
area will probably not wrap at all. However, source
compatibility is maintained."
basically, gaim will start wrapping text in any version of gtk2 that supports it,
and should work exactly the same in any version that still has the bug.
many thanks to David for his hard work.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Fri, 11 Apr 2003 04:23:55 +0000 |
parents | 77b04219f3e2 |
children | 0241d6b6702d |
rev | line source |
---|---|
1 | 1 /* |
2 * gaim | |
3 * | |
4562 | 4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> |
4561 | 5 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> |
1 | 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 * | |
21 */ | |
22 | |
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
338
diff
changeset
|
23 #ifdef HAVE_CONFIG_H |
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2048
diff
changeset
|
24 #include <config.h> |
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
338
diff
changeset
|
25 #endif |
1 | 26 #include <stdio.h> |
1057
d50d3abb9eb7
[gaim-migrate @ 1067]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1006
diff
changeset
|
27 #include <stdlib.h> |
1 | 28 #include <string.h> |
3630 | 29 |
30 #ifndef _WIN32 | |
63 | 31 #include <unistd.h> |
3630 | 32 #else |
33 #include <windows.h> | |
34 #include <mmsystem.h> | |
35 #endif | |
36 | |
4592 | 37 #ifdef HAVE_ENDIAN_H |
38 #include <endian.h> | |
39 #endif | |
40 | |
4561 | 41 #ifdef USE_AO |
42 #include <ao/ao.h> | |
43 #include <audiofile.h> | |
44 #endif /* USE_AO */ | |
4581 | 45 #ifdef USE_NAS_AUDIO |
46 #include <audio/audiolib.h> | |
47 #include <audio/soundlib.h> | |
48 #endif /* USE_NAS_AUDIO */ | |
4012 | 49 |
1 | 50 #include "gaim.h" |
4561 | 51 #include "sound.h" |
1 | 52 |
4019
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
53 #ifdef _WIN32 |
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
54 #include "win32dep.h" |
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
55 #endif |
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
56 |
4561 | 57 struct gaim_sound_event { |
58 char *label; | |
59 guint opt; | |
60 char *def; | |
61 }; | |
62 | |
63 #ifdef USE_AO | |
4581 | 64 static gboolean ao_initialized=FALSE; |
65 static int ao_driver = -1; | |
4561 | 66 #endif /* USE_AO */ |
67 | |
68 | |
69 static gboolean mute_login_sounds = FALSE; | |
70 static gboolean mute_sounds = FALSE; | |
71 static char *sound_cmd = NULL; | |
3319 | 72 |
4082 | 73 /* description, option bit, default sound file * |
74 * set the option bit to 0 to have it not display in prefs * | |
75 * the order here has to match the defines in gaim.h. * | |
76 * -Robot101 */ | |
4561 | 77 static struct gaim_sound_event sounds[GAIM_NUM_SOUNDS] = { |
4013 | 78 {N_("Buddy logs in"), OPT_SOUND_LOGIN, "arrive.wav"}, |
79 {N_("Buddy logs out"), OPT_SOUND_LOGOUT, "leave.wav"}, | |
4012 | 80 {N_("Message received"), OPT_SOUND_RECV, "receive.wav"}, |
81 {N_("Message received begins conversation"), OPT_SOUND_FIRST_RCV, "receive.wav"}, | |
82 {N_("Message sent"), OPT_SOUND_SEND, "send.wav"}, | |
4013 | 83 {N_("Person enters chat"), OPT_SOUND_CHAT_JOIN, "arrive.wav"}, |
84 {N_("Person leaves chat"), OPT_SOUND_CHAT_PART, "leave.wav"}, | |
4012 | 85 {N_("You talk in chat"), OPT_SOUND_CHAT_YOU_SAY, "send.wav"}, |
86 {N_("Others talk in chat"), OPT_SOUND_CHAT_SAY, "receive.wav"}, | |
3326 | 87 /* this isn't a terminator, it's the buddy pounce default sound event ;-) */ |
4012 | 88 {NULL, 0, "redalert.wav"}, |
89 {N_("Someone says your name in chat"), OPT_SOUND_CHAT_NICK, "redalert.wav"} | |
3060 | 90 }; |
91 | |
4561 | 92 static char *sound_file[GAIM_NUM_SOUNDS]; |
4430 | 93 |
4581 | 94 |
95 #ifdef USE_AO | |
96 static void check_ao_init() | |
4430 | 97 { |
4581 | 98 if(!ao_initialized) { |
99 debug_printf("Initializing sound ouput drivers.\n"); | |
100 ao_initialize(); | |
101 ao_initialized = TRUE; | |
102 } | |
103 } | |
104 #endif /* USE_AO */ | |
4430 | 105 |
4581 | 106 void gaim_sound_change_output_method() { |
107 #ifdef USE_AO | |
108 ao_driver = -1; | |
4430 | 109 |
4581 | 110 if ((sound_options & OPT_SOUND_ESD) || (sound_options & OPT_SOUND_ARTS) || |
111 (sound_options & OPT_SOUND_NORMAL)) { | |
112 check_ao_init(); | |
113 if (ao_driver == -1 && (sound_options & OPT_SOUND_ESD)) { | |
114 ao_driver = ao_driver_id("esd"); | |
115 } | |
116 if(ao_driver == -1 && (sound_options & OPT_SOUND_ARTS)) { | |
117 ao_driver = ao_driver_id("arts"); | |
118 } | |
119 if (ao_driver == -1) { | |
120 ao_driver = ao_default_driver_id(); | |
121 } | |
122 } | |
123 if(ao_driver != -1) { | |
4561 | 124 ao_info *info = ao_driver_info(ao_driver); |
125 debug_printf("Sound output driver loaded: %s\n", info->name); | |
4430 | 126 } |
4581 | 127 #endif /* USE_AO */ |
128 #ifdef USE_NAS | |
129 if((sound_options & OPT_SOUND_NAS)) | |
130 debug_printf("Sound output driver loaded: NAS output\n"); | |
131 #endif /* USE_NAS */ | |
4430 | 132 } |
133 | |
4561 | 134 void gaim_sound_quit() |
4430 | 135 { |
4561 | 136 #ifdef USE_AO |
4581 | 137 if(ao_initialized) |
138 ao_shutdown(); | |
4561 | 139 #endif |
4430 | 140 } |
141 | |
4581 | 142 |
143 #ifdef USE_NAS_AUDIO | |
144 static gboolean play_file_nas(const char *filename) | |
145 { | |
146 AuServer *nas_serv; | |
147 gboolean ret = FALSE; | |
148 | |
149 if((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) { | |
150 ret = AuSoundPlaySynchronousFromFile(nas_serv, filename, 100); | |
151 AuCloseServer(nas_serv); | |
152 } | |
153 | |
154 return ret; | |
155 } | |
156 | |
157 #endif /* USE_NAS_AUDIO */ | |
158 | |
4561 | 159 void gaim_sound_play_file(char *filename) |
4430 | 160 { |
4581 | 161 #if defined(USE_NAS_AUDIO) || defined(USE_AO) |
4561 | 162 pid_t pid; |
4581 | 163 #ifdef USE_AO |
164 AFfilehandle file; | |
165 #endif | |
166 #endif | |
4430 | 167 |
4561 | 168 if (mute_sounds) |
169 return; | |
4430 | 170 |
3901 | 171 if (awaymessage && !(sound_options & OPT_SOUND_WHEN_AWAY)) |
172 return; /* check here in case a buddy pounce plays a file while away */ | |
4561 | 173 |
3004 | 174 if (sound_options & OPT_SOUND_BEEP) { |
175 gdk_beep(); | |
176 return; | |
177 } | |
178 | |
4561 | 179 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { |
180 char *tmp = g_strdup_printf(_("Unable to play sound because the chosen filename (%s) does not exist."), filename); | |
181 do_error_dialog(tmp, NULL, GAIM_ERROR); | |
182 g_free(tmp); | |
183 return; | |
3060 | 184 } |
4561 | 185 |
4430 | 186 #ifndef _WIN32 |
4561 | 187 if ((sound_options & OPT_SOUND_CMD)) { |
188 char *command; | |
189 GError *error = NULL; | |
190 | |
191 if(!sound_cmd) { | |
192 do_error_dialog(_("Unable to play sound because the 'Command' sound method has been chosen, but no command has been set."), NULL, GAIM_ERROR); | |
193 return; | |
194 } | |
195 | |
196 command = g_strdup_printf(sound_cmd, filename); | |
197 | |
198 if(!g_spawn_command_line_async(command, &error)) { | |
199 char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message); | |
200 do_error_dialog(tmp, NULL, GAIM_ERROR); | |
201 g_free(tmp); | |
202 g_error_free(error); | |
203 } | |
204 | |
205 g_free(command); | |
206 return; | |
207 } | |
4581 | 208 #if defined(USE_NAS_AUDIO) || defined(USE_AO) |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
209 pid = fork(); |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
210 if (pid < 0) |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
211 return; |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
212 else if (pid == 0) { |
4581 | 213 #ifdef USE_NAS_AUDIO |
214 if ((sound_options & OPT_SOUND_NAS)) { | |
215 if (play_file_nas(filename)) | |
216 _exit(0); | |
217 } | |
218 #endif /* USE_NAS_AUDIO */ | |
219 | |
220 #ifdef USE_AO | |
221 file = afOpenFile(filename, "rb", NULL); | |
4561 | 222 if(file) { |
223 ao_device *device; | |
224 ao_sample_format format; | |
225 int in_fmt; | |
226 int bytes_per_frame; | |
4429 | 227 |
4561 | 228 format.rate = afGetRate(file, AF_DEFAULT_TRACK); |
229 format.channels = afGetChannels(file, AF_DEFAULT_TRACK); | |
230 afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt, | |
231 &format.bits); | |
232 | |
4878 | 233 /* XXX: libao doesn't seem to like 8-bit sounds, so we'll |
234 * let libaudiofile make them a bit better for us */ | |
235 if(format.bits == 8) | |
236 format.bits = 16; | |
237 | |
4561 | 238 afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, |
239 AF_SAMPFMT_TWOSCOMP, format.bits); | |
4429 | 240 |
4592 | 241 #if __BYTE_ORDER == __BIG_ENDIAN |
242 format.byte_format = AO_FMT_BIG; | |
243 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
244 AF_BYTEORDER_BIGENDIAN); | |
245 #elif __BYTE_ORDER == __LITTLE_ENDIAN | |
246 format.byte_format = AO_FMT_LITTLE; | |
247 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
248 AF_BYTEORDER_LITTLEENDIAN); | |
249 #endif | |
4561 | 250 |
251 bytes_per_frame = format.bits * format.channels / 8; | |
252 | |
253 device = ao_open_live(ao_driver, &format, NULL); | |
254 | |
255 if(device) { | |
256 int frames_read; | |
257 char buf[4096]; | |
258 int buf_frames = sizeof(buf) / bytes_per_frame; | |
259 | |
260 while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK, | |
261 buf, buf_frames))) { | |
262 if(!ao_play(device, buf, frames_read * bytes_per_frame)) | |
263 break; | |
264 } | |
265 ao_close(device); | |
266 } | |
267 afCloseFile(file); | |
4430 | 268 } |
4581 | 269 ao_shutdown(); |
270 #endif /* USE_AO */ | |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
271 _exit(0); |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
272 } |
4581 | 273 #else /* USE_NAS_AUDIO || USE_AO */ |
4561 | 274 gdk_beep(); |
275 return; | |
4581 | 276 #endif /* USE_NAS_AUDIO || USE_AO */ |
3630 | 277 #else /* _WIN32 */ |
278 debug_printf("Playing %s\n", filename); | |
279 if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME)) | |
280 debug_printf("Error playing sound."); | |
4561 | 281 #endif /* _WIN32 */ |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
282 } |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
283 |
4561 | 284 void gaim_sound_play_event(GaimSoundEventID event) |
1 | 285 { |
4561 | 286 if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds) |
3060 | 287 return; |
288 | |
4561 | 289 if (event >= GAIM_NUM_SOUNDS) { |
290 debug_printf("got request for unknown sound: %d\n", event); | |
3060 | 291 return; |
292 } | |
293 | |
294 /* check NULL for sounds that don't have an option, ie buddy pounce */ | |
4561 | 295 if ((sound_options & sounds[event].opt) || (sounds[event].opt == 0)) { |
296 if (sound_file[event]) { | |
297 gaim_sound_play_file(sound_file[event]); | |
3060 | 298 } else { |
4004 | 299 gchar *filename = NULL; |
300 | |
4561 | 301 filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL); |
302 gaim_sound_play_file(filename); | |
4004 | 303 g_free(filename); |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
304 } |
1252
46c09828e929
[gaim-migrate @ 1262]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1235
diff
changeset
|
305 } |
64 | 306 } |
4561 | 307 |
308 void gaim_sound_set_mute(gboolean mute) | |
309 { | |
310 mute_sounds = mute; | |
311 } | |
312 | |
313 gboolean gaim_sound_get_mute() | |
314 { | |
315 return mute_sounds; | |
316 } | |
317 | |
318 void gaim_sound_set_login_mute(gboolean mute) | |
319 { | |
320 mute_login_sounds = mute; | |
321 } | |
322 | |
323 void gaim_sound_set_event_file(GaimSoundEventID event, const char *filename) | |
324 { | |
325 if(event >= GAIM_NUM_SOUNDS) | |
326 return; | |
327 | |
328 if(sound_file[event]) | |
329 g_free(sound_file[event]); | |
330 | |
331 sound_file[event] = g_strdup(filename); | |
332 } | |
333 | |
334 | |
335 char *gaim_sound_get_event_file(GaimSoundEventID event) | |
336 { | |
337 if(event >= GAIM_NUM_SOUNDS) | |
338 return NULL; | |
339 | |
340 return sound_file[event]; | |
341 } | |
342 | |
343 guint gaim_sound_get_event_option(GaimSoundEventID event) | |
344 { | |
345 if(event >= GAIM_NUM_SOUNDS) | |
346 return 0; | |
347 | |
348 return sounds[event].opt; | |
349 } | |
350 | |
351 char *gaim_sound_get_event_label(GaimSoundEventID event) | |
352 { | |
353 if(event >= GAIM_NUM_SOUNDS) | |
354 return NULL; | |
355 | |
356 return sounds[event].label; | |
357 } | |
358 | |
359 | |
360 void gaim_sound_set_command(const char *cmd) | |
361 { | |
362 if(sound_cmd) | |
363 g_free(sound_cmd); | |
364 if(strlen(cmd) > 0) | |
365 sound_cmd = g_strdup(cmd); | |
366 else | |
367 sound_cmd = NULL; | |
368 } | |
369 | |
370 char *gaim_sound_get_command() | |
371 { | |
372 return sound_cmd; | |
373 } | |
374 |