Mercurial > pidgin.yaz
annotate src/sound.c @ 4561:9df99116840a
[gaim-migrate @ 4842]
This is the new sound subsystem
Lots of stuff got renamed, and everything sound-wise is documented.
Gaim now uses libaudiofile and libao to play sounds. Lots of ugly hacks
were removed, and now we support playing audio through anything that
libao will support.
If you need to (you shouldn't) you can force libao to use a specific
output driver, by putting a line into ~/.libao like:
default_driver=esd
You shouldn't need to do this, libao is pretty good at figuring out what
driver to use.
committer: Tailor Script <tailor@pidgin.im>
author | Nathan Walp <nwalp@pidgin.im> |
---|---|
date | Sun, 09 Feb 2003 01:55:35 +0000 |
parents | 3196d9044a45 |
children | 2c8372d4fb2a |
rev | line source |
---|---|
1 | 1 /* |
2 * gaim | |
3 * | |
4561 | 4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> |
1 | 5 * |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 | |
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
338
diff
changeset
|
22 #ifdef HAVE_CONFIG_H |
2090
b66aca8e8dce
[gaim-migrate @ 2100]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2048
diff
changeset
|
23 #include <config.h> |
349
b402a23f35df
[gaim-migrate @ 359]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
338
diff
changeset
|
24 #endif |
1 | 25 #include <stdio.h> |
1057
d50d3abb9eb7
[gaim-migrate @ 1067]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1006
diff
changeset
|
26 #include <stdlib.h> |
1 | 27 #include <string.h> |
3630 | 28 |
29 #ifndef _WIN32 | |
1 | 30 #include <sys/time.h> |
31 #include <unistd.h> | |
32 #include <sys/wait.h> | |
63 | 33 #include <unistd.h> |
3630 | 34 #else |
35 #include <windows.h> | |
36 #include <mmsystem.h> | |
37 #endif | |
38 | |
39 #include <fcntl.h> | |
63 | 40 #include <sys/types.h> |
41 #include <sys/stat.h> | |
1 | 42 |
4561 | 43 #ifdef USE_AO |
44 #include <ao/ao.h> | |
45 #include <audiofile.h> | |
46 #endif /* USE_AO */ | |
4012 | 47 |
1 | 48 #include "gaim.h" |
4561 | 49 #include "sound.h" |
1 | 50 |
4019
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
51 #ifdef _WIN32 |
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
52 #include "win32dep.h" |
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
53 #endif |
e53d9f9969d0
[gaim-migrate @ 4219]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
4014
diff
changeset
|
54 |
4561 | 55 struct gaim_sound_event { |
56 char *label; | |
57 guint opt; | |
58 char *def; | |
59 }; | |
60 | |
61 #ifdef USE_AO | |
62 static int ao_driver; | |
63 #endif /* USE_AO */ | |
64 | |
65 | |
66 static gboolean mute_login_sounds = FALSE; | |
67 static gboolean mute_sounds = FALSE; | |
68 static char *sound_cmd = NULL; | |
3319 | 69 |
4082 | 70 /* description, option bit, default sound file * |
71 * set the option bit to 0 to have it not display in prefs * | |
72 * the order here has to match the defines in gaim.h. * | |
73 * -Robot101 */ | |
4561 | 74 static struct gaim_sound_event sounds[GAIM_NUM_SOUNDS] = { |
4013 | 75 {N_("Buddy logs in"), OPT_SOUND_LOGIN, "arrive.wav"}, |
76 {N_("Buddy logs out"), OPT_SOUND_LOGOUT, "leave.wav"}, | |
4012 | 77 {N_("Message received"), OPT_SOUND_RECV, "receive.wav"}, |
78 {N_("Message received begins conversation"), OPT_SOUND_FIRST_RCV, "receive.wav"}, | |
79 {N_("Message sent"), OPT_SOUND_SEND, "send.wav"}, | |
4013 | 80 {N_("Person enters chat"), OPT_SOUND_CHAT_JOIN, "arrive.wav"}, |
81 {N_("Person leaves chat"), OPT_SOUND_CHAT_PART, "leave.wav"}, | |
4012 | 82 {N_("You talk in chat"), OPT_SOUND_CHAT_YOU_SAY, "send.wav"}, |
83 {N_("Others talk in chat"), OPT_SOUND_CHAT_SAY, "receive.wav"}, | |
3326 | 84 /* this isn't a terminator, it's the buddy pounce default sound event ;-) */ |
4012 | 85 {NULL, 0, "redalert.wav"}, |
86 {N_("Someone says your name in chat"), OPT_SOUND_CHAT_NICK, "redalert.wav"} | |
3060 | 87 }; |
88 | |
4561 | 89 static char *sound_file[GAIM_NUM_SOUNDS]; |
4430 | 90 |
4561 | 91 void gaim_sound_init() |
4430 | 92 { |
4561 | 93 #ifdef USE_AO |
4430 | 94 |
4561 | 95 ao_initialize(); |
96 ao_driver = ao_default_driver_id(); | |
4430 | 97 |
4561 | 98 if(ao_driver == -1) { |
99 do_error_dialog(_("Sound Driver Not Found"), | |
100 _("Gaim was unable to load a sound driver. Sound files will " | |
101 "not be played."), GAIM_ERROR); | |
102 } else { | |
103 ao_info *info = ao_driver_info(ao_driver); | |
104 debug_printf("Sound output driver loaded: %s\n", info->name); | |
4430 | 105 } |
106 | |
4561 | 107 #endif |
4430 | 108 } |
109 | |
4561 | 110 void gaim_sound_quit() |
4430 | 111 { |
4561 | 112 #ifdef USE_AO |
4430 | 113 |
4561 | 114 ao_shutdown(); |
4430 | 115 |
4561 | 116 #endif |
4430 | 117 } |
118 | |
4561 | 119 void gaim_sound_play_file(char *filename) |
4430 | 120 { |
4561 | 121 #ifdef USE_AO |
122 pid_t pid; | |
123 #endif /* USE_AO */ | |
4430 | 124 |
4561 | 125 if (mute_sounds) |
126 return; | |
4430 | 127 |
3901 | 128 if (awaymessage && !(sound_options & OPT_SOUND_WHEN_AWAY)) |
129 return; /* check here in case a buddy pounce plays a file while away */ | |
4561 | 130 |
3004 | 131 if (sound_options & OPT_SOUND_BEEP) { |
132 gdk_beep(); | |
133 return; | |
134 } | |
135 | |
4561 | 136 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { |
137 char *tmp = g_strdup_printf(_("Unable to play sound because the chosen filename (%s) does not exist."), filename); | |
138 do_error_dialog(tmp, NULL, GAIM_ERROR); | |
139 g_free(tmp); | |
140 return; | |
3060 | 141 } |
4561 | 142 |
4430 | 143 #ifndef _WIN32 |
4561 | 144 if ((sound_options & OPT_SOUND_CMD)) { |
145 char *command; | |
146 GError *error = NULL; | |
147 | |
148 if(!sound_cmd) { | |
149 do_error_dialog(_("Unable to play sound because the 'Command' sound method has been chosen, but no command has been set."), NULL, GAIM_ERROR); | |
150 return; | |
151 } | |
152 | |
153 command = g_strdup_printf(sound_cmd, filename); | |
154 | |
155 if(!g_spawn_command_line_async(command, &error)) { | |
156 char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message); | |
157 do_error_dialog(tmp, NULL, GAIM_ERROR); | |
158 g_free(tmp); | |
159 g_error_free(error); | |
160 } | |
161 | |
162 g_free(command); | |
163 return; | |
164 } | |
165 #ifdef USE_AO | |
166 | |
167 if(ao_driver == -1) { | |
168 /* do _something_ audible ;-) */ | |
169 gdk_beep(); | |
170 return; | |
171 } | |
172 | |
173 | |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
174 pid = fork(); |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
175 |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
176 if (pid < 0) |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
177 return; |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
178 else if (pid == 0) { |
4561 | 179 AFfilehandle file = afOpenFile(filename, "rb", NULL); |
180 if(file) { | |
181 ao_device *device; | |
182 ao_sample_format format; | |
183 int in_fmt; | |
184 int bytes_per_frame; | |
4429 | 185 |
4561 | 186 format.rate = afGetRate(file, AF_DEFAULT_TRACK); |
187 format.channels = afGetChannels(file, AF_DEFAULT_TRACK); | |
188 afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt, | |
189 &format.bits); | |
190 | |
191 afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, | |
192 AF_SAMPFMT_TWOSCOMP, format.bits); | |
4429 | 193 |
4561 | 194 if(afGetByteOrder(file, AF_DEFAULT_TRACK) == AF_BYTEORDER_BIGENDIAN) |
195 format.byte_format = AO_FMT_BIG; | |
196 else | |
197 format.byte_format = AO_FMT_LITTLE; | |
198 | |
199 bytes_per_frame = format.bits * format.channels / 8; | |
200 | |
201 device = ao_open_live(ao_driver, &format, NULL); | |
202 | |
203 if(device) { | |
204 int frames_read; | |
205 char buf[4096]; | |
206 int buf_frames = sizeof(buf) / bytes_per_frame; | |
207 | |
208 while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK, | |
209 buf, buf_frames))) { | |
210 if(!ao_play(device, buf, frames_read * bytes_per_frame)) | |
211 break; | |
212 } | |
213 ao_close(device); | |
214 } | |
215 afCloseFile(file); | |
4430 | 216 } |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
217 _exit(0); |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
218 } |
4561 | 219 #else /* USE_AO */ |
220 gdk_beep(); | |
221 return; | |
222 #endif /* USE_AO */ | |
3630 | 223 #else /* _WIN32 */ |
224 debug_printf("Playing %s\n", filename); | |
225 if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME)) | |
226 debug_printf("Error playing sound."); | |
4561 | 227 #endif /* _WIN32 */ |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
228 } |
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
229 |
4561 | 230 void gaim_sound_play_event(GaimSoundEventID event) |
1 | 231 { |
4561 | 232 if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds) |
3060 | 233 return; |
234 | |
4561 | 235 if (event >= GAIM_NUM_SOUNDS) { |
236 debug_printf("got request for unknown sound: %d\n", event); | |
3060 | 237 return; |
238 } | |
239 | |
240 /* check NULL for sounds that don't have an option, ie buddy pounce */ | |
4561 | 241 if ((sound_options & sounds[event].opt) || (sounds[event].opt == 0)) { |
242 if (sound_file[event]) { | |
243 gaim_sound_play_file(sound_file[event]); | |
3060 | 244 } else { |
4004 | 245 gchar *filename = NULL; |
246 | |
4561 | 247 filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL); |
248 gaim_sound_play_file(filename); | |
4004 | 249 g_free(filename); |
1006
0a4d0ed65e17
[gaim-migrate @ 1016]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
899
diff
changeset
|
250 } |
1252
46c09828e929
[gaim-migrate @ 1262]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1235
diff
changeset
|
251 } |
64 | 252 } |
4561 | 253 |
254 void gaim_sound_set_mute(gboolean mute) | |
255 { | |
256 mute_sounds = mute; | |
257 } | |
258 | |
259 gboolean gaim_sound_get_mute() | |
260 { | |
261 return mute_sounds; | |
262 } | |
263 | |
264 void gaim_sound_set_login_mute(gboolean mute) | |
265 { | |
266 mute_login_sounds = mute; | |
267 } | |
268 | |
269 void gaim_sound_set_event_file(GaimSoundEventID event, const char *filename) | |
270 { | |
271 if(event >= GAIM_NUM_SOUNDS) | |
272 return; | |
273 | |
274 if(sound_file[event]) | |
275 g_free(sound_file[event]); | |
276 | |
277 sound_file[event] = g_strdup(filename); | |
278 } | |
279 | |
280 | |
281 char *gaim_sound_get_event_file(GaimSoundEventID event) | |
282 { | |
283 if(event >= GAIM_NUM_SOUNDS) | |
284 return NULL; | |
285 | |
286 return sound_file[event]; | |
287 } | |
288 | |
289 guint gaim_sound_get_event_option(GaimSoundEventID event) | |
290 { | |
291 if(event >= GAIM_NUM_SOUNDS) | |
292 return 0; | |
293 | |
294 return sounds[event].opt; | |
295 } | |
296 | |
297 char *gaim_sound_get_event_label(GaimSoundEventID event) | |
298 { | |
299 if(event >= GAIM_NUM_SOUNDS) | |
300 return NULL; | |
301 | |
302 return sounds[event].label; | |
303 } | |
304 | |
305 | |
306 void gaim_sound_set_command(const char *cmd) | |
307 { | |
308 if(sound_cmd) | |
309 g_free(sound_cmd); | |
310 if(strlen(cmd) > 0) | |
311 sound_cmd = g_strdup(cmd); | |
312 else | |
313 sound_cmd = NULL; | |
314 } | |
315 | |
316 char *gaim_sound_get_command() | |
317 { | |
318 return sound_cmd; | |
319 } | |
320 |