Yattm - unified GTK instant-messaging client logo
   [Generated for version 0.2-17 - Mon Jan 6 19:01:23 GMT+1 2003]

Home - Main Page - Data Structures - File List - Data Fields - Globals

sound.c File Reference

#include "intl.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <sys/wait.h>
#include <sys/signal.h>
#include "globals.h"
#include "util.h"
#include "dialog.h"
#include "sound.h"
#include "prefs.h"

Include dependency graph for sound.c:

Include dependency graph

Go to the source code of this file.

Defines

#define ZEROTRAP
#define BIAS   0x84
#define CLIP   32635

Functions

int play_audio (gchar *soundfile)
int can_play_audio ()
unsigned char linear2ulaw (int sample)
int _af_ulaw2linear (unsigned char ulawbyte)
int can_play_esd ()
int play_esd_file (gchar *soundfile)
int can_play_arts ()
void arts_shutdown ()
int play_arts_file (gchar *soundfile)
char * auscale (char *infile, char *outfile, float scaling)
gboolean file_ok (gchar *soundfile)
void playsoundfile (gchar *soundfile)
void play_sound (int sound)
void sound_init ()
void sound_shutdown ()

Variables

int(* play_soundfile )(gchar *soundfile)
void(* shutdown_sounddrv )()


Define Documentation

#define BIAS   0x84
 

Definition at line 142 of file sound.c.

Referenced by linear2ulaw().

#define CLIP   32635
 

Definition at line 143 of file sound.c.

Referenced by linear2ulaw().

#define ZEROTRAP
 

Definition at line 141 of file sound.c.


Function Documentation

int _af_ulaw2linear unsigned char    ulawbyte
 

Definition at line 223 of file sound.c.

Referenced by auscale().

00224 {
00225   static int exp_lut[8] = {0,132,396,924,1980,4092,8316,16764};
00226   int sign, exponent, mantissa, sample;
00227 
00228   ulawbyte = ~ulawbyte;
00229   sign = (ulawbyte & 0x80);
00230   exponent = (ulawbyte >> 4) & 0x07;
00231   mantissa = ulawbyte & 0x0F;
00232   sample = exp_lut[exponent] + (mantissa << (exponent + 3));
00233   if (sign != 0) sample = -sample;
00234   {
00235     return(sample);
00236   }
00237 }

void arts_shutdown   [static]
 

Definition at line 401 of file sound.c.

Referenced by sound_init().

00402 {
00403 }

char* auscale char *    infile,
char *    outfile,
float    scaling
 

Definition at line 411 of file sound.c.

References _af_ulaw2linear(), DBG_CORE, eb_debug, and linear2ulaw().

Referenced by playsoundfile().

