Annotation of quake2/win32/snd_win.c, revision 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.