|
|
1.1.1.2 ! root 1: /* $Id: xpbeep.c,v 1.78 2011/06/14 07:47:04 deuce Exp $ */ ! 2: ! 3: /* TODO: USE PORTAUDIO! */ 1.1 root 4: 5: /* standard headers */ 6: #include <math.h> 1.1.1.2 ! root 7: #include <stdlib.h> ! 8: #include "xp_dl.h" 1.1 root 9: 10: #if defined(_WIN32) 11: #include <windows.h> 12: #include <mmsystem.h> 13: #elif defined(__unix__) 14: #include <fcntl.h> 15: #if SOUNDCARD_H_IN==1 16: #include <sys/soundcard.h> 17: #elif SOUNDCARD_H_IN==2 18: #include <soundcard.h> 19: #elif SOUNDCARD_H_IN==3 20: #include <linux/soundcard.h> 21: #else 22: #ifndef USE_ALSA_SOUND 23: #warning Cannot find soundcard.h 24: #endif 25: #endif 26: #ifdef USE_ALSA_SOUND 1.1.1.2 ! root 27: #include <dlfcn.h> 1.1 root 28: #include <alsa/asoundlib.h> 29: #endif 30: /* KIOCSOUND */ 31: #if defined(__FreeBSD__) 32: #include <sys/kbio.h> 33: #elif defined(__linux__) 34: #include <sys/kd.h> 35: #elif defined(__solaris__) 36: #include <sys/kbio.h> 37: #include <sys/kbd.h> 38: #endif 39: #if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(HAS_MACHINE_SPKR_H) 40: #include <machine/spkr.h> 41: #elif defined(__FreeBSD__) 42: #if defined(HAS_DEV_SPEAKER_SPEAKER_H) 43: #include <dev/speaker/speaker.h> 44: #elif defined(HAS_MACHINE_SPEAKER_H) 45: #include <machine/speaker.h> 46: #endif 47: #endif 48: #endif 49: 50: /* xpdev headers */ 1.1.1.2 ! root 51: #ifdef WITH_PORTAUDIO ! 52: #include <portaudio.h> ! 53: #endif ! 54: ! 55: #ifdef WITH_SDL_AUDIO 1.1 root 56: #include "sdlfuncs.h" 57: #endif 1.1.1.2 ! root 58: 1.1 root 59: #include "genwrap.h" 60: #include "xpbeep.h" 61: 62: #define S_RATE 22050 63: 1.1.1.2 ! root 64: #ifdef XPDEV_THREAD_SAFE ! 65: #include "threadwrap.h" ! 66: ! 67: static BOOL sample_thread_running=FALSE; ! 68: static sem_t sample_pending_sem; ! 69: static sem_t sample_complete_sem; ! 70: static BOOL sample_initialized=FALSE; ! 71: static pthread_mutex_t sample_mutex; ! 72: static const unsigned char *sample_buffer; ! 73: static size_t sample_size; ! 74: #endif ! 75: 1.1 root 76: static BOOL sound_device_open_failed=FALSE; 77: static BOOL alsa_device_open_failed=FALSE; 78: static BOOL sdl_device_open_failed=FALSE; 1.1.1.2 ! root 79: static BOOL portaudio_device_open_failed=FALSE; 1.1 root 80: 81: enum { 82: SOUND_DEVICE_CLOSED 83: ,SOUND_DEVICE_WIN32 84: ,SOUND_DEVICE_ALSA 85: ,SOUND_DEVICE_OSS 86: ,SOUND_DEVICE_SDL 1.1.1.2 ! root 87: ,SOUND_DEVICE_PORTAUDIO 1.1 root 88: }; 89: 90: static int handle_type=SOUND_DEVICE_CLOSED; 91: 1.1.1.2 ! root 92: #ifdef WITH_PORTAUDIO ! 93: static PaStream *portaudio_stream; ! 94: static int portaudio_buf_len=0; ! 95: static int portaudio_buf_pos=0; ! 96: static const unsigned char *pawave; ! 97: static int portaudio_initialized=FALSE; ! 98: #ifndef PaStream // Detect version... defined for 1.8 and not for 1.9 ! 99: #define PortAudioCallback void ! 100: #define PaTimestamp PaTime ! 101: #endif ! 102: struct portaudio_api_struct { ! 103: PaError (*init)( void ); ! 104: PaError (*open)( PaStream** stream, ! 105: int numInputChannels, ! 106: int numOutputChannels, ! 107: PaSampleFormat sampleFormat, ! 108: double sampleRate, ! 109: unsigned long framesPerBuffer, ! 110: unsigned long numberOfBuffers, ! 111: PortAudioCallback *callback, ! 112: void *userData ); ! 113: PaError (*close)( PaStream* ); ! 114: PaError (*start)( PaStream *stream ); ! 115: PaError (*stop)( PaStream *stream ); ! 116: PaError (*active)( PaStream *stream ); ! 117: PaError (*write)( PaStream *stream, const void *buf, unsigned long frames ); ! 118: int (*version)( void ); ! 119: int ver; ! 120: }; ! 121: struct portaudio_api_struct *pa_api=NULL; ! 122: #endif ! 123: ! 124: #ifdef WITH_SDL_AUDIO 1.1 root 125: static SDL_AudioSpec spec; 126: static int sdl_audio_buf_len=0; 127: static int sdl_audio_buf_pos=0; 1.1.1.2 ! root 128: static unsigned char *swave; 1.1 root 129: static SDL_sem *sdlToneDone; 130: #endif 131: 132: #ifdef _WIN32 133: static HWAVEOUT waveOut; 134: static WAVEHDR wh; 135: #endif 136: 137: #ifdef USE_ALSA_SOUND 138: static snd_pcm_t *playback_handle; 1.1.1.2 ! root 139: static snd_pcm_hw_params_t *hw_params=NULL; 1.1 root 140: #endif 141: 142: #ifdef AFMT_U8 143: static int dsp; 144: #endif 145: 146: #define WAVE_PI 3.14159265358979323846 147: #define WAVE_TPI 6.28318530717958647692 148: 149: #ifdef USE_ALSA_SOUND 150: struct alsa_api_struct { 151: int (*snd_pcm_open) 152: (snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode); 153: int (*snd_pcm_hw_params_malloc) 154: (snd_pcm_hw_params_t **ptr); 155: int (*snd_pcm_hw_params_any) 156: (snd_pcm_t *pcm, snd_pcm_hw_params_t *params); 157: int (*snd_pcm_hw_params_set_access) 158: (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access); 159: int (*snd_pcm_hw_params_set_format) 160: (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); 161: int (*snd_pcm_hw_params_set_rate_near) 162: (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); 163: int (*snd_pcm_hw_params_set_channels) 164: (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); 165: int (*snd_pcm_hw_params) 166: (snd_pcm_t *pcm, snd_pcm_hw_params_t *params); 167: int (*snd_pcm_prepare) 168: (snd_pcm_t *pcm); 169: void (*snd_pcm_hw_params_free) 170: (snd_pcm_hw_params_t *obj); 171: int (*snd_pcm_close) 172: (snd_pcm_t *pcm); 173: snd_pcm_sframes_t (*snd_pcm_writei) 174: (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); 1.1.1.2 ! root 175: int (*snd_pcm_drain) ! 176: (snd_pcm_t *pcm); 1.1 root 177: }; 178: 179: struct alsa_api_struct *alsa_api=NULL; 180: #endif 181: 182: /********************************************************************************/ 183: /* Calculate and generate a sound wave pattern (thanks to Deuce!) */ 184: /********************************************************************************/ 185: void makewave(double freq, unsigned char *wave, int samples, enum WAVE_SHAPE shape) 186: { 187: int i; 188: int midpoint; 189: double inc; 190: double pos; 191: BOOL endhigh; 192: 193: midpoint=samples/2; 194: inc=8.0*atan(1.0); 195: inc *= ((double)freq / (double)S_RATE); 196: 197: for(i=0;i<samples;i++) { 198: pos=(inc*(double)i); 199: pos -= (int)(pos/WAVE_TPI)*WAVE_TPI; 200: switch(shape) { 201: case WAVE_SHAPE_SINE: 202: wave[i]=(sin (pos))*127+128; 203: break; 204: case WAVE_SHAPE_SINE_HARM: 205: wave[i]=(sin (pos))*64+128; 206: wave[i]=(sin ((inc*2)*(double)i))*24; 207: wave[i]=(sin ((inc*3)*(double)i))*16; 208: break; 209: case WAVE_SHAPE_SAWTOOTH: 210: wave[i]=(WAVE_TPI-pos)*40.5; 211: break; 212: case WAVE_SHAPE_SQUARE: 213: wave[i]=(pos<WAVE_PI)?255:0; 214: break; 215: case WAVE_SHAPE_SINE_SAW: 216: wave[i]=(((sin (pos))*127+128)+((WAVE_TPI-pos)*40.5))/2; 217: break; 218: case WAVE_SHAPE_SINE_SAW_CHORD: 219: wave[i]=(((sin (pos))*64+128)+((WAVE_TPI-pos)*6.2))/2; 220: wave[i]+=(sin ((inc/2)*(double)i))*24; 221: wave[i]+=(sin ((inc/3)*(double)i))*16; 222: break; 223: case WAVE_SHAPE_SINE_SAW_HARM: 224: wave[i]=(((sin (pos))*64+128)+((WAVE_TPI-pos)*6.2))/2; 225: wave[i]+=(sin ((inc*2)*(double)i))*24; 226: wave[i]+=(sin ((inc*3)*(double)i))*16; 227: break; 228: } 229: } 230: 231: /* Now we have a "perfect" wave... 232: * we must clean it up now to avoid click/pop 233: */ 234: if(wave[samples-1]>128) 235: endhigh=TRUE; 236: else 237: endhigh=FALSE; 238: /* Completely remove the last wave fragment */ 239: i=samples-1; 240: if(wave[i]!=128) { 241: for(;i>midpoint;i--) { 242: if(endhigh && wave[i]<128) 243: break; 244: if(!endhigh && wave[i]>128) 245: break; 246: wave[i]=128; 247: } 248: } 249: } 250: 1.1.1.2 ! root 251: #ifdef WITH_PORTAUDIO ! 252: /* ! 253: * Used by v18 library, not v19! ! 254: */ ! 255: static int portaudio_callback(void *inputBuffer ! 256: , void *outputBuffer ! 257: , unsigned long framesPerBuffer ! 258: , const PaTimestamp outTime ! 259: , void *userData ) ! 260: { ! 261: int copylen=framesPerBuffer; ! 262: int maxlen=portaudio_buf_len-portaudio_buf_pos; ! 263: ! 264: if(copylen>maxlen) { ! 265: copylen=maxlen; ! 266: memset(((char *)outputBuffer)+copylen, 128, framesPerBuffer-copylen); ! 267: } ! 268: if(copylen) { ! 269: memcpy(outputBuffer, (*((unsigned char **)userData))+portaudio_buf_pos, copylen); ! 270: portaudio_buf_pos+=copylen; ! 271: } ! 272: if(portaudio_buf_pos >= portaudio_buf_len) ! 273: return(1); ! 274: return(0); ! 275: } ! 276: #endif ! 277: ! 278: #ifdef WITH_SDL_AUDIO 1.1 root 279: void sdl_fillbuf(void *userdata, Uint8 *stream, int len) 280: { 281: int copylen=len; 282: int maxlen=sdl_audio_buf_len-sdl_audio_buf_pos; 283: 284: /* Copy in the current buffer */ 285: if(copylen>maxlen) 286: copylen=maxlen; 287: /* Fill with silence */ 288: if(len>copylen) 289: memset(stream+copylen, spec.silence, len-copylen); 290: if(copylen) { 291: memcpy(stream, swave+sdl_audio_buf_pos, copylen); 292: sdl_audio_buf_pos+=copylen; 293: /* If we're done, post the semaphore */ 294: if(sdl_audio_buf_pos>=sdl_audio_buf_len) { 295: sdl.SemPost(sdlToneDone); 296: sdl_audio_buf_len=0; 297: sdl_audio_buf_pos=0; 298: } 299: } 300: } 301: #endif 302: 303: BOOL xptone_open(void) 304: { 305: #ifdef _WIN32 306: WAVEFORMATEX w; 307: #endif 308: 309: #ifdef AFMT_U8 310: int format=AFMT_U8; 311: int channels=1; 312: int rate=S_RATE; 313: int fragsize=0x7fff0004; 314: #endif 315: 316: /* Already open */ 317: if(handle_type!=SOUND_DEVICE_CLOSED) 318: return(TRUE); 319: 1.1.1.2 ! root 320: #ifdef WITH_PORTAUDIO ! 321: if(!portaudio_device_open_failed) { ! 322: if(pa_api==NULL) { ! 323: dll_handle dl; ! 324: const char *libnames[]={"portaudio",NULL}; ! 325: if(((pa_api=(struct portaudio_api_struct *)malloc(sizeof(struct portaudio_api_struct)))==NULL) ! 326: || ((dl=xp_dlopen(libnames,RTLD_LAZY,0))==NULL) ! 327: || ((pa_api->init=xp_dlsym(dl,Pa_Initialize))==NULL) ! 328: || ((pa_api->open=xp_dlsym(dl,Pa_OpenDefaultStream))==NULL) ! 329: || ((pa_api->close=xp_dlsym(dl,Pa_CloseStream))==NULL) ! 330: || ((pa_api->start=xp_dlsym(dl,Pa_StartStream))==NULL) ! 331: || ! 332: ( ! 333: ((pa_api->active=xp_dlsym(dl,Pa_StreamActive))==NULL) ! 334: && ((pa_api->active=xp_dlsym(dl,Pa_IsStreamActive))==NULL) ! 335: ) ! 336: || ((pa_api->stop=xp_dlsym(dl,Pa_StopStream))==NULL) ! 337: ) { ! 338: if(dl) ! 339: xp_dlclose(dl); ! 340: free(pa_api); ! 341: pa_api=NULL; ! 342: } ! 343: else { ! 344: /* Get version and other optional pointers */ ! 345: pa_api->ver=1800; ! 346: if((pa_api->version=xp_dlsym(dl, Pa_GetVersion))!=NULL) { ! 347: pa_api->ver=pa_api->version(); ! 348: if(pa_api->ver >= 1899) { ! 349: if((pa_api->write=xp_dlsym(dl, Pa_WriteStream))==NULL) { ! 350: xp_dlclose(dl); ! 351: free(pa_api); ! 352: pa_api=NULL; ! 353: } ! 354: } ! 355: } ! 356: } ! 357: if(pa_api==NULL) { ! 358: portaudio_device_open_failed=TRUE; ! 359: } ! 360: } ! 361: if(pa_api != NULL) { ! 362: if(!portaudio_initialized) { ! 363: if(pa_api->init() != paNoError) ! 364: portaudio_device_open_failed=TRUE; ! 365: else ! 366: portaudio_initialized=TRUE; ! 367: } ! 368: if(portaudio_initialized) { ! 369: if(pa_api->open(&portaudio_stream ! 370: , 0 /* No input */ ! 371: , 1 /* Mono output */ ! 372: , paUInt8 ! 373: , S_RATE ! 374: , 256 ! 375: , 0 ! 376: , pa_api->ver >= 1899 ? NULL : portaudio_callback ! 377: , &pawave) != paNoError) ! 378: portaudio_device_open_failed=TRUE; ! 379: else { ! 380: handle_type=SOUND_DEVICE_PORTAUDIO; ! 381: return(TRUE); ! 382: } ! 383: } ! 384: } ! 385: } ! 386: #endif ! 387: ! 388: #ifdef WITH_SDL_AUDIO 1.1 root 389: if(!sdl_device_open_failed) { 390: if(init_sdl_audio()==-1) 391: sdl_device_open_failed=TRUE; 392: else { 393: spec.freq=22050; 394: spec.format=AUDIO_U8; 395: spec.channels=1; 396: spec.samples=256; /* Size of audio buffer */ 397: spec.size=256; 398: spec.callback=sdl_fillbuf; 399: spec.userdata=NULL; 400: if(sdl.OpenAudio(&spec, NULL)==-1) { 401: sdl_device_open_failed=TRUE; 402: } 403: else { 404: sdlToneDone=sdl.SDL_CreateSemaphore(0); 405: sdl_audio_buf_len=0; 406: sdl_audio_buf_pos=0; 407: sdl.PauseAudio(FALSE); 408: handle_type=SOUND_DEVICE_SDL; 409: return(TRUE); 410: } 411: } 412: } 413: #endif 414: 415: #ifdef _WIN32 416: if(!sound_device_open_failed) { 417: w.wFormatTag = WAVE_FORMAT_PCM; 418: w.nChannels = 1; 419: w.nSamplesPerSec = S_RATE; 420: w.wBitsPerSample = 8; 421: w.nBlockAlign = (w.wBitsPerSample * w.nChannels) / 8; 422: w.nAvgBytesPerSec = w.nSamplesPerSec * w.nBlockAlign; 423: 424: if(!sound_device_open_failed && waveOutOpen(&waveOut, WAVE_MAPPER, &w, 0, 0, 0)!=MMSYSERR_NOERROR) 425: sound_device_open_failed=TRUE; 426: if(sound_device_open_failed) 427: return(FALSE); 428: memset(&wh, 0, sizeof(wh)); 1.1.1.2 ! root 429: wh.lpData=NULL; 1.1 root 430: wh.dwBufferLength=S_RATE*15/2+1; 431: handle_type=SOUND_DEVICE_WIN32; 432: if(!sound_device_open_failed) 433: return(TRUE); 434: } 435: #endif 436: 437: #ifdef USE_ALSA_SOUND 438: if(!alsa_device_open_failed) { 439: if(alsa_api==NULL) { 1.1.1.2 ! root 440: dll_handle dl; ! 441: const char *libnames[]={"asound", NULL}; 1.1 root 442: if(((alsa_api=(struct alsa_api_struct *)malloc(sizeof(struct alsa_api_struct)))==NULL) 1.1.1.2 ! root 443: || ((dl=xp_dlopen(libnames,RTLD_LAZY,2))==NULL) ! 444: || ((alsa_api->snd_pcm_open=xp_dlsym(dl,snd_pcm_open))==NULL) ! 445: || ((alsa_api->snd_pcm_hw_params_malloc=xp_dlsym(dl,snd_pcm_hw_params_malloc))==NULL) ! 446: || ((alsa_api->snd_pcm_hw_params_any=xp_dlsym(dl,snd_pcm_hw_params_any))==NULL) ! 447: || ((alsa_api->snd_pcm_hw_params_set_access=xp_dlsym(dl,snd_pcm_hw_params_set_access))==NULL) ! 448: || ((alsa_api->snd_pcm_hw_params_set_format=xp_dlsym(dl,snd_pcm_hw_params_set_format))==NULL) ! 449: || ((alsa_api->snd_pcm_hw_params_set_rate_near=xp_dlsym(dl,snd_pcm_hw_params_set_rate_near))==NULL) ! 450: || ((alsa_api->snd_pcm_hw_params_set_channels=xp_dlsym(dl,snd_pcm_hw_params_set_channels))==NULL) ! 451: || ((alsa_api->snd_pcm_hw_params=xp_dlsym(dl,snd_pcm_hw_params))==NULL) ! 452: || ((alsa_api->snd_pcm_prepare=xp_dlsym(dl,snd_pcm_prepare))==NULL) ! 453: || ((alsa_api->snd_pcm_hw_params_free=xp_dlsym(dl,snd_pcm_hw_params_free))==NULL) ! 454: || ((alsa_api->snd_pcm_close=xp_dlsym(dl,snd_pcm_close))==NULL) ! 455: || ((alsa_api->snd_pcm_writei=xp_dlsym(dl,snd_pcm_writei))==NULL) ! 456: || ((alsa_api->snd_pcm_drain=xp_dlsym(dl,snd_pcm_drain))==NULL) ! 457: ) { ! 458: if(dl) ! 459: xp_dlclose(dl); ! 460: free(alsa_api); ! 461: alsa_api=NULL; 1.1 root 462: alsa_device_open_failed=TRUE; 463: } 464: if(alsa_api==NULL) 465: alsa_device_open_failed=TRUE; 466: } 467: if(alsa_api!=NULL) { 1.1.1.2 ! root 468: int rate=S_RATE; ! 469: if((alsa_api->snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)<0) 1.1 root 470: || (alsa_api->snd_pcm_hw_params_malloc(&hw_params)<0) 471: || (alsa_api->snd_pcm_hw_params_any(playback_handle, hw_params)<0) 472: || (alsa_api->snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) 473: || (alsa_api->snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_U8) < 0) 1.1.1.2 ! root 474: || (alsa_api->snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0) < 0) 1.1 root 475: || (alsa_api->snd_pcm_hw_params_set_channels(playback_handle, hw_params, 1) < 0) 476: || (alsa_api->snd_pcm_hw_params(playback_handle, hw_params) < 0) 477: || (alsa_api->snd_pcm_prepare(playback_handle) < 0)) { 478: alsa_device_open_failed=TRUE; 479: if(hw_params!=NULL) 480: alsa_api->snd_pcm_hw_params_free(hw_params); 481: if(playback_handle!=NULL) { 482: alsa_api->snd_pcm_close(playback_handle); 483: playback_handle=NULL; 484: } 485: } 486: else { 1.1.1.2 ! root 487: alsa_api->snd_pcm_hw_params_free(hw_params); 1.1 root 488: handle_type=SOUND_DEVICE_ALSA; 489: return(TRUE); 490: } 491: } 492: } 493: #endif 494: 495: #ifdef AFMT_U8 496: if(!sound_device_open_failed) { 497: if((dsp=open("/dev/dsp",O_WRONLY,0))<0) { 498: sound_device_open_failed=TRUE; 499: } 500: else { 501: ioctl(dsp, SNDCTL_DSP_SETFRAGMENT, &fragsize); 502: if((ioctl(dsp, SNDCTL_DSP_SETFMT, &format)==-1) || format!=AFMT_U8) { 503: sound_device_open_failed=TRUE; 504: close(dsp); 505: } 506: else if((ioctl(dsp, SNDCTL_DSP_CHANNELS, &channels)==-1) || channels!=1) { 507: sound_device_open_failed=TRUE; 508: close(dsp); 509: } 510: else if((ioctl(dsp, SNDCTL_DSP_SPEED, &rate)==-1) || rate!=S_RATE) { 511: sound_device_open_failed=TRUE; 512: close(dsp); 513: } 514: } 515: } 516: if(sound_device_open_failed) 517: return(FALSE); 518: handle_type=SOUND_DEVICE_OSS; 519: if(!sound_device_open_failed) 520: return(TRUE); 521: #endif 522: return(FALSE); 523: } 524: 525: BOOL xptone_close(void) 526: { 1.1.1.2 ! root 527: #ifdef WITH_PORTAUDIO ! 528: if(handle_type==SOUND_DEVICE_PORTAUDIO) { ! 529: pa_api->close(portaudio_stream); ! 530: } ! 531: #endif ! 532: ! 533: #ifdef WITH_SDL_AUDIO 1.1 root 534: if(handle_type==SOUND_DEVICE_SDL) { 535: sdl.CloseAudio(); 536: sdl.SDL_DestroySemaphore(sdlToneDone); 537: } 538: #endif 539: 540: #ifdef _WIN32 541: if(handle_type==SOUND_DEVICE_WIN32) { 542: waveOutClose(waveOut); 543: } 544: #endif 545: 546: #ifdef USE_ALSA_SOUND 1.1.1.2 ! root 547: if(handle_type==SOUND_DEVICE_ALSA) { 1.1 root 548: alsa_api->snd_pcm_close (playback_handle); 1.1.1.2 ! root 549: playback_handle=NULL; ! 550: } 1.1 root 551: #endif 552: 553: #ifdef AFMT_U8 554: if(handle_type==SOUND_DEVICE_OSS) 555: close(dsp); 556: #endif 557: handle_type=SOUND_DEVICE_CLOSED; 558: sound_device_open_failed=FALSE; 559: alsa_device_open_failed=FALSE; 560: sdl_device_open_failed=FALSE; 561: 562: return(TRUE); 563: } 564: 1.1.1.2 ! root 565: #ifdef XPDEV_THREAD_SAFE ! 566: void xp_play_sample_thread(void *data) 1.1 root 567: { 568: BOOL must_close=FALSE; 1.1.1.2 ! root 569: BOOL posted_last=TRUE; ! 570: BOOL waited=FALSE; 1.1 root 571: 1.1.1.2 ! root 572: #ifdef AFMT_U8 ! 573: int wr; ! 574: int i; 1.1 root 575: #endif 576: 1.1.1.2 ! root 577: sample_thread_running=TRUE; ! 578: while(1) { ! 579: if(!waited) { ! 580: if(sem_wait(&sample_pending_sem)!=0) ! 581: goto error_return; ! 582: } ! 583: else ! 584: waited=FALSE; ! 585: posted_last=FALSE; ! 586: if(pthread_mutex_lock(&sample_mutex)!=0) ! 587: goto error_return; ! 588: ! 589: if(handle_type==SOUND_DEVICE_CLOSED) { ! 590: must_close=TRUE; ! 591: if(!xptone_open()) { ! 592: sem_post(&sample_complete_sem); ! 593: pthread_mutex_unlock(&sample_mutex); ! 594: continue; ! 595: } ! 596: } ! 597: ! 598: #ifdef WITH_PORTAUDIO ! 599: if(handle_type==SOUND_DEVICE_PORTAUDIO) { ! 600: if(pa_api->ver >= 1899) { ! 601: pa_api->write(portaudio_stream, sample_buffer, sample_size); ! 602: } ! 603: else { ! 604: pawave=sample_buffer; ! 605: portaudio_buf_pos=0; ! 606: portaudio_buf_len=sample_size; ! 607: pa_api->start(portaudio_stream); ! 608: } ! 609: while(pa_api->active(portaudio_stream)) ! 610: SLEEP(1); ! 611: pa_api->stop(portaudio_stream); ! 612: } ! 613: #endif ! 614: ! 615: #ifdef WITH_SDL_AUDIO ! 616: if(handle_type==SOUND_DEVICE_SDL) { ! 617: sdl.LockAudio(); ! 618: swave=sample_buffer; ! 619: sdl_audio_buf_pos=0; ! 620: sdl_audio_buf_len=sample_size; ! 621: sdl.UnlockAudio(); ! 622: sdl.SemWait(sdlToneDone); ! 623: } ! 624: #endif ! 625: ! 626: #ifdef _WIN32 ! 627: if(handle_type==SOUND_DEVICE_WIN32) { ! 628: wh.lpData=sample_buffer; ! 629: wh.dwBufferLength=sample_size; ! 630: if(waveOutPrepareHeader(waveOut, &wh, sizeof(wh))==MMSYSERR_NOERROR) { ! 631: if(waveOutWrite(waveOut, &wh, sizeof(wh))==MMSYSERR_NOERROR) { ! 632: while(!(wh.dwFlags & WHDR_DONE)) ! 633: SLEEP(1); ! 634: while(waveOutUnprepareHeader(waveOut, &wh, sizeof(wh))==WAVERR_STILLPLAYING) ! 635: SLEEP(1); ! 636: } ! 637: } ! 638: } ! 639: #endif ! 640: ! 641: #ifdef USE_ALSA_SOUND ! 642: if(handle_type==SOUND_DEVICE_ALSA) { ! 643: int ret; ! 644: int written=0; ! 645: ! 646: while(written < sample_size) { ! 647: ret=alsa_api->snd_pcm_writei(playback_handle, sample_buffer+written, sample_size-written); ! 648: if(ret < 0) { ! 649: if(written==0) { ! 650: /* Go back and try OSS */ ! 651: xptone_close(); ! 652: alsa_device_open_failed=TRUE; ! 653: xptone_open(); ! 654: } ! 655: break; ! 656: } ! 657: written += ret; ! 658: } ! 659: if(!alsa_device_open_failed) { ! 660: while(alsa_api->snd_pcm_drain(playback_handle)) ! 661: SLEEP(1); ! 662: } ! 663: } ! 664: #endif ! 665: ! 666: #ifdef AFMT_U8 ! 667: if(handle_type==SOUND_DEVICE_OSS) { ! 668: wr=0; ! 669: while(wr<sample_size) { ! 670: i=write(dsp, sample_buffer+wr, sample_size-wr); ! 671: if(i>=0) ! 672: wr+=i; ! 673: } ! 674: } ! 675: #endif ! 676: sem_post(&sample_complete_sem); ! 677: posted_last=TRUE; ! 678: pthread_mutex_unlock(&sample_mutex); ! 679: if(must_close) { ! 680: if(sem_trywait(&sample_pending_sem)==0) ! 681: waited=TRUE; ! 682: else ! 683: xptone_close(); ! 684: } ! 685: } ! 686: ! 687: error_return: ! 688: xptone_close(); ! 689: if(!posted_last) ! 690: sem_post(&sample_complete_sem); ! 691: sample_thread_running=FALSE; ! 692: pthread_mutex_unlock(&sample_mutex); ! 693: } ! 694: ! 695: BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t size, BOOL background) ! 696: { ! 697: if(!sample_initialized) { ! 698: if(pthread_mutex_init(&sample_mutex, NULL)!=0) ! 699: return(FALSE); ! 700: pthread_mutex_lock(&sample_mutex); ! 701: if(sem_init(&sample_pending_sem, 0, 0)!=0) { ! 702: pthread_mutex_destroy(&sample_mutex); ! 703: return(FALSE); ! 704: } ! 705: if(sem_init(&sample_complete_sem, 0, 1)!=0) { ! 706: pthread_mutex_destroy(&sample_mutex); ! 707: sem_destroy(&sample_pending_sem); ! 708: return(FALSE); ! 709: } ! 710: sample_initialized=TRUE; ! 711: pthread_mutex_unlock(&sample_mutex); ! 712: } ! 713: ! 714: sem_wait(&sample_complete_sem); ! 715: pthread_mutex_lock(&sample_mutex); ! 716: if(!sample_thread_running) { ! 717: _beginthread(xp_play_sample_thread, 0,NULL); ! 718: } ! 719: ! 720: sample_buffer=sample; ! 721: sample_size=size; ! 722: pthread_mutex_unlock(&sample_mutex); ! 723: sem_post(&sample_pending_sem); ! 724: if(!background) { ! 725: sem_wait(&sample_complete_sem); ! 726: sem_post(&sample_complete_sem); ! 727: } ! 728: return(TRUE); ! 729: } ! 730: #else ! 731: BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t sample_size, BOOL background) ! 732: { ! 733: BOOL must_close=FALSE; 1.1 root 734: 735: #ifdef AFMT_U8 736: int wr; 737: int i; 738: #endif 739: 740: if(handle_type==SOUND_DEVICE_CLOSED) { 741: must_close=TRUE; 742: if(!xptone_open()) 743: return(FALSE); 744: } 745: 1.1.1.2 ! root 746: #ifdef WITH_PORTAUDIO ! 747: if(handle_type==SOUND_DEVICE_PORTAUDIO) { ! 748: if(pa_api->ver >= 1899) { ! 749: pa_api->write(portaudio_stream, sample, sample_size); ! 750: } ! 751: else { ! 752: pawave=sample; ! 753: portaudio_buf_pos=0; ! 754: portaudio_buf_len=sample_size; ! 755: pa_api->start(portaudio_stream); ! 756: } ! 757: while(pa_api->active(portaudio_stream)) ! 758: SLEEP(1); ! 759: pa_api->stop(portaudio_stream); ! 760: } ! 761: #endif ! 762: ! 763: #ifdef WITH_SDL_AUDIO 1.1 root 764: if(handle_type==SOUND_DEVICE_SDL) { 765: sdl.LockAudio(); 1.1.1.2 ! root 766: swave=sample; 1.1 root 767: sdl_audio_buf_pos=0; 1.1.1.2 ! root 768: sdl_audio_buf_len=sample_size; 1.1 root 769: sdl.UnlockAudio(); 770: sdl.SemWait(sdlToneDone); 771: } 772: #endif 773: 774: #ifdef _WIN32 775: if(handle_type==SOUND_DEVICE_WIN32) { 1.1.1.2 ! root 776: wh.lpData=sample; ! 777: wh.dwBufferLength=sample_size; ! 778: if(waveOutPrepareHeader(waveOut, &wh, sizeof(wh))==MMSYSERR_NOERROR) { ! 779: if(waveOutWrite(waveOut, &wh, sizeof(wh))==MMSYSERR_NOERROR) { ! 780: while(!(wh.dwFlags & WHDR_DONE)) ! 781: SLEEP(1); ! 782: while(waveOutUnprepareHeader(waveOut, &wh, sizeof(wh))==WAVERR_STILLPLAYING) ! 783: SLEEP(1); ! 784: } 1.1 root 785: } 786: } 787: #endif 788: 789: #ifdef USE_ALSA_SOUND 790: if(handle_type==SOUND_DEVICE_ALSA) { 1.1.1.2 ! root 791: int ret; ! 792: int written=0; ! 793: ! 794: while(written < sample_size) { ! 795: ret=alsa_api->snd_pcm_writei(playback_handle, sample+written, sample_size-written); ! 796: if(ret < 0) { ! 797: if(written==0) { ! 798: /* Go back and try OSS */ ! 799: xptone_close(); ! 800: alsa_device_open_failed=TRUE; ! 801: xptone_open(); ! 802: } ! 803: break; ! 804: } ! 805: written += ret; 1.1 root 806: } 1.1.1.2 ! root 807: if(!alsa_device_open_failed) { ! 808: while(alsa_api->snd_pcm_drain(playback_handle)) ! 809: SLEEP(1); 1.1 root 810: if(must_close) 811: xptone_close(); 812: return(TRUE); 813: } 814: } 815: #endif 816: 817: #ifdef AFMT_U8 818: if(handle_type==SOUND_DEVICE_OSS) { 819: wr=0; 1.1.1.2 ! root 820: while(wr<sample_size) { ! 821: i=write(dsp, sample+wr, sample_size-wr); 1.1 root 822: if(i>=0) 823: wr+=i; 824: } 825: if(must_close) 826: xptone_close(); 827: return(TRUE); 828: } 829: #endif 830: if(must_close) 831: xptone_close(); 832: return(FALSE); 833: } 1.1.1.2 ! root 834: #endif ! 835: ! 836: /********************************************************************************/ ! 837: /* Play a tone through the wave/DSP output device (sound card) - Deuce */ ! 838: /********************************************************************************/ ! 839: ! 840: BOOL DLLCALL xptone(double freq, DWORD duration, enum WAVE_SHAPE shape) ! 841: { ! 842: unsigned char wave[S_RATE*15/2+1]; ! 843: int samples; ! 844: ! 845: if(freq<17) ! 846: freq=17; ! 847: samples=S_RATE*duration/1000; ! 848: if(samples<=S_RATE/freq*2) ! 849: samples=S_RATE/freq*2; ! 850: if(samples > S_RATE/freq*2) { ! 851: int sample_len; ! 852: ! 853: makewave(freq,wave,S_RATE*15/2,shape); ! 854: for(sample_len=S_RATE*15/2-1; sample_len && wave[sample_len]==128; sample_len--) ! 855: ; ! 856: sample_len++; ! 857: while(samples > S_RATE*15/2) { ! 858: if(!xp_play_sample(wave, sample_len, TRUE)) ! 859: return FALSE; ! 860: samples -= sample_len; ! 861: } ! 862: } ! 863: makewave(freq,wave,samples,shape); ! 864: return(xp_play_sample(wave, samples, FALSE)); ! 865: } 1.1 root 866: 867: #ifdef __unix__ 868: /****************************************************************************/ 869: /* Generate a tone at specified frequency for specified milliseconds */ 870: /* Thanks to Casey Martin (and Deuce) for this code */ 871: /****************************************************************************/ 872: void DLLCALL unix_beep(int freq, int dur) 873: { 874: static int console_fd=-1; 875: 876: #if (defined(__FreeBSD__) && defined(HAS_MACHINE_SPEAKER_H)) || ((defined(__OpenBSD__) || defined(__NetBSD__)) && defined(HAS_MACHINE_SPKR_H)) 877: int speaker_fd=-1; 878: tone_t tone; 879: 880: speaker_fd = open("/dev/speaker", O_WRONLY|O_APPEND); 881: if(speaker_fd != -1) { 882: tone.frequency=freq; 883: tone.duration=dur/10; 884: ioctl(speaker_fd,SPKRTONE,&tone); 885: close(speaker_fd); 886: return; 887: } 888: #endif 889: 890: #if !defined(__GNU__) && !defined(__QNX__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(__CYGWIN__) 891: if(console_fd == -1) 892: console_fd = open("/dev/console", O_NOCTTY); 893: 894: if(console_fd != -1) { 895: #if defined(__solaris__) 896: ioctl(console_fd, KIOCCMD, KBD_CMD_BELL); 897: #else 898: if(freq != 0) /* Don't divide by zero */ 899: ioctl(console_fd, KIOCSOUND, (int) (1193180 / freq)); 900: #endif /* solaris */ 901: SLEEP(dur); 902: #if defined(__solaris__) 903: ioctl(console_fd, KIOCCMD, KBD_CMD_NOBELL); /* turn off tone */ 904: #else 905: ioctl(console_fd, KIOCSOUND, 0); /* turn off tone */ 906: #endif /* solaris */ 907: } 908: #endif 909: } 910: 911: #endif 912: 913: /********************************************************************************/ 914: /* Play sound through DSP/wave device, if unsuccessful, play through PC speaker */ 915: /********************************************************************************/ 916: void xpbeep(double freq, DWORD duration) 917: { 918: if(xptone(freq,duration,WAVE_SHAPE_SINE_SAW_HARM)) 919: return; 920: 921: #if defined(_WIN32) 922: Beep((DWORD)(freq+.5), duration); 923: #elif defined(__unix__) 924: unix_beep((int)(freq+.5),duration); 925: #endif 926: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.