Wed, 19 Apr 2000 02:04:30 +0000
[gaim-migrate @ 143]
Let's see if I can remember everything I did:
- Fixed a bug I let slip. If you choose the new option to not play
login sounds when you log in, and then quit before the timeout is
up, it would save that you didn't want login sounds at all.
- Added two new plugin events: event_away and event_buddy_away.
- Made GtkWidget *imaway in away.c and void play(uchar *, int) in
sound.c not static any more (though not referenced in gaim.h).
This is so plugins can use those (and not have to worry about
writing their own sound code).
- Wrote a quick plugin to auto-iconify windows when you go away. I
had just been locally patching my own copy, since I figured it wasn't
worth including as an option. It also demonstrates some of the issues
of deciding between USE_APPLET and not. Perhaps plugins are the way
to go with some things that would otherwise have been options (for
example, the Lag-O-Meter is one of those things that could possibly
have been a plugin instead of hard-coded in).
I think that's everything.
| 1 | 1 | /* |
| 2 | * gaim | |
| 3 | * | |
| 4 | * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> | |
| 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 | ||
| 22 | #include <stdio.h> | |
| 23 | #include <string.h> | |
| 24 | #include <sys/time.h> | |
| 25 | #include <unistd.h> | |
| 26 | #include <gtk/gtk.h> | |
| 27 | #include <fcntl.h> | |
| 28 | #include <sys/wait.h> | |
| 29 | #include <sys/signal.h> | |
| 63 | 30 | #include <unistd.h> |
| 31 | #include <sys/types.h> | |
| 32 | #include <sys/stat.h> | |
| 1 | 33 | |
| 34 | #ifdef ESD_SOUND | |
| 35 | #include <esd.h> | |
| 36 | #endif | |
| 37 | ||
| 38 | #ifdef NAS_SOUND | |
| 39 | #include <audio/audiolib.h> | |
| 40 | #endif | |
| 41 | ||
| 42 | #include "gaim.h" | |
| 43 | #include "sounds/BuddyArrive.h" | |
| 44 | #include "sounds/BuddyLeave.h" | |
| 45 | #include "sounds/Send.h" | |
| 46 | #include "sounds/Receive.h" | |
| 47 | ||
| 48 | ||
| 49 | static void play_audio(char *data, int size) | |
| 50 | { | |
| 51 | int fd; | |
| 52 | ||
| 53 | fd = open("/dev/audio", O_WRONLY | O_EXCL); | |
| 54 | if (fd < 0) | |
| 55 | return; | |
| 56 | write(fd, data, size); | |
| 57 | close(fd); | |
| 58 | } | |
| 59 | ||
| 60 | static int can_play_audio() | |
| 61 | { | |
| 79 | 62 | struct stat stat_buf; |
| 63 | 63 | uid_t user = getuid(); |
| 64 | gid_t group = getgid(); | |
| 79 | 65 | if (stat("/dev/audio", &stat_buf)) |
| 63 | 66 | return 0; |
| 79 | 67 | if (user == stat_buf.st_uid && stat_buf.st_mode & S_IWUSR) |
| 63 | 68 | return 1; |
| 79 | 69 | if (group == stat_buf.st_gid && stat_buf.st_mode & S_IWGRP) |
| 63 | 70 | return 1; |
| 79 | 71 | if (stat_buf.st_mode & S_IWOTH) |
| 63 | 72 | return 1; |
| 73 | return 0; | |
| 1 | 74 | } |
| 75 | ||
| 76 | ||
| 77 | #ifdef ESD_SOUND | |
| 78 | /* | |
| 79 | ** This routine converts from ulaw to 16 bit linear. | |
| 80 | ** | |
| 81 | ** Craig Reese: IDA/Supercomputing Research Center | |
| 82 | ** 29 September 1989 | |
| 83 | ** | |
| 84 | ** References: | |
| 85 | ** 1) CCITT Recommendation G.711 (very difficult to follow) | |
| 86 | ** 2) MIL-STD-188-113,"Interoperability and Performance Standards | |
| 87 | ** for Analog-to_Digital Conversion Techniques," | |
| 88 | ** 17 February 1987 | |
| 89 | ** | |
| 90 | ** Input: 8 bit ulaw sample | |
| 91 | ** Output: signed 16 bit linear sample | |
| 92 | ** Z-note -- this is from libaudiofile. Thanks guys! | |
| 93 | */ | |
| 94 | ||
| 95 | int _af_ulaw2linear (unsigned char ulawbyte) | |
| 96 | { | |
| 97 | static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764}; | |
| 98 | int sign, exponent, mantissa, sample; | |
| 99 | ||
| 100 | ulawbyte = ~ulawbyte; | |
| 101 | sign = (ulawbyte & 0x80); | |
| 102 | exponent = (ulawbyte >> 4) & 0x07; | |
| 103 | mantissa = ulawbyte & 0x0F; | |
| 104 | sample = exp_lut[exponent] + (mantissa << (exponent + 3)); | |
| 105 | if (sign != 0) sample = -sample; | |
| 106 | ||
| 107 | return(sample); | |
| 108 | } | |
| 109 | ||
| 110 | ||
| 111 | ||
| 112 | static int play_esd(unsigned char *data, int size) | |
| 113 | { | |
| 114 | int fd, i; | |
| 115 | esd_format_t format = ESD_BITS16 | ESD_STREAM | ESD_PLAY | ESD_MONO; | |
| 79 | 116 | guint16 *lineardata; |
| 1 | 117 | |
| 118 | ||
| 119 | fd = esd_play_stream(format, 8012, NULL, "gaim"); | |
| 120 | ||
| 79 | 121 | if (fd < 0) { |
| 1 | 122 | return 0; |
| 79 | 123 | } |
| 124 | ||
| 125 | lineardata = g_malloc(size * 2); | |
| 1 | 126 | |
| 127 | for (i=0; i<size; i++) | |
| 128 | lineardata[i] = _af_ulaw2linear(data[i]); | |
| 129 | ||
| 130 | write(fd, lineardata, size * 2); | |
| 131 | ||
| 132 | close(fd); | |
| 133 | g_free(lineardata); | |
| 134 | ||
| 135 | return 1; | |
| 136 | ||
| 137 | } | |
| 138 | ||
| 139 | static int can_play_esd() | |
| 140 | { | |
| 141 | return 1; | |
| 142 | } | |
| 143 | ||
| 144 | #endif | |
| 145 | ||
| 146 | #ifdef NAS_SOUND | |
| 147 | ||
| 148 | char nas_server[] = "localhost"; | |
| 149 | AuServer *nas_serv = NULL; | |
| 150 | ||
| 151 | static AuBool | |
| 152 | NasEventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler) | |
| 153 | { | |
| 154 | AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev; | |
| 155 | ||
| 156 | if (ev->type == AuEventTypeElementNotify) { | |
| 157 | switch (event->kind) { | |
| 158 | case AuElementNotifyKindState: | |
| 159 | switch (event->cur_state) { | |
| 160 | case AuStateStop: | |
| 161 | _exit(0); | |
| 162 | } | |
| 163 | break; | |
| 164 | } | |
| 165 | } | |
| 166 | return AuTrue; | |
| 167 | } | |
| 168 | ||
| 169 | ||
| 170 | static int play_nas(unsigned char *data, int size) | |
| 171 | { | |
| 172 | AuDeviceID device = AuNone; | |
| 173 | AuFlowID flow; | |
| 174 | AuElement elements[3]; | |
| 175 | int i, n, w; | |
| 176 | ||
| 177 | /* look for an output device */ | |
| 178 | for (i = 0; i < AuServerNumDevices(nas_serv); i++) { | |
| 179 | if ((AuDeviceKind(AuServerDevice(nas_serv, i)) == | |
| 180 | AuComponentKindPhysicalOutput) && | |
| 181 | AuDeviceNumTracks(AuServerDevice(nas_serv, i)) == 1) { | |
| 182 | device = AuDeviceIdentifier(AuServerDevice(nas_serv, i)); | |
| 183 | break; | |
| 184 | } | |
| 185 | } | |
| 186 | ||
| 187 | if (device == AuNone) | |
| 188 | return 0; | |
| 189 | ||
| 190 | if (!(flow = AuCreateFlow(nas_serv, NULL))) | |
| 191 | return 0; | |
| 192 | ||
| 193 | ||
| 194 | AuMakeElementImportClient(&elements[0], 8012, AuFormatULAW8, | |
| 195 | 1, AuTrue, size, size/2, 0, NULL); | |
| 196 | AuMakeElementExportDevice(&elements[1], 0, device, 8012, | |
| 197 | AuUnlimitedSamples, 0, NULL); | |
| 198 | AuSetElements(nas_serv, flow, AuTrue, 2, elements, NULL); | |
| 199 | ||
| 200 | AuStartFlow(nas_serv, flow, NULL); | |
| 201 | ||
| 202 | AuWriteElement(nas_serv, flow, 0, size, data, AuTrue, NULL); | |
| 203 | ||
| 204 | AuRegisterEventHandler(nas_serv, AuEventHandlerIDMask, 0, flow, | |
| 205 | NasEventHandler, NULL); | |
| 206 | ||
| 207 | while(1) { | |
| 208 | AuHandleEvents(nas_serv); | |
| 209 | } | |
| 210 | ||
| 211 | return 1; | |
| 212 | } | |
| 213 | ||
| 214 | static int can_play_nas() | |
| 215 | { | |
| 216 | if ((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) | |
| 217 | return 1; | |
| 218 | return 0; | |
| 219 | } | |
| 220 | ||
| 221 | #endif | |
| 222 | ||
|
133
418de720c20d
[gaim-migrate @ 143]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
108
diff
changeset
|
223 | void play(unsigned char *data, int size) |
| 1 | 224 | { |
| 225 | int pid; | |
| 226 | ||
| 227 | #ifdef _WIN32 | |
| 228 | return; | |
| 229 | #endif | |
| 230 | ||
| 231 | pid = fork(); | |
| 232 | ||
| 233 | if (pid < 0) | |
| 234 | return; | |
| 235 | else if (pid == 0) { | |
| 236 | #ifdef ESD_SOUND | |
| 237 | /* ESD is our player of choice. Are we OK to | |
| 238 | * go there? */ | |
| 239 | if (can_play_esd()) { | |
| 240 | if (play_esd(data, size)) | |
| 241 | _exit(0); | |
| 242 | } | |
| 243 | #endif | |
| 244 | ||
| 245 | #ifdef NAS_SOUND | |
| 246 | /* NAS is our second choice setup. */ | |
| 247 | if (can_play_nas()) { | |
| 248 | if (play_nas(data, size)) | |
| 249 | _exit(0); | |
| 250 | } | |
| 251 | #endif | |
| 252 | ||
| 253 | /* Lastly, we can try just plain old /dev/audio */ | |
| 254 | if (can_play_audio()) { | |
| 255 | play_audio(data, size); | |
| 256 | _exit(0); | |
| 257 | } | |
| 258 | } else { | |
| 259 | gtk_timeout_add(100, (GtkFunction)clean_pid, NULL); | |
| 260 | } | |
| 261 | } | |
| 262 | ||
|
133
418de720c20d
[gaim-migrate @ 143]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
108
diff
changeset
|
263 | extern int logins_not_muted; |
|
108
a44b2ce7d0dc
[gaim-migrate @ 118]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
82
diff
changeset
|
264 | #ifndef USE_APPLET |
| 1 | 265 | |
| 266 | void play_sound(int sound) | |
| 267 | { | |
| 268 | ||
| 269 | switch(sound) { | |
| 270 | case BUDDY_ARRIVE: | |
|
133
418de720c20d
[gaim-migrate @ 143]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
108
diff
changeset
|
271 | if ((sound_options & OPT_SOUND_LOGIN) && logins_not_muted) |
| 1 | 272 | play(BuddyArrive, sizeof(BuddyArrive)); |
| 273 | break; | |
| 274 | case BUDDY_LEAVE: | |
| 275 | if (sound_options & OPT_SOUND_LOGOUT) | |
| 276 | play(BuddyLeave, sizeof(BuddyLeave)); | |
| 277 | break; | |
| 278 | case SEND: | |
| 279 | if (sound_options & OPT_SOUND_SEND) | |
| 280 | play(Send, sizeof(Send)); | |
| 281 | break; | |
| 282 | case FIRST_RECEIVE: | |
| 283 | if (sound_options & OPT_SOUND_FIRST_RCV) | |
| 284 | play(Receive, sizeof(Receive)); | |
| 285 | break; | |
| 286 | case RECEIVE: | |
| 287 | if (sound_options & OPT_SOUND_RECV) | |
| 288 | play(Receive, sizeof(Receive)); | |
| 289 | break; | |
| 290 | case AWAY: | |
| 291 | if (sound_options & OPT_SOUND_WHEN_AWAY) | |
| 292 | play(Receive, sizeof(Receive)); | |
| 293 | break; | |
| 294 | } | |
|
64
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
295 | } |
| 1 | 296 | |
|
64
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
297 | #else /* USE_APPLET */ |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
298 | |
|
82
33bc54b6c16a
[gaim-migrate @ 92]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
79
diff
changeset
|
299 | #include <gnome.h> |
|
64
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
300 | void play_sound(int sound) |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
301 | { |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
302 | |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
303 | switch(sound) { |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
304 | case BUDDY_ARRIVE: |
|
133
418de720c20d
[gaim-migrate @ 143]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
108
diff
changeset
|
305 | if ((sound_options & OPT_SOUND_LOGIN) && logins_not_muted) |
|
64
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
306 | gnome_triggers_do("", "program", "gaim_applet", "login", NULL); |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
307 | break; |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
308 | case BUDDY_LEAVE: |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
309 | if (sound_options & OPT_SOUND_LOGOUT) |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
310 | gnome_triggers_do("", "program", "gaim_applet", "leave", NULL); |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
311 | break; |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
312 | case SEND: |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
313 | if (sound_options & OPT_SOUND_SEND) |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
314 | gnome_triggers_do("", "program", "gaim_applet", "send", NULL); |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
315 | break; |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
316 | case FIRST_RECEIVE: |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
317 | if (sound_options & OPT_SOUND_FIRST_RCV) |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
318 | gnome_triggers_do("", "program", "gaim_applet", "recv", NULL); |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
319 | break; |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
320 | case RECEIVE: |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
321 | if (sound_options & OPT_SOUND_RECV) |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
322 | gnome_triggers_do("", "program", "gaim_applet", "recv", NULL); |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
323 | break; |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
324 | case AWAY: |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
325 | if (sound_options & OPT_SOUND_WHEN_AWAY) |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
326 | gnome_triggers_do("", "program", "gaim_applet", "recv", NULL); |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
327 | break; |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
328 | } |
| 1 | 329 | } |
|
64
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
330 | |
|
cb32d6c8353c
[gaim-migrate @ 74]
Eric Warmenhoven <warmenhoven@yahoo.com>
parents:
63
diff
changeset
|
331 | #endif /* USE_APPLET */ |