Mercurial > pidgin.yaz
annotate src/gtksound.c @ 6035:8c44020a958e
[gaim-migrate @ 6485]
gaim_request_input() now takes a masked bool, which, if enabled, masks the
text on the entry field so that it cannot be seen. Good for password input
requests, and what do you know, that's why this is written!
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Sat, 05 Jul 2003 21:54:19 +0000 |
parents | 059d95c67cda |
children | eb0fedc1ac09 |
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 */ | |
5872
059d95c67cda
[gaim-migrate @ 6304]
Christian Hammond <chipx86@chipx86.com>
parents:
5794
diff
changeset
|
22 #include "internal.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; | |
57 static char *sound_cmd = NULL; | |
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 gaim_prefs_trigger_callback("/gaim/gtk/sound/method"); |
119 } | |
120 | |
121 | |
122 static void gaim_gtk_sound_shutdown(void) | |
123 { | |
124 #ifdef USE_AO | |
125 ao_shutdown(); | |
126 #endif | |
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 | |
139 if (mute_sounds) | |
140 return; | |
141 | |
142 method = gaim_prefs_get_string("/gaim/gtk/sound/method"); | |
143 | |
144 if (!strcmp(method, "beep")) { | |
145 gdk_beep(); | |
146 return; | |
147 } | |
148 | |
149 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { | |
150 char *tmp = g_strdup_printf(_("Unable to play sound because the chosen file (%s) does not exist."), filename); | |
151 gaim_notify_error(NULL, NULL, tmp, NULL); | |
152 g_free(tmp); | |
153 return; | |
154 } | |
155 | |
156 #ifndef _WIN32 | |
157 if (!strcmp(method, "custom")) { | |
158 const char *sound_cmd; | |
159 char *command; | |
160 GError *error = NULL; | |
161 | |
162 sound_cmd = gaim_prefs_get_string("/gaim/gtk/sound/command"); | |
163 | |
164 if (!sound_cmd || *sound_cmd == '\0') { | |
165 gaim_notify_error(NULL, NULL, | |
166 _("Unable to play sound because the " | |
167 "'Command' sound method has been chosen, " | |
168 "but no command has been set."), NULL); | |
169 return; | |
170 } | |
171 | |
172 command = g_strdup_printf(sound_cmd, filename); | |
173 | |
174 if(!g_spawn_command_line_async(command, &error)) { | |
175 char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message); | |
176 gaim_notify_error(NULL, NULL, tmp, NULL); | |
177 g_free(tmp); | |
178 g_error_free(error); | |
179 } | |
180 | |
181 g_free(command); | |
182 return; | |
183 } | |
184 #if defined(USE_NAS_AUDIO) || defined(USE_AO) | |
185 pid = fork(); | |
186 if (pid < 0) | |
187 return; | |
188 else if (pid == 0) { | |
189 #ifdef USE_NAS_AUDIO | |
190 if (!strcmp(method, "nas")) { | |
191 if (play_file_nas(filename)) | |
192 _exit(0); | |
193 } | |
194 #endif /* USE_NAS_AUDIO */ | |
195 | |
196 #ifdef USE_AO | |
197 file = afOpenFile(filename, "rb", NULL); | |
198 if(file) { | |
199 ao_device *device; | |
200 ao_sample_format format; | |
201 int in_fmt; | |
202 int bytes_per_frame; | |
203 | |
204 format.rate = afGetRate(file, AF_DEFAULT_TRACK); | |
205 format.channels = afGetChannels(file, AF_DEFAULT_TRACK); | |
206 afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt, | |
207 &format.bits); | |
208 | |
209 /* XXX: libao doesn't seem to like 8-bit sounds, so we'll | |
210 * let libaudiofile make them a bit better for us */ | |
211 if(format.bits == 8) | |
212 format.bits = 16; | |
213 | |
214 afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, | |
215 AF_SAMPFMT_TWOSCOMP, format.bits); | |
216 | |
217 #if __BYTE_ORDER == __BIG_ENDIAN | |
218 format.byte_format = AO_FMT_BIG; | |
219 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
220 AF_BYTEORDER_BIGENDIAN); | |
221 #elif __BYTE_ORDER == __LITTLE_ENDIAN | |
222 format.byte_format = AO_FMT_LITTLE; | |
223 afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, | |
224 AF_BYTEORDER_LITTLEENDIAN); | |
225 #endif | |
226 | |
227 bytes_per_frame = format.bits * format.channels / 8; | |
228 | |
229 device = ao_open_live(ao_driver, &format, NULL); | |
230 | |
231 if(device) { | |
232 int frames_read; | |
233 char buf[4096]; | |
234 int buf_frames = sizeof(buf) / bytes_per_frame; | |
235 | |
236 while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK, | |
237 buf, buf_frames))) { | |
238 if(!ao_play(device, buf, frames_read * bytes_per_frame)) | |
239 break; | |
240 } | |
241 ao_close(device); | |
242 } | |
243 afCloseFile(file); | |
244 } | |
245 ao_shutdown(); | |
246 #endif /* USE_AO */ | |
247 _exit(0); | |
248 } | |
249 #else /* USE_NAS_AUDIO || USE_AO */ | |
250 gdk_beep(); | |
251 return; | |
252 #endif /* USE_NAS_AUDIO || USE_AO */ | |
253 #else /* _WIN32 */ | |
254 gaim_debug(GAIM_DEBUG_INFO, "sound", "Playing %s\n", filename); | |
255 | |
256 if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME)) | |
257 gaim_debug(GAIM_DEBUG_ERROR, "sound", "Error playing sound.\n"); | |
258 #endif /* _WIN32 */ | |
259 } | |
260 | |
261 static void gaim_gtk_sound_play_event(GaimSoundEventID event) | |
262 { | |
263 char *enable_pref; | |
264 char *file_pref; | |
265 | |
266 if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds) | |
267 return; | |
268 | |
269 if (event >= GAIM_NUM_SOUNDS) { | |
270 gaim_debug(GAIM_DEBUG_MISC, "sound", | |
271 "got request for unknown sound: %d\n", event); | |
272 return; | |
273 } | |
274 | |
275 enable_pref = g_strdup_printf("/gaim/gtk/sound/enabled/%s", | |
276 sounds[event].pref); | |
277 file_pref = g_strdup_printf("/gaim/gtk/sound/file/%s", sounds[event].pref); | |
278 | |
279 /* check NULL for sounds that don't have an option, ie buddy pounce */ | |
280 if (gaim_prefs_get_bool(enable_pref)) { | |
281 char *filename = g_strdup(gaim_prefs_get_string(file_pref)); | |
282 if(!filename || !strlen(filename)) { | |
283 if(filename) g_free(filename); | |
284 filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL); | |
285 } | |
286 | |
287 gaim_sound_play_file(filename); | |
288 g_free(filename); | |
289 } | |
290 | |
291 g_free(enable_pref); | |
292 g_free(file_pref); | |
293 } | |
294 | |
295 static GaimSoundUiOps sound_ui_ops = | |
296 { | |
297 gaim_gtk_sound_init, | |
298 gaim_gtk_sound_shutdown, | |
299 gaim_gtk_sound_play_file, | |
300 gaim_gtk_sound_play_event | |
301 }; | |
302 | |
303 GaimSoundUiOps *gaim_get_gtk_sound_ui_ops(void) | |
304 { | |
305 return &sound_ui_ops; | |
306 } | |
307 | |
308 | |
5794
5e93fc46d1af
[gaim-migrate @ 6219]
Christian Hammond <chipx86@chipx86.com>
parents:
5684
diff
changeset
|
309 static void _pref_sound_method_changed(const char *name, GaimPrefType type, |
5684 | 310 gpointer val, gpointer data) { |
311 if(type != GAIM_PREF_STRING || strcmp(name, "/gaim/gtk/sound/method")) | |
312 return; | |
313 #ifdef USE_AO | |
314 ao_driver = -1; | |
315 | |
316 if(!strcmp(val, "esd")) | |
317 ao_driver = ao_driver_id("esd"); | |
318 else if(!strcmp(val, "arts")) | |
319 ao_driver = ao_driver_id("arts"); | |
320 else if(!strcmp(val, "automatic")) | |
321 ao_driver = ao_default_driver_id(); | |
322 | |
323 if(ao_driver != -1) { | |
324 ao_info *info = ao_driver_info(ao_driver); | |
325 gaim_debug(GAIM_DEBUG_INFO, "sound", | |
326 "Sound output driver loaded: %s\n", info->name); | |
327 } | |
328 #endif /* USE_AO */ | |
329 #ifdef USE_NAS | |
330 if (!strcmp(val, "nas")) | |
331 gaim_debug(GAIM_DEBUG_INFO, "sound", | |
332 "Sound output driver loaded: NAS output\n"); | |
333 #endif /* USE_NAS */ | |
334 } | |
335 | |
336 #ifdef USE_NAS_AUDIO | |
337 static gboolean play_file_nas(const char *filename) | |
338 { | |
339 AuServer *nas_serv; | |
340 gboolean ret = FALSE; | |
341 | |
342 if((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) { | |
343 ret = AuSoundPlaySynchronousFromFile(nas_serv, filename, 100); | |
344 AuCloseServer(nas_serv); | |
345 } | |
346 | |
347 return ret; | |
348 } | |
349 | |
350 #endif /* USE_NAS_AUDIO */ | |
351 | |
352 void gaim_gtk_sound_set_mute(gboolean mute) | |
353 { | |
354 mute_sounds = mute; | |
355 } | |
356 | |
357 gboolean gaim_gtk_sound_get_mute() | |
358 { | |
359 return mute_sounds; | |
360 } | |
361 | |
362 void gaim_gtk_sound_set_login_mute(gboolean mute) | |
363 { | |
364 mute_login_sounds = mute; | |
365 } | |
366 | |
367 const char *gaim_gtk_sound_get_event_option(GaimSoundEventID event) | |
368 { | |
369 if(event >= GAIM_NUM_SOUNDS) | |
370 return 0; | |
371 | |
372 return sounds[event].pref; | |
373 } | |
374 | |
375 char *gaim_gtk_sound_get_event_label(GaimSoundEventID event) | |
376 { | |
377 if(event >= GAIM_NUM_SOUNDS) | |
378 return NULL; | |
379 | |
380 return sounds[event].label; | |
381 } | |
382 | |
383 | |
384 void gaim_sound_set_command(const char *cmd) | |
385 { | |
386 if(sound_cmd) | |
387 g_free(sound_cmd); | |
388 if(strlen(cmd) > 0) | |
389 sound_cmd = g_strdup(cmd); | |
390 else | |
391 sound_cmd = NULL; | |
392 } | |
393 | |
394 char *gaim_sound_get_command() | |
395 { | |
396 return sound_cmd; | |
397 } | |
398 |