Annotation of quake2/win32/snd_win.c, revision 1.1.1.1

1.1       root        1: #include <float.h>
                      2: 
                      3: #include "../client/client.h"
                      4: #include "../client/snd_loc.h"
                      5: #include "winquake.h"
                      6: 
                      7: #define iDirectSoundCreate(a,b,c)      pDirectSoundCreate(a,b,c)
                      8: 
                      9: HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
                     10: 
                     11: // 64K is > 1 second at 16-bit, 22050 Hz
                     12: #define        WAV_BUFFERS                             64
                     13: #define        WAV_MASK                                0x3F
                     14: #define        WAV_BUFFER_SIZE                 0x0400
                     15: #define SECONDARY_BUFFER_SIZE  0x10000
                     16: 
                     17: typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
                     18: 
                     19: cvar_t *s_wavonly;
                     20: 
                     21: static qboolean        dsound_init;
                     22: static qboolean        wav_init;
                     23: static qboolean        snd_firsttime = true, snd_isdirect, snd_iswave;
                     24: static qboolean        primary_format_set;
                     25: 
                     26: // starts at 0 for disabled
                     27: static int     snd_buffer_count = 0;
                     28: static int     sample16;
                     29: static int     snd_sent, snd_completed;
                     30: 
                     31: /* 
                     32:  * Global variables. Must be visible to window-procedure function 
                     33:  *  so it can unlock and free the data block after it has been played. 
                     34:  */ 
                     35: 
                     36: 
                     37: HANDLE         hData;
                     38: HPSTR          lpData, lpData2;
                     39: 
                     40: HGLOBAL                hWaveHdr;
                     41: LPWAVEHDR      lpWaveHdr;
                     42: 
                     43: HWAVEOUT    hWaveOut; 
                     44: 
                     45: WAVEOUTCAPS    wavecaps;
                     46: 
                     47: DWORD  gSndBufSize;
                     48: 
                     49: MMTIME         mmstarttime;
                     50: 
                     51: LPDIRECTSOUND pDS;
                     52: LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
                     53: 
                     54: HINSTANCE hInstDS;
                     55: 
                     56: qboolean SNDDMA_InitDirect (void);
                     57: qboolean SNDDMA_InitWav (void);
                     58: 
                     59: void FreeSound( void );
                     60: 
                     61: static const char *DSoundError( int error )
                     62: {
                     63:        switch ( error )
                     64:        {
                     65:        case DSERR_BUFFERLOST:
                     66:                return "DSERR_BUFFERLOST";
                     67:        case DSERR_INVALIDCALL:
                     68:                return "DSERR_INVALIDCALLS";
                     69:        case DSERR_INVALIDPARAM:
                     70:                return "DSERR_INVALIDPARAM";
                     71:        case DSERR_PRIOLEVELNEEDED:
                     72:                return "DSERR_PRIOLEVELNEEDED";
                     73:        }
                     74: 
                     75:        return "unknown";
                     76: }
                     77: 
                     78: /*
                     79: ** DS_CreateBuffers
                     80: */
                     81: static qboolean DS_CreateBuffers( void )
                     82: {
                     83:        DSBUFFERDESC    dsbuf;
                     84:        DSBCAPS                 dsbcaps;
                     85:        WAVEFORMATEX    pformat, format;
                     86:        DWORD                   dwWrite;
                     87: 
                     88:        memset (&format, 0, sizeof(format));
                     89:        format.wFormatTag = WAVE_FORMAT_PCM;
                     90:     format.nChannels = dma.channels;
                     91:     format.wBitsPerSample = dma.samplebits;
                     92:     format.nSamplesPerSec = dma.speed;
                     93:     format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
                     94:     format.cbSize = 0;
                     95:     format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; 
                     96: 
                     97:        Com_Printf( "Creating DS buffers\n" );
                     98: 
                     99:        Com_DPrintf("...setting EXCLUSIVE coop level: " );
                    100:        if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_EXCLUSIVE ) )
                    101:        {
                    102:                Com_Printf ("failed\n");
                    103:                FreeSound ();
                    104:                return false;
                    105:        }
                    106:        Com_DPrintf("ok\n" );
                    107: 
                    108: // get access to the primary buffer, if possible, so we can set the
                    109: // sound hardware format
                    110:        memset (&dsbuf, 0, sizeof(dsbuf));
                    111:        dsbuf.dwSize = sizeof(DSBUFFERDESC);
                    112:        dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
                    113:        dsbuf.dwBufferBytes = 0;
                    114:        dsbuf.lpwfxFormat = NULL;
                    115: 
                    116:        memset(&dsbcaps, 0, sizeof(dsbcaps));
                    117:        dsbcaps.dwSize = sizeof(dsbcaps);
                    118:        primary_format_set = false;
                    119: 
                    120:        Com_DPrintf( "...creating primary buffer: " );
                    121:        if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
                    122:        {
                    123:                pformat = format;
                    124: 
                    125:                Com_DPrintf( "ok\n" );
                    126:                if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat))
                    127:                {
                    128:                        if (snd_firsttime)
                    129:                                Com_DPrintf ("...setting primary sound format: failed\n");
                    130:                }
                    131:                else
                    132:                {
                    133:                        if (snd_firsttime)
                    134:                                Com_DPrintf ("...setting primary sound format: ok\n");
                    135: 
                    136:                        primary_format_set = true;
                    137:                }
                    138:        }
                    139:        else
                    140:                Com_Printf( "failed\n" );
                    141: 
                    142:        if ( !primary_format_set || !s_primary->value)
                    143:        {
                    144:        // create the secondary buffer we'll actually work with
                    145:                memset (&dsbuf, 0, sizeof(dsbuf));
                    146:                dsbuf.dwSize = sizeof(DSBUFFERDESC);
                    147:                dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
                    148:                dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
                    149:                dsbuf.lpwfxFormat = &format;
                    150: 
                    151:                memset(&dsbcaps, 0, sizeof(dsbcaps));
                    152:                dsbcaps.dwSize = sizeof(dsbcaps);
                    153: 
                    154:                Com_DPrintf( "...creating secondary buffer: " );
                    155:                if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL))
                    156:                {
                    157:                        Com_Printf( "failed\n" );
                    158:                        FreeSound ();
                    159:                        return false;
                    160:                }
                    161:                Com_DPrintf( "ok\n" );
                    162: 
                    163:                dma.channels = format.nChannels;
                    164:                dma.samplebits = format.wBitsPerSample;
                    165:                dma.speed = format.nSamplesPerSec;
                    166: 
                    167:                if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps))
                    168:                {
                    169:                        Com_Printf ("*** GetCaps failed ***\n");
                    170:                        FreeSound ();
                    171:                        return false;
                    172:                }
                    173: 
                    174:                Com_Printf ("...using secondary sound buffer\n");
                    175:        }
                    176:        else
                    177:        {
                    178:                Com_Printf( "...using primary buffer\n" );
                    179: 
                    180:                Com_DPrintf( "...setting WRITEPRIMARY coop level: " );
                    181:                if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, cl_hwnd, DSSCL_WRITEPRIMARY))
                    182:                {
                    183:                        Com_Printf( "failed\n" );
                    184:                        FreeSound ();
                    185:                        return false;
                    186:                }
                    187:                Com_DPrintf( "ok\n" );
                    188: 
                    189:                if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps))
                    190:                {
                    191:                        Com_Printf ("*** GetCaps failed ***\n");
                    192:                        return false;
                    193:                }
                    194: 
                    195:                pDSBuf = pDSPBuf;
                    196:        }
                    197: 
                    198:        // Make sure mixer is active
                    199:        pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
                    200: 
                    201:        if (snd_firsttime)
                    202:                Com_Printf("   %d channel(s)\n"
                    203:                               "   %d bits/sample\n"
                    204:                                           "   %d bytes/sec\n",
                    205:                                           dma.channels, dma.samplebits, dma.speed);
                    206:        
                    207:        gSndBufSize = dsbcaps.dwBufferBytes;
                    208: 
                    209:        /* we don't want anyone to access the buffer directly w/o locking it first. */
                    210:        lpData = NULL; 
                    211: 
                    212:        pDSBuf->lpVtbl->Stop(pDSBuf);
                    213:        pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite);
                    214:        pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
                    215: 
                    216:        dma.samples = gSndBufSize/(dma.samplebits/8);
                    217:        dma.samplepos = 0;
                    218:        dma.submission_chunk = 1;
                    219:        dma.buffer = (unsigned char *) lpData;
                    220:        sample16 = (dma.samplebits/8) - 1;
                    221: 
                    222:        return true;
                    223: }
                    224: 
                    225: /*
                    226: ** DS_DestroyBuffers
                    227: */
                    228: static void DS_DestroyBuffers( void )
                    229: {
                    230:        Com_DPrintf( "Destroying DS buffers\n" );
                    231:        if ( pDS )
                    232:        {
                    233:                Com_DPrintf( "...setting NORMAL coop level\n" );
                    234:                pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_NORMAL );
                    235:        }
                    236: 
                    237:        if ( pDSBuf )
                    238:        {
                    239:                Com_DPrintf( "...stopping and releasing sound buffer\n" );
                    240:                pDSBuf->lpVtbl->Stop( pDSBuf );
                    241:                pDSBuf->lpVtbl->Release( pDSBuf );
                    242:        }
                    243: 
                    244:        // only release primary buffer if it's not also the mixing buffer we just released
                    245:        if ( pDSPBuf && ( pDSBuf != pDSPBuf ) )
                    246:        {
                    247:                Com_DPrintf( "...releasing primary buffer\n" );
                    248:                pDSPBuf->lpVtbl->Release( pDSPBuf );
                    249:        }
                    250:        pDSBuf = NULL;
                    251:        pDSPBuf = NULL;
                    252: 
                    253:        dma.buffer = NULL;
                    254: }
                    255: 
                    256: /*
                    257: ==================
                    258: FreeSound
                    259: ==================
                    260: */
                    261: void FreeSound (void)
                    262: {
                    263:        int             i;
                    264: 
                    265:        Com_DPrintf( "Shutting down sound system\n" );
                    266: 
                    267:        if ( pDS )
                    268:                DS_DestroyBuffers();
                    269: 
                    270:        if ( hWaveOut )
                    271:        {
                    272:                Com_DPrintf( "...resetting waveOut\n" );
                    273:                waveOutReset (hWaveOut);
                    274: 
                    275:                if (lpWaveHdr)
                    276:                {
                    277:                        Com_DPrintf( "...unpreparing headers\n" );
                    278:                        for (i=0 ; i< WAV_BUFFERS ; i++)
                    279:                                waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
                    280:                }
                    281: 
                    282:                Com_DPrintf( "...closing waveOut\n" );
                    283:                waveOutClose (hWaveOut);
                    284: 
                    285:                if (hWaveHdr)
                    286:                {
                    287:                        Com_DPrintf( "...freeing WAV header\n" );
                    288:                        GlobalUnlock(hWaveHdr);
                    289:                        GlobalFree(hWaveHdr);
                    290:                }
                    291: 
                    292:                if (hData)
                    293:                {
                    294:                        Com_DPrintf( "...freeing WAV buffer\n" );
                    295:                        GlobalUnlock(hData);
                    296:                        GlobalFree(hData);
                    297:                }
                    298: 
                    299:        }
                    300: 
                    301:        if ( pDS )
                    302:        {
                    303:                Com_DPrintf( "...releasing DS object\n" );
                    304:                pDS->lpVtbl->Release( pDS );
                    305:        }
                    306: 
                    307:        if ( hInstDS )
                    308:        {
                    309:                Com_DPrintf( "...freeing DSOUND.DLL\n" );
                    310:                FreeLibrary( hInstDS );
                    311:                hInstDS = NULL;
                    312:        }
                    313: 
                    314:        pDS = NULL;
                    315:        pDSBuf = NULL;
                    316:        pDSPBuf = NULL;
                    317:        hWaveOut = 0;
                    318:        hData = 0;
                    319:        hWaveHdr = 0;
                    320:        lpData = NULL;
                    321:        lpWaveHdr = NULL;
                    322:        dsound_init = false;
                    323:        wav_init = false;
                    324: }
                    325: 
                    326: /*
                    327: ==================
                    328: SNDDMA_InitDirect
                    329: 
                    330: Direct-Sound support
                    331: ==================
                    332: */
                    333: sndinitstat SNDDMA_InitDirect (void)
                    334: {
                    335:        DSCAPS                  dscaps;
                    336:        HRESULT                 hresult;
                    337: 
                    338:        dma.channels = 2;
                    339:        dma.samplebits = 16;
                    340: 
                    341:        if (s_khz->value == 44)
                    342:                dma.speed = 44100;
                    343:        if (s_khz->value == 22)
                    344:                dma.speed = 22050;
                    345:        else
                    346:                dma.speed = 11025;
                    347: 
                    348:        Com_Printf( "Initializing DirectSound\n");
                    349: 
                    350:        if ( !hInstDS )
                    351:        {
                    352:                Com_DPrintf( "...loading dsound.dll: " );
                    353: 
                    354:                hInstDS = LoadLibrary("dsound.dll");
                    355:                
                    356:                if (hInstDS == NULL)
                    357:                {
                    358:                        Com_Printf ("failed\n");
                    359:                        return SIS_FAILURE;
                    360:                }
                    361: 
                    362:                Com_DPrintf ("ok\n");
                    363:                pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
                    364: 
                    365:                if (!pDirectSoundCreate)
                    366:                {
                    367:                        Com_Printf ("*** couldn't get DS proc addr ***\n");
                    368:                        return SIS_FAILURE;
                    369:                }
                    370:        }
                    371: 
                    372:        Com_DPrintf( "...creating DS object: " );
                    373:        while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK )
                    374:        {
                    375:                if (hresult != DSERR_ALLOCATED)
                    376:                {
                    377:                        Com_Printf( "failed\n" );
                    378:                        return SIS_FAILURE;
                    379:                }
                    380: 
                    381:                if (MessageBox (NULL,
                    382:                                                "The sound hardware is in use by another app.\n\n"
                    383:                                            "Select Retry to try to start sound again or Cancel to run Quake with no sound.",
                    384:                                                "Sound not available",
                    385:                                                MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
                    386:                {
                    387:                        Com_Printf ("failed, hardware already in use\n" );
                    388:                        return SIS_NOTAVAIL;
                    389:                }
                    390:        }
                    391:        Com_DPrintf( "ok\n" );
                    392: 
                    393:        dscaps.dwSize = sizeof(dscaps);
                    394: 
                    395:        if ( DS_OK != pDS->lpVtbl->GetCaps( pDS, &dscaps ) )
                    396:        {
                    397:                Com_Printf ("*** couldn't get DS caps ***\n");
                    398:        }
                    399: 
                    400:        if ( dscaps.dwFlags & DSCAPS_EMULDRIVER )
                    401:        {
                    402:                Com_DPrintf ("...no DSound driver found\n" );
                    403:                FreeSound();
                    404:                return SIS_FAILURE;
                    405:        }
                    406: 
                    407:        if ( !DS_CreateBuffers() )
                    408:                return SIS_FAILURE;
                    409: 
                    410:        dsound_init = true;
                    411: 
                    412:        Com_DPrintf("...completed successfully\n" );
                    413: 
                    414:        return SIS_SUCCESS;
                    415: }
                    416: 
                    417: 
                    418: /*
                    419: ==================
                    420: SNDDM_InitWav
                    421: 
                    422: Crappy windows multimedia base
                    423: ==================
                    424: */
                    425: qboolean SNDDMA_InitWav (void)
                    426: {
                    427:        WAVEFORMATEX  format; 
                    428:        int                             i;
                    429:        HRESULT                 hr;
                    430: 
                    431:        Com_Printf( "Initializing wave sound\n" );
                    432:        
                    433:        snd_sent = 0;
                    434:        snd_completed = 0;
                    435: 
                    436:        dma.channels = 2;
                    437:        dma.samplebits = 16;
                    438: 
                    439:        if (s_khz->value == 44)
                    440:                dma.speed = 44100;
                    441:        if (s_khz->value == 22)
                    442:                dma.speed = 22050;
                    443:        else
                    444:                dma.speed = 11025;
                    445: 
                    446:        memset (&format, 0, sizeof(format));
                    447:        format.wFormatTag = WAVE_FORMAT_PCM;
                    448:        format.nChannels = dma.channels;
                    449:        format.wBitsPerSample = dma.samplebits;
                    450:        format.nSamplesPerSec = dma.speed;
                    451:        format.nBlockAlign = format.nChannels
                    452:                *format.wBitsPerSample / 8;
                    453:        format.cbSize = 0;
                    454:        format.nAvgBytesPerSec = format.nSamplesPerSec
                    455:                *format.nBlockAlign; 
                    456:        
                    457:        /* Open a waveform device for output using window callback. */ 
                    458:        Com_DPrintf ("...opening waveform device: ");
                    459:        while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, 
                    460:                                        &format, 
                    461:                                        0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR)
                    462:        {
                    463:                if (hr != MMSYSERR_ALLOCATED)
                    464:                {
                    465:                        Com_Printf ("failed\n");
                    466:                        return false;
                    467:                }
                    468: 
                    469:                if (MessageBox (NULL,
                    470:                                                "The sound hardware is in use by another app.\n\n"
                    471:                                            "Select Retry to try to start sound again or Cancel to run Quake 2 with no sound.",
                    472:                                                "Sound not available",
                    473:                                                MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
                    474:                {
                    475:                        Com_Printf ("hw in use\n" );
                    476:                        return false;
                    477:                }
                    478:        } 
                    479:        Com_DPrintf( "ok\n" );
                    480: 
                    481:        /* 
                    482:         * Allocate and lock memory for the waveform data. The memory 
                    483:         * for waveform data must be globally allocated with 
                    484:         * GMEM_MOVEABLE and GMEM_SHARE flags. 
                    485: 
                    486:        */ 
                    487:        Com_DPrintf ("...allocating waveform buffer: ");
                    488:        gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE;
                    489:        hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); 
                    490:        if (!hData) 
                    491:        { 
                    492:                Com_Printf( " failed\n" );
                    493:                FreeSound ();
                    494:                return false; 
                    495:        }
                    496:        Com_DPrintf( "ok\n" );
                    497: 
                    498:        Com_DPrintf ("...locking waveform buffer: ");
                    499:        lpData = GlobalLock(hData);
                    500:        if (!lpData)
                    501:        { 
                    502:                Com_Printf( " failed\n" );
                    503:                FreeSound ();
                    504:                return false; 
                    505:        } 
                    506:        memset (lpData, 0, gSndBufSize);
                    507:        Com_DPrintf( "ok\n" );
                    508: 
                    509:        /* 
                    510:         * Allocate and lock memory for the header. This memory must 
                    511:         * also be globally allocated with GMEM_MOVEABLE and 
                    512:         * GMEM_SHARE flags. 
                    513:         */ 
                    514:        Com_DPrintf ("...allocating waveform header: ");
                    515:        hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, 
                    516:                (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); 
                    517: 
                    518:        if (hWaveHdr == NULL)
                    519:        { 
                    520:                Com_Printf( "failed\n" );
                    521:                FreeSound ();
                    522:                return false; 
                    523:        } 
                    524:        Com_DPrintf( "ok\n" );
                    525: 
                    526:        Com_DPrintf ("...locking waveform header: ");
                    527:        lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); 
                    528: 
                    529:        if (lpWaveHdr == NULL)
                    530:        { 
                    531:                Com_Printf( "failed\n" );
                    532:                FreeSound ();
                    533:                return false; 
                    534:        }
                    535:        memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
                    536:        Com_DPrintf( "ok\n" );
                    537: 
                    538:        /* After allocation, set up and prepare headers. */ 
                    539:        Com_DPrintf ("...preparing headers: ");
                    540:        for (i=0 ; i<WAV_BUFFERS ; i++)
                    541:        {
                    542:                lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE; 
                    543:                lpWaveHdr[i].lpData = lpData + i*WAV_BUFFER_SIZE;
                    544: 
                    545:                if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) !=
                    546:                                MMSYSERR_NOERROR)
                    547:                {
                    548:                        Com_Printf ("failed\n");
                    549:                        FreeSound ();
                    550:                        return false;
                    551:                }
                    552:        }
                    553:        Com_DPrintf ("ok\n");
                    554: 
                    555:        dma.samples = gSndBufSize/(dma.samplebits/8);
                    556:        dma.samplepos = 0;
                    557:        dma.submission_chunk = 512;
                    558:        dma.buffer = (unsigned char *) lpData;
                    559:        sample16 = (dma.samplebits/8) - 1;
                    560: 
                    561:        wav_init = true;
                    562: 
                    563:        return true;
                    564: }
                    565: 
                    566: /*
                    567: ==================
                    568: SNDDMA_Init
                    569: 
                    570: Try to find a sound device to mix for.
                    571: Returns false if nothing is found.
                    572: ==================
                    573: */
                    574: int SNDDMA_Init(void)
                    575: {
                    576:        sndinitstat     stat;
                    577: 
                    578:        memset ((void *)&dma, 0, sizeof (dma));
                    579: 
                    580:        s_wavonly = Cvar_Get ("s_wavonly", "0", 0);
                    581: 
                    582:        dsound_init = wav_init = 0;
                    583: 
                    584:        stat = SIS_FAILURE;     // assume DirectSound won't initialize
                    585: 
                    586:        /* Init DirectSound */
                    587:        if (!s_wavonly->value)
                    588:        {
                    589:                if (snd_firsttime || snd_isdirect)
                    590:                {
                    591:                        stat = SNDDMA_InitDirect ();
                    592: 
                    593:                        if (stat == SIS_SUCCESS)
                    594:                        {
                    595:                                snd_isdirect = true;
                    596: 
                    597:                                if (snd_firsttime)
                    598:                                        Com_Printf ("dsound init succeeded\n" );
                    599:                        }
                    600:                        else
                    601:                        {
                    602:                                snd_isdirect = false;
                    603:                                Com_Printf ("*** dsound init failed ***\n");
                    604:                        }
                    605:                }
                    606:        }
                    607: 
                    608: // if DirectSound didn't succeed in initializing, try to initialize
                    609: // waveOut sound, unless DirectSound failed because the hardware is
                    610: // already allocated (in which case the user has already chosen not
                    611: // to have sound)
                    612:        if (!dsound_init && (stat != SIS_NOTAVAIL))
                    613:        {
                    614:                if (snd_firsttime || snd_iswave)
                    615:                {
                    616: 
                    617:                        snd_iswave = SNDDMA_InitWav ();
                    618: 
                    619:                        if (snd_iswave)
                    620:                        {
                    621:                                if (snd_firsttime)
                    622:                                        Com_Printf ("Wave sound init succeeded\n");
                    623:                        }
                    624:                        else
                    625:                        {
                    626:                                Com_Printf ("Wave sound init failed\n");
                    627:                        }
                    628:                }
                    629:        }
                    630: 
                    631:        snd_firsttime = false;
                    632: 
                    633:        snd_buffer_count = 1;
                    634: 
                    635:        if (!dsound_init && !wav_init)
                    636:        {
                    637:                if (snd_firsttime)
                    638:                        Com_Printf ("*** No sound device initialized ***\n");
                    639: 
                    640:                return 0;
                    641:        }
                    642: 
                    643:        return 1;
                    644: }
                    645: 
                    646: /*
                    647: ==============
                    648: SNDDMA_GetDMAPos
                    649: 
                    650: return the current sample position (in mono samples read)
                    651: inside the recirculating dma buffer, so the mixing code will know
                    652: how many sample are required to fill it up.
                    653: ===============
                    654: */
                    655: int SNDDMA_GetDMAPos(void)
                    656: {
                    657:        MMTIME  mmtime;
                    658:        int             s;
                    659:        DWORD   dwWrite;
                    660: 
                    661:        if (dsound_init) 
                    662:        {
                    663:                mmtime.wType = TIME_SAMPLES;
                    664:                pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
                    665:                s = mmtime.u.sample - mmstarttime.u.sample;
                    666:        }
                    667:        else if (wav_init)
                    668:        {
                    669:                s = snd_sent * WAV_BUFFER_SIZE;
                    670:        }
                    671: 
                    672: 
                    673:        s >>= sample16;
                    674: 
                    675:        s &= (dma.samples-1);
                    676: 
                    677:        return s;
                    678: }
                    679: 
                    680: /*
                    681: ==============
                    682: SNDDMA_BeginPainting
                    683: 
                    684: Makes sure dma.buffer is valid
                    685: ===============
                    686: */
                    687: DWORD  locksize;
                    688: void SNDDMA_BeginPainting (void)
                    689: {
                    690:        int             reps;
                    691:        DWORD   dwSize2;
                    692:        DWORD   *pbuf, *pbuf2;
                    693:        HRESULT hresult;
                    694:        DWORD   dwStatus;
                    695: 
                    696:        if (!pDSBuf)
                    697:                return;
                    698: 
                    699:        // if the buffer was lost or stopped, restore it and/or restart it
                    700:        if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK)
                    701:                Com_Printf ("Couldn't get sound buffer status\n");
                    702:        
                    703:        if (dwStatus & DSBSTATUS_BUFFERLOST)
                    704:                pDSBuf->lpVtbl->Restore (pDSBuf);
                    705:        
                    706:        if (!(dwStatus & DSBSTATUS_PLAYING))
                    707:                pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
                    708: 
                    709:        // lock the dsound buffer
                    710: 
                    711:        reps = 0;
                    712:        dma.buffer = NULL;
                    713: 
                    714:        while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &locksize, 
                    715:                                                                   &pbuf2, &dwSize2, 0)) != DS_OK)
                    716:        {
                    717:                if (hresult != DSERR_BUFFERLOST)
                    718:                {
                    719:                        Com_Printf( "S_TransferStereo16: Lock failed with error '%s'\n", DSoundError( hresult ) );
                    720:                        S_Shutdown ();
                    721:                        return;
                    722:                }
                    723:                else
                    724:                {
                    725:                        pDSBuf->lpVtbl->Restore( pDSBuf );
                    726:                }
                    727: 
                    728:                if (++reps > 2)
                    729:                        return;
                    730:        }
                    731:        dma.buffer = (unsigned char *)pbuf;
                    732: }
                    733: 
                    734: /*
                    735: ==============
                    736: SNDDMA_Submit
                    737: 
                    738: Send sound to device if buffer isn't really the dma buffer
                    739: Also unlocks the dsound buffer
                    740: ===============
                    741: */
                    742: void SNDDMA_Submit(void)
                    743: {
                    744:        LPWAVEHDR       h;
                    745:        int                     wResult;
                    746: 
                    747:        if (!dma.buffer)
                    748:                return;
                    749: 
                    750:        // unlock the dsound buffer
                    751:        if (pDSBuf)
                    752:                pDSBuf->lpVtbl->Unlock(pDSBuf, dma.buffer, locksize, NULL, 0);
                    753: 
                    754:        if (!wav_init)
                    755:                return;
                    756: 
                    757:        //
                    758:        // find which sound blocks have completed
                    759:        //
                    760:        while (1)
                    761:        {
                    762:                if ( snd_completed == snd_sent )
                    763:                {
                    764:                        Com_DPrintf ("Sound overrun\n");
                    765:                        break;
                    766:                }
                    767: 
                    768:                if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) )
                    769:                {
                    770:                        break;
                    771:                }
                    772: 
                    773:                snd_completed++;        // this buffer has been played
                    774:        }
                    775: 
                    776: //Com_Printf ("completed %i\n", snd_completed);
                    777:        //
                    778:        // submit a few new sound blocks
                    779:        //
                    780:        while (((snd_sent - snd_completed) >> sample16) < 8)
                    781:        {
                    782:                h = lpWaveHdr + ( snd_sent&WAV_MASK );
                    783:        if (paintedtime/256 <= snd_sent)
                    784:                break;  //      Com_Printf ("submit overrun\n");
                    785: //Com_Printf ("send %i\n", snd_sent);
                    786:                snd_sent++;
                    787:                /* 
                    788:                 * Now the data block can be sent to the output device. The 
                    789:                 * waveOutWrite function returns immediately and waveform 
                    790:                 * data is sent to the output device in the background. 
                    791:                 */ 
                    792:                wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); 
                    793: 
                    794:                if (wResult != MMSYSERR_NOERROR)
                    795:                { 
                    796:                        Com_Printf ("Failed to write block to device\n");
                    797:                        FreeSound ();
                    798:                        return; 
                    799:                } 
                    800:        }
                    801: }
                    802: 
                    803: /*
                    804: ==============
                    805: SNDDMA_Shutdown
                    806: 
                    807: Reset the sound device for exiting
                    808: ===============
                    809: */
                    810: void SNDDMA_Shutdown(void)
                    811: {
                    812:        FreeSound ();
                    813: }
                    814: 
                    815: 
                    816: /*
                    817: ===========
                    818: S_Activate
                    819: 
                    820: Called when the main window gains or loses focus.
                    821: The window have been destroyed and recreated
                    822: between a deactivate and an activate.
                    823: ===========
                    824: */
                    825: void S_Activate (qboolean active)
                    826: {
                    827:        if ( active )
                    828:        {
                    829:                if ( pDS && cl_hwnd && snd_isdirect )
                    830:                {
                    831:                        DS_CreateBuffers();
                    832:                }
                    833:        }
                    834:        else
                    835:        {
                    836:                if ( pDS && cl_hwnd && snd_isdirect )
                    837:                {
                    838:                        DS_DestroyBuffers();
                    839:                }
                    840:        }
                    841: }
                    842: 

unix.superglobalmegacorp.com

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