diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c index a312b549c49..bd49985c959 100644 --- a/dlls/dsound/dsound_main.c +++ b/dlls/dsound/dsound_main.c @@ -1140,6 +1140,8 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown (*ippDS)->drvcaps.dwPrimaryBuffers = 1; } + (*ippDS)->volpan.lVolume = 0; + (*ippDS)->volpan.lPan = 0; DSOUND_RecalcVolPan(&((*ippDS)->volpan)); InitializeCriticalSection(&((*ippDS)->mixlock)); diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index e282a61f8ea..4f21f58ce99 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -55,14 +55,14 @@ void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) TRACE("(%p)\n",volpan); /* the AmpFactors are expressed in 16.16 fixed point */ - volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 65536); + volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 0xffff); /* FIXME: dwPan{Left|Right}AmpFactor */ /* FIXME: use calculated vol and pan ampfactors */ temp = (double) (volpan->lVolume - (volpan->lPan > 0 ? volpan->lPan : 0)); - volpan->dwTotalLeftAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 65536); + volpan->dwTotalLeftAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff); temp = (double) (volpan->lVolume + (volpan->lPan < 0 ? volpan->lPan : 0)); - volpan->dwTotalRightAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 65536); + volpan->dwTotalRightAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff); TRACE("left = %lx, right = %lx\n", volpan->dwTotalLeftAmpFactor, volpan->dwTotalRightAmpFactor); } diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 42b76fb4bc5..7589f8c06ee 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -74,6 +74,8 @@ static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This) HRESULT err = DS_OK; TRACE("(%p)\n",This); + DSOUND_RecalcVolPan(&(This->volpan)); + /* are we using waveOut stuff? */ if (!This->hwbuf) { LPBYTE newbuf; @@ -128,7 +130,15 @@ static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This) } if ((err == DS_OK) && (merr != DS_OK)) err = merr; + + if (!err) { + DWORD vol = (This->volpan.dwTotalLeftAmpFactor & 0xffff) | (This->volpan.dwTotalRightAmpFactor << 16); + err = mmErr(waveOutSetVolume(This->hwo, vol)); + } + } else { + err = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan)); } + return err; } @@ -431,7 +441,6 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume( TRACE("(%p,%ld)\n",This,vol); - /* I'm not sure if we need this for primary buffer */ if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL; @@ -458,15 +467,9 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume( WARN("IDsDriverBuffer_SetVolumePan failed\n"); return hres; } - } - else { -#if 0 /* should we really do this? */ - /* the DS volume ranges from 0 (max, 0dB attenuation) to -10000 (min, 100dB attenuation) */ - /* the MM volume ranges from 0 to 0xffff in an unspecified logarithmic scale */ - WORD cvol = 0xffff + vol*6 + vol/2; - DWORD vol = cvol | ((DWORD)cvol << 16) + } else { + DWORD vol = (dsound->volpan.dwTotalLeftAmpFactor & 0xffff) | (dsound->volpan.dwTotalRightAmpFactor << 16); waveOutSetVolume(dsound->hwo, vol); -#endif } } @@ -778,13 +781,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan( } } else { -#if 0 /* should we really do this? */ - /* the DS volume ranges from 0 (max, 0dB attenuation) to -10000 (min, 100dB attenuation) */ - /* the MM volume ranges from 0 to 0xffff in an unspecified logarithmic scale */ - WORD cvol = 0xffff + vol*6 + vol/2; - DWORD vol = cvol | ((DWORD)cvol << 16) + DWORD vol = (dsound->volpan.dwTotalLeftAmpFactor & 0xffff) | (dsound->volpan.dwTotalRightAmpFactor << 16); waveOutSetVolume(dsound->hwo, vol); -#endif } } diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c index eeb628ed6fd..f5abbe22c50 100644 --- a/dlls/dsound/propset.c +++ b/dlls/dsound/propset.c @@ -431,8 +431,47 @@ static HRESULT WINAPI DSPROPERTY_Description1( } } } else { - FIXME("DeviceId=Unknown\n"); - return E_PROP_ID_UNSUPPORTED; + BOOL found = FALSE; + ULONG wod; + int wodn; + /* given specific device so try the render devices first */ + wodn = waveOutGetNumDevs(); + for (wod = 0; wod < wodn; wod++) { + err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0)); + if (err == DS_OK) { + if (IsEqualGUID( &ppd->DeviceId, &guid) ) { + DSDRIVERDESC desc; + TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n"); + ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; + ppd->WaveDeviceId = wod; + ppd->Devnode = wod; + err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0)); + if (err == DS_OK) { + PIDSDRIVER drv = NULL; + strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1); + strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1); + MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); + err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0)); + if (err == DS_OK && drv) + ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; + found = TRUE; + break; + } else { + WARN("waveOutMessage failed\n"); + return E_PROP_ID_UNSUPPORTED; + } + } + } else { + WARN("waveOutMessage failed\n"); + return E_PROP_ID_UNSUPPORTED; + } + } + + if (found == FALSE) { + WARN("device not found\n"); + return E_PROP_ID_UNSUPPORTED; + } } if (pcbReturned) { diff --git a/dlls/dsound/tests/dsound.c b/dlls/dsound/tests/dsound.c index c2fb5e747e8..fcbdd7b60ac 100644 --- a/dlls/dsound/tests/dsound.c +++ b/dlls/dsound/tests/dsound.c @@ -254,7 +254,8 @@ STOP: } static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, - int is_primary, int play, int buffer3d, + int is_primary, BOOL set_volume, LONG volume, + BOOL set_pan, LONG pan, int play, int buffer3d, LPDIRECTSOUND3DLISTENER listener, int move_listener, int move_sound) { @@ -358,7 +359,7 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, if (play) { play_state_t state; - LONG volume,pan; + LPDIRECTSOUND3DBUFFER buffer=NULL; DS3DBUFFER buffer_param; DS3DLISTENER listener_param; @@ -417,34 +418,50 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param); ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc); } - if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) { - rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); - ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc); - - rc=IDirectSoundBuffer_SetVolume(dsbo,-300); + if (set_volume) { + rc=IDirectSoundBuffer_SetVolume(dsbo,volume); ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc); rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); trace(" volume=%ld\n",volume); } else { - /* DSOUND: Error: Buffer does not have CTRLVOLUME */ - rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); - ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc); + if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) { + rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); + ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc); + + rc=IDirectSoundBuffer_SetVolume(dsbo,-300); + ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc); + + rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); + trace(" volume=%ld\n",volume); + } else { + /* DSOUND: Error: Buffer does not have CTRLVOLUME */ + rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); + ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc); + } } - if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) { - rc=IDirectSoundBuffer_GetPan(dsbo,&pan); - ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc); - - rc=IDirectSoundBuffer_SetPan(dsbo,0); + if (set_pan) { + rc=IDirectSoundBuffer_SetPan(dsbo,pan); ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc); rc=IDirectSoundBuffer_GetPan(dsbo,&pan); trace(" pan=%ld\n",pan); } else { - /* DSOUND: Error: Buffer does not have CTRLPAN */ - rc=IDirectSoundBuffer_GetPan(dsbo,&pan); - ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc); + if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) { + rc=IDirectSoundBuffer_GetPan(dsbo,&pan); + ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc); + + rc=IDirectSoundBuffer_SetPan(dsbo,0); + ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc); + + rc=IDirectSoundBuffer_GetPan(dsbo,&pan); + trace(" pan=%ld\n",pan); + } else { + /* DSOUND: Error: Buffer does not have CTRLPAN */ + rc=IDirectSoundBuffer_GetPan(dsbo,&pan); + ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc); + } } state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len); @@ -639,7 +656,7 @@ static HRESULT test_secondary(LPGUID lpGuid, int play, } if (rc==DS_OK&&secondary!=NULL) { - test_buffer(dso,secondary,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound); + test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref); } @@ -768,7 +785,7 @@ static HRESULT test_primary(LPGUID lpGuid) LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL; DSBUFFERDESC bufdesc; DSCAPS dscaps; - int ref; + int ref, i; /* Create the DirectSound object */ rc=DirectSoundCreate(lpGuid,&dso,NULL); @@ -829,7 +846,22 @@ static HRESULT test_primary(LPGUID lpGuid) rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third); /* rc=0x88780032 */ ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc); - test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); + test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); + test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); + if (winetest_interactive) { + LONG volume = DSBVOLUME_MAX; + for (i = 0; i < 6; i++) { + test_buffer(dso,primary,1,TRUE,volume,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); + volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40); + } + if (winetest_interactive) { + LONG pan = DSBPAN_LEFT; + for (i = 0; i < 7; i++) { + test_buffer(dso,primary,1,TRUE,0,TRUE,pan,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); + pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6); + } + } + } ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); } @@ -894,7 +926,7 @@ static HRESULT test_primary_3d(LPGUID lpGuid) rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc); if (rc==DS_OK&&primary!=NULL) { - test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); + test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0); ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); } @@ -971,7 +1003,7 @@ static HRESULT test_primary_3d_with_listener(LPGUID lpGuid) ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref); /* Testing the buffer */ - test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0); + test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0); } /* Testing the reference counting */ diff --git a/dlls/winmm/wineoss/audio.c b/dlls/winmm/wineoss/audio.c index 83cd00db07a..b570a487cb7 100644 --- a/dlls/winmm/wineoss/audio.c +++ b/dlls/winmm/wineoss/audio.c @@ -1891,7 +1891,10 @@ static DWORD wodSetVolume(WORD wDevID, DWORD dwParam) right = (HIWORD(dwParam) * 100) / 0xFFFFl; volume = left + (right << 8); - if (wDevID >= numOutDev) return MMSYSERR_INVALPARAM; + if (wDevID >= numOutDev) { + WARN("invalid parameter: wDevID > %d\n", numOutDev); + return MMSYSERR_INVALPARAM; + } if ((mixer = open(WOutDev[wDevID].ossdev->mixer_name, O_WRONLY|O_NDELAY)) < 0) { WARN("mixer device not available !\n"); @@ -2138,9 +2141,17 @@ static HRESULT WINAPI IDsDriverBufferImpl_SetFrequency(PIDSDRIVERBUFFER iface, D static HRESULT WINAPI IDsDriverBufferImpl_SetVolumePan(PIDSDRIVERBUFFER iface, PDSVOLUMEPAN pVolPan) { - /* ICOM_THIS(IDsDriverBufferImpl,iface); */ - FIXME("(%p,%p): stub!\n",iface,pVolPan); - /* FIXME: the dsound software mixer does this for us so don't return an error */ + DWORD vol; + ICOM_THIS(IDsDriverBufferImpl,iface); + TRACE("(%p,%p)\n",This,pVolPan); + + vol = pVolPan->dwTotalLeftAmpFactor | (pVolPan->dwTotalRightAmpFactor << 16); + + if (wodSetVolume(This->drv->wDevID, vol) != MMSYSERR_NOERROR) { + WARN("wodSetVolume failed\n"); + return DSERR_INVALIDPARAM; + } + return DS_OK; }