Annotation of sbbs/src/xpdev/xpbeep.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.