00412 {
00413 #ifndef __MINGW32__
00414     FILE *fd_in, *fd_out; 
00415     int bytes_read, x;
00416     guint32 header_size;
00417     size_t io_bytes;
00418   
00419     typedef struct
00420     {
00421     /* NOTE: THE GUINT32 VALUES BELOW ARE IN THE FILE AS BIG-ENDIAN
00422      * FORMAT !!!! */
00423     guchar  magic[4];  /* magic number '.snd' */
00424     guint32 dataloc;    /* offset to start of data */
00425     guint32 datasize;   /* num bytes of data */
00426     guint32 dataformat; /* data format code */
00427     guint32 samplerate; /* sampling rate */
00428     guint32 channelcount; /* num of channels */
00429     guchar  info;         /* null terminated id string
00430                    * (variable length) */
00431     } SNDStruct;
00432 
00433     SNDStruct auheader; /* first 28 bytes of .au header */
00434     guchar buf,   buf2[256];
00435     guchar map[256]; /* 8-bit mapping */
00436 
00437     if (scaling == 0.0) return(infile);  /* save time */
00438 
00439     if ((fd_in = fopen(infile, "rb")) == NULL)
00440     {
00441     fprintf(stderr,"Failed opening infile %s, errno=%d\n",infile, errno);
00442     return(infile);
00443     }
00444     /* see if this is .au file, if not then get out */
00445     if ((io_bytes = fread((guchar *)&auheader, sizeof(guchar), sizeof(auheader), fd_in)) != 28)
00446     {
00447     fclose(fd_in);
00448     fprintf(stderr,"Auscale - header read failed\n");
00449     return(infile);
00450     }
00451     if (strncmp(auheader.magic,".snd",4))
00452     {
00453     eb_debug(DBG_CORE, "Not .au file,file type=%X%X%X%X\n",auheader.magic[0],auheader.magic[1],auheader.magic[2],auheader.magic[3]);
00454     fclose(fd_in);
00455     return(infile);
00456     }
00457     x = GUINT32_FROM_BE(auheader.dataformat);
00458     if (x!=1) /* only want ulaw-8 format files */
00459     {
00460     eb_debug(DBG_CORE, "Not .au file,file type=%X%X%X%X\n",auheader.magic[0],auheader.magic[1],auheader.magic[2],auheader.magic[3]);
00461     fclose(fd_in);
00462     return(infile);
00463     }
00464     header_size= GUINT32_FROM_BE(auheader.dataloc); /* get offset to start of
00465                       * data */
00466     /* file is right type, reset to start */
00467     rewind(fd_in);
00468 
00469     if ((fd_out = fopen(outfile, "w+b")) == NULL)
00470     {
00471     fprintf(stderr,"Failed opening outfile %s, errno=%d\n",outfile,
00472         errno);
00473     fclose(fd_in);
00474     return(infile);
00475     }
00476 
00477     eb_debug(DBG_CORE, "Scaling = %f dB\n",scaling);
00478     scaling = pow(10.0,scaling/20.0);
00479 
00480         /* Build mapping */
00481     for (x=0; x<256 ; x++) map[x]=linear2ulaw(scaling*_af_ulaw2linear(x));
00482   
00483     /* Shift the .au header */
00484     /* copy the .au header */
00485     /* Note: There are unusual situations when the 'info' field is VERY
00486      * large and the start of data can therefore be larger than buf2.
00487      * The following 'while' statement takes care of that problem. */
00488     while(header_size >= (guint32)sizeof(buf2))
00489     {
00490     if ((io_bytes = fread(buf2, sizeof(guchar), sizeof(buf2), fd_in)) == sizeof(buf2))
00491     {
00492         if ((io_bytes = fwrite(buf2, sizeof(guchar), sizeof(buf2), fd_out)) !=
00493          sizeof(buf2))
00494         {
00495         eb_debug(DBG_CORE, "error copy au file");
00496         fclose(fd_out);
00497         fclose(fd_in);
00498         return (infile);
00499         }
00500     }
00501     else
00502     {
00503         eb_debug(DBG_CORE, "error copying au file");
00504         fclose(fd_in);
00505         fclose(fd_out);
00506         return (infile);
00507     }
00508     /* calc remaining amount of header */
00509     header_size -= (guint32)sizeof(buf2);
00510     }
00511     /* copy rest of header (or in most cases - all of it) */
00512     if ((io_bytes = fread(buf2, sizeof(guchar), header_size, fd_in)) ==
00513     header_size)
00514     {
00515     if ((io_bytes = fwrite(buf2, sizeof(guchar), header_size, fd_out))
00516         != header_size)
00517     {
00518         eb_debug(DBG_CORE, "error copying au file");
00519         fclose(fd_out);
00520         fclose(fd_in);
00521         return (infile);
00522     }
00523     }
00524     else
00525     {
00526     eb_debug(DBG_CORE, "error copying au file");
00527     fclose(fd_in);
00528     fclose(fd_out);
00529     return(infile);
00530     }
00531 
00532     /* Write the mapped data out */
00533     while((bytes_read = fread( &buf, sizeof(guchar), 1, fd_in)) > 0)
00534     {
00535     fwrite(map+buf, sizeof(guchar), 1, fd_out);
00536     }
00537     fclose(fd_in);
00538     fclose(fd_out);
00539 #endif
00540 
00541     return outfile;
00542 }

int can_play_arts   [static]
 

Definition at line 396 of file sound.c.

Referenced by sound_init().

00397 {
00398     return FALSE;
00399 }

int can_play_audio   [static]
 

Definition at line 112 of file sound.c.

Referenced by sound_init().

00113 {
00114         /* FIXME check for write access and such. */
00115     /* do not change from return 1 for WIN32 */
00116         return 1;
00117 
00118 }

int can_play_esd   [static]
 

Definition at line 268 of file sound.c.

Referenced by sound_init().

00269 {
00270     return FALSE;
00271 }

gboolean file_ok gchar *    soundfile
 

Definition at line 558 of file sound.c.

References do_error_dialog().

Referenced by playsoundfile().

