/* WebDownloader for X-Window * Copyright (C) 1999-2002 Koshelev Maxim * This Program is free but not GPL!!! You can't modify it * without agreement with author. You can't distribute modified * program but you can distribute unmodified program. * * 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. */ #include #include #include #include #include #include #include #include "sndserv.h" #include "locstr.h" #include "var.h" #define WAVE_FORMAT_UNKNOWN (0x0000) #define WAVE_FORMAT_PCM (0x0001) #define WAVE_FORMAT_ADPCM (0x0002) #define WAVE_FORMAT_ALAW (0x0006) #define WAVE_FORMAT_MULAW (0x0007) #define WAVE_FORMAT_OKI_ADPCM (0x0010) #define WAVE_FORMAT_DIGISTD (0x0015) #define WAVE_FORMAT_DIGIFIX (0x0016) #define IBM_FORMAT_MULAW (0x0101) #define IBM_FORMAT_ALAW (0x0102) #define IBM_FORMAT_ADPCM (0x0103) enum FMT_ENUM{ FMT_U8, FMT_S8, FMT_U16_LE, FMT_U16_BE, FMT_U16_NE, FMT_S16_LE, FMT_S16_BE, FMT_S16_NE }; class d4xAudio{ public: d4xAudio(); virtual int write(void *data, int length); virtual int open(int fmt, int rate, int nch); virtual ~d4xAudio(); }; #ifdef D4X_WITH_OSS #include class d4xOssAudio:public d4xAudio{ int fragsize,oss_format,format,channels,frequency; int fd; int bps,ebps; int blk_size; int convert_stereo; void setup_format(int fmt,int rate, int nch); void set_audio_params(); public: d4xOssAudio(); ~d4xOssAudio(); int write(void *data, int length); int open(int fmt, int rate, int nch); }; #endif //D4X_WITH_OSS #ifdef D4X_WITH_AO #include class d4xAOAudio:public d4xAudio{ ao_device *snd_device; ao_sample_format snd_format; int ao_drv_id; public: d4xAOAudio(); ~d4xAOAudio(); int write(void *data, int length); int open(int fmt, int rate, int nch); }; #endif //D4X_WITH_AO class d4xSndFile{ public: d4xSndFile(){}; d4xSndFile(char *filename); virtual void play()=0; virtual ~d4xSndFile(){}; }; class d4xWaveFile:public d4xSndFile{ FILE *file; short format,channels,align,bits,eof; long samples_per_sec, avg_bytes_per_sec; int position, length; int data_offset; d4xAudio *audio; int read_long(long *len); int read_short(short *val); void play_begin(); public: d4xWaveFile(char *filename); void play(); ~d4xWaveFile(); }; #ifdef HAVE_ESD #include class d4xEsdFile:public d4xSndFile{ int fd; char *file; public: d4xEsdFile(char *filename); void play(); ~d4xEsdFile(); }; /***********************************************************/ d4xEsdFile::d4xEsdFile(char *filename){ file=copy_string(filename); fd=-1; }; void d4xEsdFile::play(){ if (fd<0) fd=esd_open_sound(NULL);//"localhost"); if (fd>=0) esd_play_file(NULL,file,0); // ??? }; d4xEsdFile::~d4xEsdFile(){ if (fd>=0) esd_close(fd); }; #endif //HAVE_ESD /***********************************************************/ int d4xWaveFile::read_long(long *len){ unsigned char buf[4]; if (fread(buf, 1, 4, file) != 4) return 0; #if G_BYTE_ORDER == G_LITTLE_ENDIAN *len =(buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; #else *len =(buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; #endif return 1; }; int d4xWaveFile::read_short(short *val){ unsigned char buf[2]; if (fread(buf, 1, 2, file) != 2) return 0; #if G_BYTE_ORDER == G_LITTLE_ENDIAN *val = (buf[1] << 8) | buf[0]; #else *val = (buf[0] << 8) | buf[1]; #endif return 1; } d4xWaveFile::d4xWaveFile(char *filename){ #ifdef D4X_WITH_OSS audio=new d4xOssAudio; #elif defined(D4X_WITH_AO) audio=new d4xAOAudio; #else audio=new d4xAudio; #endif char data[4]; format=channels=align=bits=eof=0; samples_per_sec=avg_bytes_per_sec=0; if ((file = fopen(filename, "r"))){ fread(data, 1, 4, file); if (strncmp(data, "RIFF", 4)){ fclose(file); file = NULL; return; } long tmp; read_long(&tmp); fread(data, 1, 4, file); if (strncmp(data, "WAVE", 4)){ fclose(file); file = NULL; return; } }; }; d4xWaveFile::~d4xWaveFile(){ if (file) fclose(file); if (audio) delete(audio); }; void d4xWaveFile::play(){ char data[4]; unsigned long len; int audio_error = 0; if (file){ while(1){ fread(data, 1, 4, file); if (!read_long((long *)&len)) return; if (!strncmp("fmt ", data, 4)) break; fseek(file,len,SEEK_CUR); } if (len < 16){ return; } read_short(&format); switch (format) { case WAVE_FORMAT_UNKNOWN: case WAVE_FORMAT_ALAW: case WAVE_FORMAT_MULAW: case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_OKI_ADPCM: case WAVE_FORMAT_DIGISTD: case WAVE_FORMAT_DIGIFIX: case IBM_FORMAT_MULAW: case IBM_FORMAT_ALAW: case IBM_FORMAT_ADPCM: return; } if (!read_short(&channels)) return; if (!read_long(&samples_per_sec)) return; if (!read_long(&avg_bytes_per_sec)) return; if (!read_short(&align)) return; if (!read_short(&bits)) return; /* printf("channels = %i\n",int(channels)); printf("sps = %li\n",samples_per_sec); printf("abps = %li\n",avg_bytes_per_sec); printf("bps = %i\n",int(bits)); */ if (bits != 8 && bits != 16) return; len -= 16; if (len) fseek(file, len, SEEK_CUR); while(1){ fread(data, 4, 1, file); if (!read_long((long *)&len)) return; if (!strncmp("data", data, 4)) break; fseek(file, len, SEEK_CUR); } length = len; position = 0; if (audio->open((bits == 16) ? FMT_S16_LE : FMT_U8, samples_per_sec, channels) == 0){ audio_error = 1; return; } eof=0; play_begin(); } } void d4xWaveFile::play_begin(){ char data[2048 * 2]; int blk_size = 512 * (bits / 8) * channels; // printf("playing (blk_size=%i)\n",blk_size); while (!eof){ int bytes = blk_size; if (length - position < bytes) bytes = length - position; if (bytes > 0){ int actual_read = fread(data, 1, bytes, file); if (actual_read == -1){ eof = 1; }else{ audio->write(data, bytes); position += actual_read; }; }else{ eof = 1; } } } /***********************************************************/ d4xAudio::d4xAudio(){ /* abstract */ }; int d4xAudio::write(void *data, int length){ return(length); }; int d4xAudio::open(int fmt, int rate, int nch){ return(1); }; d4xAudio::~d4xAudio(){ /* absctract */ }; /***********************************************************/ #ifdef D4X_WITH_OSS void d4xOssAudio::setup_format(int fmt,int rate, int nch){ format = fmt; frequency = rate; channels = nch; switch (fmt){ case FMT_U8: oss_format = AFMT_U8; break; case FMT_S16_LE: oss_format = AFMT_S16_LE; break; } bps = rate * nch; if (oss_format == AFMT_S16_LE) bps *= 2; fragsize = 0; while ((1L << fragsize) < bps / 25) fragsize++; fragsize--; } void d4xOssAudio::set_audio_params(){ ioctl(fd, SNDCTL_DSP_RESET, 0); int frag = (32 << 16) | fragsize; ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag); ioctl(fd, SNDCTL_DSP_SETFMT, &oss_format); int stereo = channels - 1; ioctl(fd, SNDCTL_DSP_STEREO, &stereo); ioctl(fd, SNDCTL_DSP_SPEED, &frequency); if(ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blk_size) == -1) blk_size = 1L << fragsize; ebps = frequency * channels; if (oss_format == AFMT_S16_LE) ebps *= 2; } int d4xOssAudio::open(int fmt, int rate, int nch){ fd = ::open("/dev/dsp", O_WRONLY);//|O_NONBLOCK); if (fd == -1){ // printf("open_audio(): Failed to open audio device (%s): %s", // "/dev/dsp", strerror(errno)); return 0; } setup_format(fmt,rate,nch); set_audio_params(); return 1; } int d4xOssAudio::write(void * data, int length){ return (::write(fd, data, length)); } d4xOssAudio::d4xOssAudio(){ fd=-1; }; d4xOssAudio::~d4xOssAudio(){ if (fd>=0){ ioctl(fd, SNDCTL_DSP_POST, 0); close(fd); }; }; #endif //D4X_WITH_OSS /***********************************************************/ #ifdef D4X_WITH_AO int d4xAOAudio::open(int fmt, int rate, int nch){ switch (fmt){ case FMT_U8: snd_format.bits = 8; snd_format.byte_format = AO_FMT_LITTLE; break; case FMT_S16_LE: snd_format.bits = 16; snd_format.byte_format = AO_FMT_LITTLE; break; } snd_format.rate = rate; snd_format.channels = nch; ao_drv_id = ao_default_driver_id(); if (ao_drv_id < 0) return 0; snd_device = ao_open_live(ao_drv_id, &snd_format, NULL); if (snd_device == NULL) return 0; return 1; } int d4xAOAudio::write(void * data, int length){ return (ao_play(snd_device, (char *)data, length)); } d4xAOAudio::d4xAOAudio(){ snd_device = NULL; ao_drv_id = -1; }; d4xAOAudio::~d4xAOAudio(){ if (snd_device != NULL) ao_close(snd_device); }; #endif //D4X_WITH_AO /***********************************************************/ d4xSndServer *SOUND_SERVER; static void *_snd_serv_run_(void *serv){ d4xSndServer *server=(d4xSndServer *)serv; sigset_t oldmask,newmask; sigemptyset(&newmask); sigaddset(&newmask,SIGTERM); sigaddset(&newmask,SIGINT); sigaddset(&newmask,SIGUSR1); sigaddset(&newmask,SIGUSR2); pthread_sigmask(SIG_BLOCK,&newmask,&oldmask); server->run(); pthread_exit(NULL); return(NULL); }; d4xSndServer::d4xSndServer(){ stop_now=0; for (int i=0;i=0 && eventplay(); delete(wav); }; }; void d4xSndServer::run(){ while(true){ my_mutex.lock(); pthread_cond_wait(&cond,&(my_mutex.m)); std::list tmpqueue=queue; queue.clear(); my_mutex.unlock(); while(!tmpqueue.empty()){ d4x::SndEvent snd=tmpqueue.front(); time_t now=time(NULL); if (snd.birth-now<4 && snd.birth-now>-4){ /* playing */ play_sound(snd.event); }; tmpqueue.pop_front(); }; if (stop_now) break; }; }; void d4xSndServer::set_sound_file(int event,char *path){ my_mutex.lock(); if (event>=0 && event=0 && event