00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifdef HAVE_CONFIG_H
00028 # include <config.h>
00029 #endif
00030
00031 #include "intl.h"
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <sys/time.h>
00036 #include <sys/stat.h>
00037 #include <fcntl.h>
00038 #include <errno.h>
00039 #include <math.h>
00040
00041 #ifdef __MINGW32__
00042 #include <windows.h>
00043 #else
00044 #include <sys/wait.h>
00045 #include <sys/signal.h>
00046 #endif
00047
00048 #include "globals.h"
00049 #include "util.h"
00050 #include "dialog.h"
00051 #include "sound.h"
00052 #include "prefs.h"
00053
00054 #ifdef ESD_SOUND
00055 #include <esd.h>
00056 #endif
00057
00058 #ifdef ARTS_SOUND
00059 #include <artsc.h>
00060 #include <audiofile.h>
00061 #define BUFFERED_FRAME_COUNT 20000
00062
00063
00064
00065
00066
00067
00068 #define ARTS_FREE_IS_BROKEN
00069
00070 #endif
00071
00072 static int (*play_soundfile)(gchar *soundfile);
00073 static void (*shutdown_sounddrv)();
00074
00075 static int play_audio(gchar *soundfile)
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
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 }
00111
00112 static int can_play_audio()
00113 {
00114
00115
00116 return 1;
00117
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #define ZEROTRAP
00142 #define BIAS 0x84
00143 #define CLIP 32635
00144
00145 unsigned char linear2ulaw(int sample)
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
00167 sign = (sample >> 8) & 0x80;
00168 if (sign != 0) sample = -sample;
00169 if (sample > CLIP) sample = CLIP;
00170
00171
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;
00178 #endif
00179
00180 return(ulawbyte);
00181 }
00182
00183 #if HAVE_LIBAUDIOFILE
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 int _af_ulaw2linear (unsigned char ulawbyte);
00204
00205 #else
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 int _af_ulaw2linear (unsigned char ulawbyte)
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 }
00238
00239 #endif
00240
00241 #ifdef ESD_SOUND
00242
00243 static int can_play_esd()
00244 {
00245 return TRUE;
00246 }
00247
00248 static int play_esd_file(gchar *soundfile)
00249 {
00250 int esd_stat;
00251 esd_stat = esd_play_file(NULL, soundfile, 1);
00252 if (!esd_stat)
00253 {
00254 if (errno == ENOENT)
00255 {
00256 eb_debug(DBG_CORE, "Yattm: File not found - file = \"%s\"\n", soundfile);
00257 }
00258 else
00259 {
00260 eb_debug(DBG_CORE, "Yattm: Esd play file failed with code %d\n", errno);
00261 }
00262 }
00263 return esd_stat;
00264 }
00265
00266 #else
00267
00268 static int can_play_esd()
00269 {
00270 return FALSE;
00271 }
00272
00273 static int play_esd_file(gchar *soundfile)
00274 {
00275 return FALSE;
00276 }
00277
00278 #endif
00279
00280
00281
00282 #ifdef ARTS_SOUND
00283
00284 static int test_arts()
00285 {
00286 int err;
00287 if ((err = arts_init()) != 0)
00288 {
00289 eb_debug(DBG_CORE, "WARNING (NO ERROR!):\ncan_play_arts(): arts_init() failed: %s\nIs artsd running?\n", arts_error_text( err ));
00290 return FALSE;
00291 }
00292 return TRUE;
00293 }
00294
00295 static int can_play_arts()
00296 {
00297
00298 #ifndef ARTS_FREE_IS_BROKEN
00299 return test_arts();
00300 #else
00301 pid_t childpid;
00302 int childstatus;
00303 int ret = -1;
00304
00305 childpid = fork();
00306
00307 if(childpid==0)
00308 {
00309
00310 exit(test_arts() ? 0 : 1);
00311 }
00312 else if(childpid==-1)
00313 {
00314 fprintf(stderr,"test_arts(): Failed at fork(), errno=%d\n", errno);
00315 return FALSE;
00316 }
00317 else
00318 {
00319 if( (ret=waitpid(-1, &childstatus, 0) == -1)) {
00320 fprintf(stderr,"test_arts(): Failed at wait(), errno=%d\n", errno);
00321 perror("waitpid");
00322 return FALSE;
00323 }
00324
00325 if( WEXITSTATUS(childstatus)==0 ) {
00326 return TRUE;
00327 }
00328 }
00329 return FALSE;
00330 #endif
00331 }
00332
00333 static void arts_shutdown()
00334 {
00335 arts_free();
00336 }
00337
00338 static int play_arts_file(gchar *soundfile)
00339 {
00340 AFfilehandle fd;
00341 AFframecount frameCount, count;
00342 arts_stream_t artsStream;
00343 int frameSize, channelCount, sampleFormat, sampleWidth, err, susperr;
00344 double sampleRate;
00345 char * buf;
00346
00347 #ifdef ARTS_FREE_IS_BROKEN
00348
00349 if ((err = arts_init()) != 0)
00350 {
00351 eb_debug(DBG_CORE, "WARNING (NO ERROR!):\ncan_play_arts(): arts_init() failed: %s\nIs artsd running?\n", arts_error_text( err ));
00352 return FALSE;
00353 }
00354 #endif
00355
00356 fd = afOpenFile( soundfile, "r", NULL );
00357 if (fd == AF_NULL_FILEHANDLE)
00358 {
00359 eb_debug(DBG_CORE, "play_arts_file(): Cannot open file %s\n", soundfile);
00360 return FALSE;
00361 }
00362 frameCount = afGetFrameCount( fd, AF_DEFAULT_TRACK );
00363 frameSize = afGetFrameSize( fd, AF_DEFAULT_TRACK, 1 );
00364 channelCount = afGetChannels( fd, AF_DEFAULT_TRACK );
00365 sampleRate = afGetRate( fd, AF_DEFAULT_TRACK );
00366 afGetSampleFormat( fd, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth );
00367 eb_debug(DBG_CORE, "play_arts_file(): frameCount: %d\nframeSize: %i\nchannelCount: %i\nsampleRate: %.2f\n", (int) frameCount, frameSize, channelCount, sampleRate );
00368
00369 artsStream = arts_play_stream( sampleRate, sampleWidth, channelCount, "EVERYBUDDY" );
00370 buf = (char *) malloc( BUFFERED_FRAME_COUNT * frameSize );
00371 count = afReadFrames( fd, AF_DEFAULT_TRACK, buf, BUFFERED_FRAME_COUNT );
00372 do
00373 {
00374 err = arts_write( artsStream, buf, count * frameSize );
00375 eb_debug(DBG_CORE, "count = %d\n", (int) count);
00376 eb_debug(DBG_CORE, "play_arts_file(): written bytes in artsStream: %i\n", err );
00377 if(err < 0)
00378 {
00379 eb_debug(DBG_CORE, "arts_write error: %s\n", arts_error_text( err ) );
00380 }
00381 }
00382 while ((count = afReadFrames( fd, AF_DEFAULT_TRACK, buf, BUFFERED_FRAME_COUNT)) && (err >= 0));
00383 free( buf );
00384 arts_close_stream( artsStream );
00385
00386 afCloseFile( fd );
00387 susperr = arts_suspend();
00388 if(susperr < 0)
00389 {
00390 eb_debug(DBG_CORE, "arts_suspend error: %s\n", arts_error_text( err ) );
00391 }
00392
00393 return (err<0?FALSE:TRUE);
00394 }
00395 #else
00396 static int can_play_arts()
00397 {
00398 return FALSE;
00399 }
00400
00401 static void arts_shutdown()
00402 {
00403 }
00404
00405 static int play_arts_file(gchar *soundfile)
00406 {
00407 return FALSE;
00408 }
00409 #endif
00410
00411 char* auscale(char* infile, char*outfile, float scaling)
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
00422
00423 guchar magic[4];
00424 guint32 dataloc;
00425 guint32 datasize;
00426 guint32 dataformat;
00427 guint32 samplerate;
00428 guint32 channelcount;
00429 guchar info;
00430
00431 } SNDStruct;
00432
00433 SNDStruct auheader;
00434 guchar buf, buf2[256];
00435 guchar map[256];
00436
00437 if (scaling == 0.0) return(infile);
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
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)
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);
00465
00466
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
00481 for (x=0; x<256 ; x++) map[x]=linear2ulaw(scaling*_af_ulaw2linear(x));
00482
00483
00484
00485
00486
00487
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
00509 header_size -= (guint32)sizeof(buf2);
00510 }
00511
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
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 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 gboolean file_ok(gchar *soundfile)
00559 {
00560 gchar message[1024];
00561
00562 if (access(soundfile, R_OK) == -1)
00563
00564
00565
00566 {
00567
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 }
00588
00589
00590 void playsoundfile(gchar *soundfile)
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
00621 if(fGetLocalPref("SoundVolume") != 0.0)
00622 {
00623 gchar tmp_soundfile[9] = "ebXXXXXX";
00624
00625 if (mkstemp(tmp_soundfile) == -1)
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
00650 gtk_timeout_add(100, (GtkFunction)clean_pid, NULL);
00651 }
00652 #endif
00653
00654 }
00655
00656
00657
00658 void play_sound(int sound)
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 }
00698
00699 void sound_init()
00700 {
00701
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
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 }
00730
00731 void sound_shutdown()
00732 {
00733 if(shutdown_sounddrv != NULL) {
00734 shutdown_sounddrv();
00735 }
00736 }