00559 {
00560   gchar message[1024];
00561     
00562   if (access(soundfile, R_OK) == -1) /* use 'access' rather than
00563                       * 'stat', so we also get access
00564                       * results 
00565                       */
00566     {
00567       /* find and report the error */
00568       switch (errno)
00569     {
00570     case ENOENT:
00571       g_snprintf(message, 1024, "Sound file \'%s\', Not Found", soundfile);
00572       break;
00573       
00574     case EACCES:
00575       g_snprintf(message, 1024, "Sound file \'%s\', Access Not Allowed", soundfile);
00576       break;
00577       
00578     default:
00579       g_snprintf(message, 1024, "Error in opening sound file \'%s\', error code = %d", soundfile, errno);
00580       break;
00581     }
00582       
00583       do_error_dialog(message, "Yattm-WARNING");
00584       return FALSE;
00585     }
00586   return TRUE;
00587 }

unsigned char linear2ulaw int    sample
 

Definition at line 145 of file sound.c.

References BIAS, and CLIP.

Referenced by auscale().

00146 {
00147   static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
00148                              4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
00149                              5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00150                              5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
00151                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00152                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00153                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00154                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
00155                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00156                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00157                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00158                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00159                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00160                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00161                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
00162                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
00163   int sign, exponent, mantissa;
00164   unsigned char ulawbyte;
00165 
00166   /* Get the sample into sign-magnitude. */
00167   sign = (sample >> 8) & 0x80;      /* set aside the sign */
00168   if (sign != 0) sample = -sample;      /* get magnitude */
00169   if (sample > CLIP) sample = CLIP;     /* clip the magnitude */
00170 
00171   /* Convert from 16 bit linear to ulaw. */
00172   sample = sample + BIAS;
00173   exponent = exp_lut[(sample >> 7) & 0xFF];
00174   mantissa = (sample >> (exponent + 3)) & 0x0F;
00175   ulawbyte = ~(sign | (exponent << 4) | mantissa);
00176 #ifdef ZEROTRAP
00177   if (ulawbyte == 0) ulawbyte = 0x02;   /* optional CCITT trap */
00178 #endif
00179 
00180   return(ulawbyte);
00181 }

int play_arts_file gchar *    soundfile [static]
 

Definition at line 405 of file sound.c.

Referenced by sound_init().

00406 {
00407     return FALSE;
00408 }

int play_audio gchar *    soundfile [static]
 

Definition at line 75 of file sound.c.

References DBG_CORE, and eb_debug.

Referenced by sound_init().

00076 {
00077     int fd;
00078     struct stat info;   
00079     char * buf;
00080     char * audio_device;
00081     
00082     fd = open(soundfile,O_RDONLY);
00083     if (fd <= 0)
00084     {
00085         eb_debug(DBG_CORE, "Cannot open file %s\n", soundfile);
00086         return FALSE;
00087     }
00088     fstat(fd, &info);
00089     buf = alloca(info.st_size);
00090     read(fd,buf,24);
00091     read(fd,buf,info.st_size-24);
00092     close(fd);
00093     eb_debug(DBG_CORE, "File is %ld bytes\n", info.st_size);
00094 
00095     audio_device = getenv("AUDIODEV");
00096     if (audio_device == NULL) {
00097       /* OK, we're not running on a SunRay */
00098       audio_device = "/dev/audio";
00099     }
00100 
00101     eb_debug(DBG_CORE, "sending to %s\n", audio_device);
00102     
00103     fd = open(audio_device, O_WRONLY | O_EXCL);
00104     if (fd < 0)
00105         return FALSE;
00106     write(fd, buf, info.st_size-24);
00107     close(fd);
00108 
00109     return TRUE;
00110 }

int play_esd_file gchar *    soundfile [static]
 

Definition at line 273 of file sound.c.

Referenced by sound_init().

00274 {
00275     return FALSE;
00276 }

void play_sound int    sound
 

Definition at line 658 of file sound.c.

References BUDDY_ARRIVE, BUDDY_AWAY, BUDDY_LEAVE, cGetLocalPref(), FIRSTMSG, playsoundfile(), RECEIVE, and SEND.

Referenced by contact_login(), contact_logoff(), eb_chat_room_show_message(), eb_chat_window_display_remote_message(), and send_message().

00659 {
00660     if (do_no_sound_when_away && is_away)
00661         return;
00662     switch(sound) 
00663     {
00664         case BUDDY_AWAY:
00665         {
00666             playsoundfile(cGetLocalPref("BuddyAwayFilename"));
00667         }
00668         break;
00669         case BUDDY_ARRIVE:
00670         {
00671             playsoundfile(cGetLocalPref("BuddyArriveFilename"));
00672         }
00673         break;
00674         case BUDDY_LEAVE:
00675         {
00676             playsoundfile(cGetLocalPref("BuddyLeaveFilename"));
00677         }
00678         break;
00679         case SEND:
00680         {
00681             playsoundfile(cGetLocalPref("SendFilename"));
00682         }
00683         break;
00684         case RECEIVE:
00685         {
00686             playsoundfile(cGetLocalPref("ReceiveFilename"));
00687             break;
00688         }
00689         case FIRSTMSG:
00690         {
00691             playsoundfile(cGetLocalPref("FirstMsgFilename"));
00692             break;
00693         }
00694         default:
00695             return;
00696     }
00697 }

