Mercurial > pidgin.yaz
annotate src/gtksound.c @ 6840:b67670ac5584
[gaim-migrate @ 7385]
Tim Ringenbach (marv_sf) writes:
" This fixes the following bugs:
Deleting a buddy didn't make the prpl realize he was no
longer on the server list (until signoff/signon), so
adding his back yet failing didn't seem to fail.
Adding a buddy that was offline showed him as not on
server list until signoff/signon or he came online.
Adding a buddy to a 2nd group actually added him a 2nd
time to his first group on the server list (which isn't
allowed, so generated an error)
This also adds an error when adding to the server list
fails for any reason except already being on the list.
This also makes the error when a buddy rejects us a
little nicer looking."
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sun, 14 Sep 2003 21:21:32 +0000 |
parents | b8bc8dd411cc |
children | feb3d21a7794 |
rev | line source |
---|---|
5684 | 1 /* |
2 * gaim | |
3 * | |
4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
5 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
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 */ | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6199
diff
changeset
|
22 #include "gtkinternal.h" |
5684 | 23 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
24 #ifdef _WIN32 |
5684 | 25 #include <windows.h> |
26 #include <mmsystem.h> | |
27 #endif | |
28 | |
29 #ifdef USE_AO | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
30 # include <ao/ao.h> |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
31 # include <audiofile.h> |
5684 | 32 #endif /* USE_AO */ |
33 | |
34 #ifdef USE_NAS_AUDIO | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
35 # include <audio/audiolib.h> |
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
36 # include <audio/soundlib.h> |
5684 | 37 #endif /* USE_NAS_AUDIO */ |
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" |
5684 | 43 |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
44 #include "gtksound.h" |
5684 | 45 |
46 | |
47 struct gaim_sound_event { | |
48 char *label; | |
49 char *pref; | |
50 char *def; | |
51 }; | |
52 | |
53 | |
54 | |
55 static gboolean mute_login_sounds = FALSE; | |
56 static gboolean mute_sounds = FALSE; | |
6199 | 57 static gboolean sound_initialized = FALSE; |
5684 | 58 |
59 static struct gaim_sound_event sounds[GAIM_NUM_SOUNDS] = { | |
60 {N_("Buddy logs in"), "login", "arrive.wav"}, | |
61 {N_("Buddy logs out"), "logout", "leave.wav"}, | |
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"}, | |
65 {N_("Person enters chat"), "join_chat", "arrive.wav"}, | |
66 {N_("Person leaves chat"), "left_chat", "leave.wav"}, | |
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 ;-) */ | |
70 {NULL, "pounce_default", "redalert.wav"}, | |
71 {N_("Someone says your name in chat"), "nick_said", "redalert.wav"} | |
72 }; | |
73 | |
74 #ifdef USE_AO | |
75 static int ao_driver = -1; | |
76 #endif /* USE_AO */ | |
77 | |
5794
5e93fc46d1af
[gaim-migrate @ 6219]
Christian Hammond <chipx86@chipx86.com>
parents:
5684
diff
changeset
|
78 static void _pref_sound_method_changed(const char *name, GaimPrefType type, |
5684 | 79 gpointer val, gpointer data); |
80 | |
81 static void gaim_gtk_sound_init(void) | |
82 { | |
83 gaim_prefs_add_none("/gaim/gtk/sound"); | |
84 gaim_prefs_add_none("/gaim/gtk/sound/enabled"); | |
85 gaim_prefs_add_none("/gaim/gtk/sound/file"); | |
86 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/login", TRUE); | |
87 gaim_prefs_add_string("/gaim/gtk/sound/file/login", ""); | |
88 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/logout", TRUE); | |
89 gaim_prefs_add_string("/gaim/gtk/sound/file/logout", ""); | |
90 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/im_recv", TRUE); | |
91 gaim_prefs_add_string("/gaim/gtk/sound/file/im_recv", ""); | |
92 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/first_im_recv", FALSE); | |
93 gaim_prefs_add_string("/gaim/gtk/sound/file/first_im_recv", ""); | |
94 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/send_im", TRUE); | |
95 gaim_prefs_add_string("/gaim/gtk/sound/file/send_im", ""); | |
96 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/join_chat", FALSE); | |
97 gaim_prefs_add_string("/gaim/gtk/sound/file/join_chat", ""); | |
98 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/left_chat", FALSE); | |
99 gaim_prefs_add_string("/gaim/gtk/sound/file/left_chat", ""); | |
100 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/send_chat_msg", FALSE); | |
101 gaim_prefs_add_string("/gaim/gtk/sound/file/send_chat_msg", ""); | |
102 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/chat_msg_recv", FALSE); | |
103 gaim_prefs_add_string("/gaim/gtk/sound/file/chat_msg_recv", ""); | |
104 gaim_prefs_add_bool("/gaim/gtk/sound/enabled/nick_said", FALSE); | |
105 gaim_prefs_add_string("/gaim/gtk/sound/file/nick_said", ""); | |
106 gaim_prefs_add_bool("/gaim/gtk/sound/silent_signon", TRUE); | |
107 gaim_prefs_add_string("/gaim/gtk/sound/command", ""); | |
108 gaim_prefs_add_string("/gaim/gtk/sound/method", "automatic"); | |
109 | |
110 #ifdef USE_AO | |
111 gaim_debug(GAIM_DEBUG_INFO, "sound", | |
112 "Initializing sound output drivers.\n"); | |
113 ao_initialize(); | |
114 #endif /* USE_AO */ | |
115 | |
116 gaim_prefs_connect_callback("/gaim/gtk/sound/method", | |
5794
5e93fc46d1af
[gaim-migrate @ 6219]
Christian Hammond <chipx86@chipx86.com>
parents:
5684
diff
changeset
|
117 _pref_sound_method_changed, NULL); |
5684 | 118 } |
119 | |
120 | |
121 static void gaim_gtk_sound_shutdown(void) | |
122 { | |
123 #ifdef USE_AO | |
124 ao_shutdown(); | |
125 #endif | |
6199 | 126 sound_initialized = FALSE; |
5684 | 127 } |
128 | |
129 static void gaim_gtk_sound_play_file(const char *filename) | |
130 { | |
131 const char *method; | |
132 #if defined(USE_NAS_AUDIO) || defined(USE_AO) | |
133 pid_t pid; | |
134 #ifdef USE_AO | |
135 AFfilehandle file; | |
136 #endif | |
137 #endif | |
138 | |
6199 | 139 if (!sound_initialized) |
140 gaim_prefs_trigger_callback("/gaim/gtk/sound/method"); | |
141 | |
5684 | 142 if (mute_sounds) |
143 return; | |
144 | |
145 method = gaim_prefs_get_string("/gaim/gtk/sound/method"); | |
146 | |
147 if (!strcmp(method, "beep")) { | |
148 gdk_beep(); | |
149 return; | |
150 } | |
151 | |
152 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { | |
153 char *tmp = g_strdup_printf(_("Unable to play sound because the chosen file (%s) does not exist."), filename); | |
154 gaim_notify_error(NULL, NULL, tmp, NULL); | |
155 g_free(tmp); | |
156 return; | |
157 } | |
158 | |
159 #ifndef _WIN32 | |
160 if (!strcmp(method, "custom")) { | |
161 const char *sound_cmd; | |
162 char *command; | |
163 GError *error = NULL; | |
164 | |
165 sound_cmd = gaim_prefs_get_string("/gaim/gtk/sound/command"); | |
166 | |
167 if (!sound_cmd || *sound_cmd == '\0') { | |
168 gaim_notify_error(NULL, NULL, | |
169 _("Unable to play sound because the " | |
170 "'Command' sound method has been chosen, " | |
171 "but no command has been set."), NULL); | |
172 return; | |
173 } | |
174 | |
175 command = g_strdup_printf(sound_cmd, filename); | |
176 | |
177 if(!g_spawn_command_line_async(command, &error)) { | |
178 char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message); | |
179 gaim_notify_error(NULL, NULL, tmp, NULL); | |
180 g_free(tmp); | |
181 g_error_free(error); | |
182 } | |
183 | |
184 g_free(command); | |
185 return; | |
186 } | |
187 #if defined(USE_NAS_AUDIO) || defined(USE_AO) | |
188 pid = fork(); | |
189 if (pid < 0) | |
190 return; | |
191 else if (pid == 0) { | |
192 #ifdef USE_NAS_AUDIO | |
193 if (!strcmp(method, "nas")) { | |
194 if (play_file_nas(filename)) | |
195 _exit(0); | |
196 } | |
197 #endif /* USE_NAS_AUDIO */ | |
198 | |
199 #ifdef USE_AO | |
200 file = afOpenFile(filename, "rb", NULL); | |
201 if(file) { | |
202 ao_device *device; | |
203 ao_sample_format format; | |
204 int in_fmt; | |
205 int bytes_per_frame; | |
206 | |
207 format.rate = afGetRate(file, AF_DEFAULT_TRACK); | |
208 format.channels = afGetChannels(file, AF_DEFAULT_TRACK); | |
209 afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt, | |
210 &format.bits); | |
211 | |
212 /* XXX: libao doesn't seem to like 8-bit sounds, so we'll | |
213 * let libaudiofile make them a bit better for us */ | |
214 if(format.bits == 8) | |
215 format.bits = 16; | |
216 | |
217 afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, | |
218 AF_SAMPFMT_TWOSCOMP, format.bits); | |
219 | |
220 #if __BYTE_ORDER == __BIG_ENDIAN | |
221 format.byte_format = AO_FMT_BIG; | |
222 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
223 AF_BYTEORDER_BIGENDIAN); | |
224 #elif __BYTE_ORDER == __LITTLE_ENDIAN | |
225 format.byte_format = AO_FMT_LITTLE; | |
226 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
227 AF_BYTEORDER_LITTLEENDIAN); | |
228 #endif | |
229 | |
230 bytes_per_frame = format.bits * format.channels / 8; | |
231 | |
232 device = ao_open_live(ao_driver, &format, NULL); | |
233 | |
234 if(device) { | |
235 int frames_read; | |
236 char buf[4096]; | |
237 int buf_frames = sizeof(buf) / bytes_per_frame; | |
238 | |
239 while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK, | |
240 buf, buf_frames))) { | |
241 if(!ao_play(device, buf, frames_read * bytes_per_frame)) | |
242 break; | |
243 } | |
244 ao_close(device); | |
245 } | |
246 afCloseFile(file); | |
247 } | |
248 ao_shutdown(); | |
249 #endif /* USE_AO */ | |
250 _exit(0); | |
251 } | |
252 #else /* USE_NAS_AUDIO || USE_AO */ | |
253 gdk_beep(); | |
254 return; | |
255 #endif /* USE_NAS_AUDIO || USE_AO */ | |
256 #else /* _WIN32 */ | |
257 gaim_debug(GAIM_DEBUG_INFO, "sound", "Playing %s\n", filename); | |
258 | |
259 if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME)) | |
260 gaim_debug(GAIM_DEBUG_ERROR, "sound", "Error playing sound.\n"); | |
261 #endif /* _WIN32 */ | |
262 } | |
263 | |
264 static void gaim_gtk_sound_play_event(GaimSoundEventID event) | |
265 { | |
266 char *enable_pref; | |
267 char *file_pref; | |
268 | |
269 if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds) | |
270 return; | |
271 | |
272 if (event >= GAIM_NUM_SOUNDS) { | |
273 gaim_debug(GAIM_DEBUG_MISC, "sound", | |
274 "got request for unknown sound: %d\n", event); | |
275 return; | |
276 } | |
277 | |
278 enable_pref = g_strdup_printf("/gaim/gtk/sound/enabled/%s", | |
279 sounds[event].pref); | |
280 file_pref = g_strdup_printf("/gaim/gtk/sound/file/%s", sounds[event].pref); | |
281 | |
282 /* check NULL for sounds that don't have an option, ie buddy pounce */ | |
283 if (gaim_prefs_get_bool(enable_pref)) { | |
284 char *filename = g_strdup(gaim_prefs_get_string(file_pref)); | |
285 if(!filename || !strlen(filename)) { | |
286 if(filename) g_free(filename); | |
287 filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL); | |
288 } | |
289 | |
290 gaim_sound_play_file(filename); | |
291 g_free(filename); | |
292 } | |
293 | |
294 g_free(enable_pref); | |
295 g_free(file_pref); | |
296 } | |
297 | |
298 static GaimSoundUiOps sound_ui_ops = | |
299 { | |
300 gaim_gtk_sound_init, | |
301 gaim_gtk_sound_shutdown, | |
302 gaim_gtk_sound_play_file, | |
303 gaim_gtk_sound_play_event | |
304 }; | |
305 | |
306 GaimSoundUiOps *gaim_get_gtk_sound_ui_ops(void) | |
307 { | |
308 return &sound_ui_ops; | |
309 } | |
310 | |
311 | |
5794
5e93fc46d1af
[gaim-migrate @ 6219]
Christian Hammond <chipx86@chipx86.com>
parents:
5684
diff
changeset
|
312 static void _pref_sound_method_changed(const char *name, GaimPrefType type, |
5684 | 313 gpointer val, gpointer data) { |
6778 | 314 if(type != GAIM_PREF_STRING || strcmp(name, "/gaim/gtk/sound/method")) |
315 return; | |
316 | |
6199 | 317 sound_initialized = TRUE; |
318 | |
5684 | 319 #ifdef USE_AO |
320 ao_driver = -1; | |
321 | |
322 if(!strcmp(val, "esd")) | |
323 ao_driver = ao_driver_id("esd"); | |
324 else if(!strcmp(val, "arts")) | |
325 ao_driver = ao_driver_id("arts"); | |
326 else if(!strcmp(val, "automatic")) | |
327 ao_driver = ao_default_driver_id(); | |
328 | |
329 if(ao_driver != -1) { | |
330 ao_info *info = ao_driver_info(ao_driver); | |
331 gaim_debug(GAIM_DEBUG_INFO, "sound", | |
332 "Sound output driver loaded: %s\n", info->name); | |
333 } | |
334 #endif /* USE_AO */ | |
335 #ifdef USE_NAS | |
336 if (!strcmp(val, "nas")) | |
337 gaim_debug(GAIM_DEBUG_INFO, "sound", | |
338 "Sound output driver loaded: NAS output\n"); | |
339 #endif /* USE_NAS */ | |
340 } | |
341 | |
342 #ifdef USE_NAS_AUDIO | |
343 static gboolean play_file_nas(const char *filename) | |
344 { | |
345 AuServer *nas_serv; | |
346 gboolean ret = FALSE; | |
347 | |
348 if((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) { | |
349 ret = AuSoundPlaySynchronousFromFile(nas_serv, filename, 100); | |
350 AuCloseServer(nas_serv); | |
351 } | |
352 | |
353 return ret; | |
354 } | |
355 | |
356 #endif /* USE_NAS_AUDIO */ | |
357 | |
358 void gaim_gtk_sound_set_mute(gboolean mute) | |
359 { | |
360 mute_sounds = mute; | |
361 } | |
362 | |
363 gboolean gaim_gtk_sound_get_mute() | |
364 { | |
365 return mute_sounds; | |
366 } | |
367 | |
368 void gaim_gtk_sound_set_login_mute(gboolean mute) | |
369 { | |
370 mute_login_sounds = mute; | |
371 } | |
372 | |
373 const char *gaim_gtk_sound_get_event_option(GaimSoundEventID event) | |
374 { | |
375 if(event >= GAIM_NUM_SOUNDS) | |
376 return 0; | |
377 | |
378 return sounds[event].pref; | |
379 } | |
380 | |
381 char *gaim_gtk_sound_get_event_label(GaimSoundEventID event) | |
382 { | |
383 if(event >= GAIM_NUM_SOUNDS) | |
384 return NULL; | |
385 | |
386 return sounds[event].label; | |
387 } | |
388 |