Mercurial > pidgin
annotate src/sound.c @ 4622:56dde5f7d3a8
[gaim-migrate @ 4913]
Fixed the "Closing a chat crashes gaim" bug, I think.
There was a double-free going on with the chat topic and the user who set
the topic. The first did checks to see if it was NULL, and if not, freed
it. The second just freed it. The second should NOT have existed!
Probably explains why I could only duplicate it in channels with no
topic.
Let me know if this still crashes for anybody. It stopped crashing here.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Thu, 27 Feb 2003 10:05:05 +0000 |
parents | b69bbf9b1044 |
children | 77b04219f3e2 |
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 | |
233 afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, | |
234 AF_SAMPFMT_TWOSCOMP, format.bits); | |
4429 | 235 |
4592 | 236 #if __BYTE_ORDER == __BIG_ENDIAN |
237 format.byte_format = AO_FMT_BIG; | |
238 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
239 AF_BYTEORDER_BIGENDIAN); | |
240 #elif __BYTE_ORDER == __LITTLE_ENDIAN | |
241 format.byte_format = AO_FMT_LITTLE; | |
242 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
243 AF_BYTEORDER_LITTLEENDIAN); | |
244 #endif | |
4561 | 245 |
246 bytes_per_frame = format.bits * format.channels / 8; | |
247 | |
248 device = ao_open_live(ao_driver, &format, NULL); | |
249 | |
250 if(device) { | |
251 int frames_read; | |
252 char buf[4096]; | |
253 int buf_frames = sizeof(buf) / bytes_per_frame; | |
254 | |
255 while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK, | |
256 buf, buf_frames))) { | |
257 if(!ao_play(device, buf, frames_read * bytes_per_frame)) | |
258 break; | |
259 } | |
260 ao_close(device); | |
261 } | |
262 afCloseFile(file); | |
4430 | 263 } |
4581 | 264 ao_shutdown(); |
265 #endif /* USE_AO */ | |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
266 _exit(0); |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
267 } |
4581 | 268 #else /* USE_NAS_AUDIO || USE_AO */ |
4561 | 269 gdk_beep(); |
270 return; | |
4581 | 271 #endif /* USE_NAS_AUDIO || USE_AO */ |
3630 | 272 #else /* _WIN32 */ |
273 debug_printf("Playing %s\n", filename); | |
274 if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME)) | |
275 debug_printf("Error playing sound."); | |
4561 | 276 #endif /* _WIN32 */ |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
277 } |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
278 |
4561 | 279 void gaim_sound_play_event(GaimSoundEventID event) |
1 | 280 { |
4561 | 281 if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds) |
3060 | 282 return; |
283 | |
4561 | 284 if (event >= GAIM_NUM_SOUNDS) { |
285 debug_printf("got request for unknown sound: %d\n", event); | |
3060 | 286 return; |
287 } | |
288 | |
289 /* check NULL for sounds that don't have an option, ie buddy pounce */ | |
4561 | 290 if ((sound_options & sounds[event].opt) || (sounds[event].opt == 0)) { |
291 if (sound_file[event]) { | |
292 gaim_sound_play_file(sound_file[event]); | |
3060 | 293 } else { |
4004 | 294 gchar *filename = NULL; |
295 | |
4561 | 296 filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL); |
297 gaim_sound_play_file(filename); | |
4004 | 298 g_free(filename); |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
299 } |
1252
46c09828e929
[gaim-migrate @ 1262]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1235
diff
changeset
|
300 } |
64 | 301 } |
4561 | 302 |
303 void gaim_sound_set_mute(gboolean mute) | |
304 { | |
305 mute_sounds = mute; | |
306 } | |
307 | |
308 gboolean gaim_sound_get_mute() | |
309 { | |
310 return mute_sounds; | |
311 } | |
312 | |
313 void gaim_sound_set_login_mute(gboolean mute) | |
314 { | |
315 mute_login_sounds = mute; | |
316 } | |
317 | |
318 void gaim_sound_set_event_file(GaimSoundEventID event, const char *filename) | |
319 { | |
320 if(event >= GAIM_NUM_SOUNDS) | |
321 return; | |
322 | |
323 if(sound_file[event]) | |
324 g_free(sound_file[event]); | |
325 | |
326 sound_file[event] = g_strdup(filename); | |
327 } | |
328 | |
329 | |
330 char *gaim_sound_get_event_file(GaimSoundEventID event) | |
331 { | |
332 if(event >= GAIM_NUM_SOUNDS) | |
333 return NULL; | |
334 | |
335 return sound_file[event]; | |
336 } | |
337 | |
338 guint gaim_sound_get_event_option(GaimSoundEventID event) | |
339 { | |
340 if(event >= GAIM_NUM_SOUNDS) | |
341 return 0; | |
342 | |
343 return sounds[event].opt; | |
344 } | |
345 | |
346 char *gaim_sound_get_event_label(GaimSoundEventID event) | |
347 { | |
348 if(event >= GAIM_NUM_SOUNDS) | |
349 return NULL; | |
350 | |
351 return sounds[event].label; | |
352 } | |
353 | |
354 | |
355 void gaim_sound_set_command(const char *cmd) | |
356 { | |
357 if(sound_cmd) | |
358 g_free(sound_cmd); | |
359 if(strlen(cmd) > 0) | |
360 sound_cmd = g_strdup(cmd); | |
361 else | |
362 sound_cmd = NULL; | |
363 } | |
364 | |
365 char *gaim_sound_get_command() | |
366 { | |
367 return sound_cmd; | |
368 } | |
369 |