Mercurial > pidgin.yaz
diff src/sound.c @ 1:2846a03bda67
[gaim-migrate @ 10]
The other missing files :)
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Thu, 23 Mar 2000 03:13:54 +0000 |
parents | |
children | 12894b62d206 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sound.c Thu Mar 23 03:13:54 2000 +0000 @@ -0,0 +1,281 @@ +/* + * gaim + * + * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <stdio.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> +#include <gtk/gtk.h> +#include <fcntl.h> +#include <sys/wait.h> +#include <sys/signal.h> + +#ifdef ESD_SOUND +#include <esd.h> +#endif + +#ifdef NAS_SOUND +#include <audio/audiolib.h> +#endif + +#include "gaim.h" +#include "sounds/BuddyArrive.h" +#include "sounds/BuddyLeave.h" +#include "sounds/Send.h" +#include "sounds/Receive.h" + + +static void play_audio(char *data, int size) +{ + int fd; + + fd = open("/dev/audio", O_WRONLY | O_EXCL); + if (fd < 0) + return; + write(fd, data, size); + close(fd); +} + +static int can_play_audio() +{ + /* FIXME check for write access and such. */ + return 1; + +} + + +#ifdef ESD_SOUND +/* +** This routine converts from ulaw to 16 bit linear. +** +** Craig Reese: IDA/Supercomputing Research Center +** 29 September 1989 +** +** References: +** 1) CCITT Recommendation G.711 (very difficult to follow) +** 2) MIL-STD-188-113,"Interoperability and Performance Standards +** for Analog-to_Digital Conversion Techniques," +** 17 February 1987 +** +** Input: 8 bit ulaw sample +** Output: signed 16 bit linear sample +** Z-note -- this is from libaudiofile. Thanks guys! +*/ + +int _af_ulaw2linear (unsigned char ulawbyte) +{ + static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764}; + int sign, exponent, mantissa, sample; + + ulawbyte = ~ulawbyte; + sign = (ulawbyte & 0x80); + exponent = (ulawbyte >> 4) & 0x07; + mantissa = ulawbyte & 0x0F; + sample = exp_lut[exponent] + (mantissa << (exponent + 3)); + if (sign != 0) sample = -sample; + + return(sample); +} + + + +static int play_esd(unsigned char *data, int size) +{ + int fd, i; + esd_format_t format = ESD_BITS16 | ESD_STREAM | ESD_PLAY | ESD_MONO; + guint16 *lineardata = g_malloc(size * 2); + + + fd = esd_play_stream(format, 8012, NULL, "gaim"); + + if (fd < 0) + return 0; + + for (i=0; i<size; i++) + lineardata[i] = _af_ulaw2linear(data[i]); + + write(fd, lineardata, size * 2); + + close(fd); + g_free(lineardata); + + return 1; + +} + +static int can_play_esd() +{ + return 1; +} + +#endif + +#ifdef NAS_SOUND + +char nas_server[] = "localhost"; +AuServer *nas_serv = NULL; + +static AuBool +NasEventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler) +{ + AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev; + + if (ev->type == AuEventTypeElementNotify) { + switch (event->kind) { + case AuElementNotifyKindState: + switch (event->cur_state) { + case AuStateStop: + _exit(0); + } + break; + } + } + return AuTrue; +} + + +static int play_nas(unsigned char *data, int size) +{ + AuDeviceID device = AuNone; + AuFlowID flow; + AuElement elements[3]; + int i, n, w; + + /* look for an output device */ + for (i = 0; i < AuServerNumDevices(nas_serv); i++) { + if ((AuDeviceKind(AuServerDevice(nas_serv, i)) == + AuComponentKindPhysicalOutput) && + AuDeviceNumTracks(AuServerDevice(nas_serv, i)) == 1) { + device = AuDeviceIdentifier(AuServerDevice(nas_serv, i)); + break; + } + } + + if (device == AuNone) + return 0; + + if (!(flow = AuCreateFlow(nas_serv, NULL))) + return 0; + + + AuMakeElementImportClient(&elements[0], 8012, AuFormatULAW8, + 1, AuTrue, size, size/2, 0, NULL); + AuMakeElementExportDevice(&elements[1], 0, device, 8012, + AuUnlimitedSamples, 0, NULL); + AuSetElements(nas_serv, flow, AuTrue, 2, elements, NULL); + + AuStartFlow(nas_serv, flow, NULL); + + AuWriteElement(nas_serv, flow, 0, size, data, AuTrue, NULL); + + AuRegisterEventHandler(nas_serv, AuEventHandlerIDMask, 0, flow, + NasEventHandler, NULL); + + while(1) { + AuHandleEvents(nas_serv); + } + + return 1; +} + +static int can_play_nas() +{ + if ((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) + return 1; + return 0; +} + +#endif + +static void play(unsigned char *data, int size) +{ + int pid; + +#ifdef _WIN32 + return; +#endif + + pid = fork(); + + if (pid < 0) + return; + else if (pid == 0) { +#ifdef ESD_SOUND + /* ESD is our player of choice. Are we OK to + * go there? */ + if (can_play_esd()) { + if (play_esd(data, size)) + _exit(0); + } +#endif + +#ifdef NAS_SOUND + /* NAS is our second choice setup. */ + if (can_play_nas()) { + if (play_nas(data, size)) + _exit(0); + } +#endif + + /* Lastly, we can try just plain old /dev/audio */ + if (can_play_audio()) { + play_audio(data, size); + _exit(0); + } + } else { + gtk_timeout_add(100, (GtkFunction)clean_pid, NULL); + } +} + + + +void play_sound(int sound) +{ + + switch(sound) { + case BUDDY_ARRIVE: + if (sound_options & OPT_SOUND_LOGIN) + play(BuddyArrive, sizeof(BuddyArrive)); + break; + case BUDDY_LEAVE: + if (sound_options & OPT_SOUND_LOGOUT) + play(BuddyLeave, sizeof(BuddyLeave)); + break; + case SEND: + if (sound_options & OPT_SOUND_SEND) + play(Send, sizeof(Send)); + break; + case FIRST_RECEIVE: + if (sound_options & OPT_SOUND_FIRST_RCV) + play(Receive, sizeof(Receive)); + break; + case RECEIVE: + if (sound_options & OPT_SOUND_RECV) + play(Receive, sizeof(Receive)); + break; + case AWAY: + if (sound_options & OPT_SOUND_WHEN_AWAY) + play(Receive, sizeof(Receive)); + break; + } + + +}