void playsoundfile gchar *    soundfile
 

Definition at line 590 of file sound.c.

References auscale(), fGetLocalPref(), file_ok(), and play_soundfile.

Referenced by do_trigger_action(), play_sound(), and testsoundfile().

00591 {
00592     
00593 #ifdef _WIN32
00594     if(!play_soundfile)
00595         return;
00596 
00597     if (!file_ok(soundfile)) 
00598         return;
00599 
00600     PlaySound(soundfile,NULL,SND_FILENAME|SND_SYNC);
00601     return;
00602 #endif
00603 #ifndef __MINGW32__
00604     gint pid;
00605 
00606     if(!play_soundfile)
00607         return;
00608 
00609     if (!file_ok(soundfile)) 
00610         return;
00611 
00612     pid = fork();
00613     if (pid < 0)
00614     {
00615         fprintf(stderr, "in playsoundfile(), fork failed!\n");
00616         return;
00617     }
00618     else if (pid == 0)
00619     {
00620         /* we're the child process, play the sound... */
00621         if(fGetLocalPref("SoundVolume") != 0.0)
00622         {
00623         gchar tmp_soundfile[9] = "ebXXXXXX";
00624             
00625             if (mkstemp(tmp_soundfile) == -1) /* create name for auscale */
00626             {
00627                 fprintf(stderr, "in playsoundfile(), mkstemp failed!\n");
00628                 return;
00629             }
00630 
00631             soundfile = auscale(soundfile,tmp_soundfile,fGetLocalPref("SoundVolume"));
00632 
00633             play_soundfile(soundfile);
00634 
00635             if (unlink(tmp_soundfile))
00636                fprintf(stderr,
00637                     "in playsoundfile(), unlink failed!\n");
00638         }
00639         else
00640         {
00641                 play_soundfile(soundfile);
00642         }
00643 
00644         _exit(0);
00645         
00646     }
00647     else
00648     {
00649         /* We're the parent process... */
00650         gtk_timeout_add(100, (GtkFunction)clean_pid, NULL);
00651     }
00652 #endif 
00653     
00654 }

void sound_init  
 

Definition at line 699 of file sound.c.

References arts_shutdown(), can_play_arts(), can_play_audio(), can_play_esd(), DBG_CORE, eb_debug, play_arts_file(), play_audio(), play_esd_file(), play_soundfile, and shutdown_sounddrv.

Referenced by main().

00700 {
00701     /* Determine which sound module will be used to play sounds */
00702 
00703 
00704     if(can_play_arts())
00705     {
00706         eb_debug(DBG_CORE,"Using arts sound\n");
00707         play_soundfile = play_arts_file;
00708         shutdown_sounddrv = arts_shutdown;
00709     }
00710     else if(can_play_esd())
00711     {
00712         eb_debug(DBG_CORE,"Using esd sound\n");
00713         play_soundfile = play_esd_file;
00714         shutdown_sounddrv = NULL;
00715     }
00716     /* handle sound direct to /dev/audio */
00717     else if (can_play_audio())
00718     {
00719         eb_debug(DBG_CORE,"Using raw audio\n");
00720         play_soundfile = play_audio;
00721         shutdown_sounddrv = NULL;
00722     }
00723     else
00724     {
00725        eb_debug(DBG_CORE,"Sound not available\n");
00726        play_soundfile = NULL;
00727        shutdown_sounddrv = NULL;
00728     }
00729 }

void sound_shutdown  
 

Definition at line 731 of file sound.c.

References shutdown_sounddrv.

Referenced by main().

00732 {
00733     if(shutdown_sounddrv != NULL) {
00734         shutdown_sounddrv();
00735     }
00736 }


Variable Documentation

int(* play_soundfile)(gchar *soundfile) [static]
 

Definition at line 72 of file sound.c.

Referenced by playsoundfile(), and sound_init().

void(* shutdown_sounddrv)() [static]
 

Definition at line 73 of file sound.c.

Referenced by sound_init(), and sound_shutdown().


Contact: Andy Maloney     [Documentation generated by doxygen]