Fix segmentation fault caused by incorrect referencing of client audio

format specifications array.
This commit is contained in:
Robert Lunnon 2005-05-07 12:17:28 +00:00 committed by Alexandre Julliard
parent fc40dcf985
commit dc1ceb95cb
1 changed files with 49 additions and 37 deletions

View File

@ -57,8 +57,10 @@
#endif #endif
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "wine/unicode.h"
#include "wingdi.h" #include "wingdi.h"
#include "winerror.h" #include "winerror.h"
#include "winuser.h"
#include "mmddk.h" #include "mmddk.h"
#include "dsound.h" #include "dsound.h"
#include "dsdriver.h" #include "dsdriver.h"
@ -198,16 +200,16 @@ static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
break; break;
case TIME_SMPTE: case TIME_SMPTE:
lpTime->u.smpte.fps = 30; lpTime->u.smpte.fps = 30;
position = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels); position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
position += (format->Format.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */ position += (format->wf.nSamplesPerSec / lpTime->u.smpte.fps) - 1; /* round up */
lpTime->u.smpte.sec = position / format->Format.nSamplesPerSec; lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->Format.nSamplesPerSec; position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60; lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min; lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60; lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour; lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30; lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->Format.nSamplesPerSec; lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n", TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min, lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame); lpTime->u.smpte.sec, lpTime->u.smpte.frame);
@ -248,15 +250,15 @@ LONG LIBAUDIOIO_WaveInit(void)
static const WCHAR ini_out[] = {'A','u','d','i','o','I','O',' ','W','a','v','e','O','u','t',' ','D','r','i','v','e','r',0}; static const WCHAR ini_out[] = {'A','u','d','i','o','I','O',' ','W','a','v','e','O','u','t',' ','D','r','i','v','e','r',0};
static const WCHAR ini_in [] = {'A','u','d','i','o','I','O',' ','W','a','v','e','I','n',' ',' ','D','r','i','v','e','r',0}; static const WCHAR ini_in [] = {'A','u','d','i','o','I','O',' ','W','a','v','e','I','n',' ',' ','D','r','i','v','e','r',0};
TRACE("Init ENTERED rate = %d\n",spec[PLAYBACK].rate); TRACE("Init ENTERED (%d) (%d) rate = %d\n",CLIENT_PLAYBACK,CLIENT_RECORD,spec[CLIENT_PLAYBACK].rate);
spec[RECORD].channels=spec[PLAYBACK].channels=2; spec[CLIENT_RECORD].channels=spec[CLIENT_PLAYBACK].channels=2;
spec[RECORD].max_blocks=spec[PLAYBACK].max_blocks=16; spec[CLIENT_RECORD].max_blocks=spec[CLIENT_PLAYBACK].max_blocks=16;
spec[RECORD].rate=spec[PLAYBACK].rate=44100; spec[CLIENT_RECORD].rate=spec[CLIENT_PLAYBACK].rate=44100;
spec[RECORD].encoding=spec[PLAYBACK].encoding= ENCODE_PCM; spec[CLIENT_RECORD].encoding=spec[CLIENT_PLAYBACK].encoding= ENCODE_PCM;
spec[RECORD].precision=spec[PLAYBACK].precision=16 ; spec[CLIENT_RECORD].precision=spec[CLIENT_PLAYBACK].precision=16 ;
spec[RECORD].endian=spec[PLAYBACK].endian=ENDIAN_INTEL; spec[CLIENT_RECORD].endian=spec[CLIENT_PLAYBACK].endian=ENDIAN_INTEL;
spec[RECORD].disable_threads=spec[PLAYBACK].disable_threads=1; spec[CLIENT_RECORD].disable_threads=spec[CLIENT_PLAYBACK].disable_threads=1;
spec[RECORD].type=spec[PLAYBACK].type=TYPE_SIGNED; /* in 16 bit mode this is what typical PC hardware expects */ spec[CLIENT_RECORD].type=spec[CLIENT_PLAYBACK].type=TYPE_SIGNED; /* in 16 bit mode this is what typical PC hardware expects */
mode = O_WRONLY|O_NDELAY; mode = O_WRONLY|O_NDELAY;
@ -284,17 +286,17 @@ LONG LIBAUDIOIO_WaveInit(void)
* So we don't need to read back and compare. * So we don't need to read back and compare.
*/ */
bytespersmpl = spec[PLAYBACK].precision/8; bytespersmpl = spec[CLIENT_PLAYBACK].precision/8;
WOutDev[0].caps.wChannels = spec[PLAYBACK].channels; WOutDev[0].caps.wChannels = spec[CLIENT_PLAYBACK].channels;
/* Fixme: Libaudioio 0.2 doesn't support balance yet (Libaudioio 0.3 does so this must be fixed later)*/ /* Fixme: Libaudioio 0.2 doesn't support balance yet (Libaudioio 0.3 does so this must be fixed later)*/
/* if (WOutDev[0].caps.wChannels > 1) WOutDev[0].caps.dwSupport |= WAVECAPS_LRVOLUME;*/ /* if (WOutDev[0].caps.wChannels > 1) WOutDev[0].caps.dwSupport |= WAVECAPS_LRVOLUME;*/
TRACE("Init sammplerate= %d\n",spec[PLAYBACK].rate); TRACE("Init sammplerate= %d\n",spec[CLIENT_PLAYBACK].rate);
smplrate = spec[PLAYBACK].rate; smplrate = spec[CLIENT_PLAYBACK].rate;
/* /*
* We have set up the data format to be 16 bit signed in intel format * We have set up the data format to be 16 bit signed in intel format
* For Big Endian machines libaudioio will convert the data to bigendian for us * For Big Endian machines libaudioio will convert the data to bigendian for us
@ -336,12 +338,12 @@ LONG LIBAUDIOIO_WaveInit(void)
WInDev[0].caps.wPid = 0x0001; /* Product ID */ WInDev[0].caps.wPid = 0x0001; /* Product ID */
strcpyW(WInDev[0].caps.szPname, ini_in); strcpyW(WInDev[0].caps.szPname, ini_in);
WInDev[0].caps.dwFormats = 0x00000000; WInDev[0].caps.dwFormats = 0x00000000;
WInDev[0].caps.wChannels = spec[RECORD].channels; WInDev[0].caps.wChannels = spec[CLIENT_RECORD].channels;
WInDev[0].bTriggerSupport = TRUE; /* Maybe :-) */ WInDev[0].bTriggerSupport = TRUE; /* Maybe :-) */
bytespersmpl = spec[RECORD].precision/8; bytespersmpl = spec[CLIENT_RECORD].precision/8;
smplrate = spec[RECORD].rate; smplrate = spec[CLIENT_RECORD].rate;
WInDev[0].caps.dwFormats |= WAVE_FORMAT_4M16; WInDev[0].caps.dwFormats |= WAVE_FORMAT_4M16;
if (WInDev[0].caps.wChannels > 1) if (WInDev[0].caps.wChannels > 1)
@ -419,7 +421,7 @@ static BOOL wodPlayer_WriteFragments(WINE_WAVEOUT* wwo)
LPBYTE lpData; LPBYTE lpData;
int count; int count;
TRACE("wodPlayer_WriteFragments sammplerate= %d\n",spec[PLAYBACK].rate); TRACE("wodPlayer_WriteFragments sammplerate= %d\n",spec[CLIENT_PLAYBACK].rate);
for (;;) { for (;;) {
@ -526,7 +528,7 @@ TRACE("wodPlayer_WriteFragments sammplerate= %d\n",spec[PLAYBACK].rate);
int wodPlayer_Message(WINE_WAVEOUT *wwo, int msg, DWORD param) int wodPlayer_Message(WINE_WAVEOUT *wwo, int msg, DWORD param)
{ {
TRACE("wodPlayerMessage sammplerate= %d msg=%d\n",spec[PLAYBACK].rate,msg); TRACE("wodPlayerMessage sammplerate= %d msg=%d\n",spec[CLIENT_PLAYBACK].rate,msg);
EnterCriticalSection(&wwo->msg_crst); EnterCriticalSection(&wwo->msg_crst);
if ((wwo->msg_tosave == wwo->msg_toget) /* buffer overflow ? */ if ((wwo->msg_tosave == wwo->msg_toget) /* buffer overflow ? */
&& (wwo->messages[wwo->msg_toget].msg)) && (wwo->messages[wwo->msg_toget].msg))
@ -690,19 +692,24 @@ static DWORD CALLBACK wodPlayer(LPVOID pmt)
TRACE("imhere[2] (q=%p p=%p) tc = %08lx\n", wwo->lpQueuePtr, TRACE("imhere[2] (q=%p p=%p) tc = %08lx\n", wwo->lpQueuePtr,
wwo->lpPlayPtr, GetTickCount()); wwo->lpPlayPtr, GetTickCount());
had_msg = FALSE; had_msg = FALSE;
TRACE("Looking for message\n");
while (wodPlayer_RetrieveMessage(wwo, &msg, &param)) { while (wodPlayer_RetrieveMessage(wwo, &msg, &param)) {
had_msg = TRUE; had_msg = TRUE;
TRACE("Processing message\n");
switch (msg) { switch (msg) {
case WINE_WM_PAUSING: case WINE_WM_PAUSING:
TRACE("WINE_WM_PAUSING\n");
wodPlayer_Reset(wwo, uDevID, FALSE); wodPlayer_Reset(wwo, uDevID, FALSE);
wwo->state = WINE_WS_PAUSED; wwo->state = WINE_WS_PAUSED;
SetEvent(wwo->hEvent); SetEvent(wwo->hEvent);
break; break;
case WINE_WM_RESTARTING: case WINE_WM_RESTARTING:
TRACE("WINE_WM_RESTARTING\n");
wwo->state = WINE_WS_PLAYING; wwo->state = WINE_WS_PLAYING;
SetEvent(wwo->hEvent); SetEvent(wwo->hEvent);
break; break;
case WINE_WM_HEADER: case WINE_WM_HEADER:
TRACE("WINE_WM_HEADER\n");
lpWaveHdr = (LPWAVEHDR)param; lpWaveHdr = (LPWAVEHDR)param;
/* insert buffer at the end of queue */ /* insert buffer at the end of queue */
@ -716,10 +723,12 @@ static DWORD CALLBACK wodPlayer(LPVOID pmt)
wwo->state = WINE_WS_PLAYING; wwo->state = WINE_WS_PLAYING;
break; break;
case WINE_WM_RESETTING: case WINE_WM_RESETTING:
TRACE("WINE_WM_RESETTING\n");
wodPlayer_Reset(wwo, uDevID, TRUE); wodPlayer_Reset(wwo, uDevID, TRUE);
SetEvent(wwo->hEvent); SetEvent(wwo->hEvent);
break; break;
case WINE_WM_CLOSING: case WINE_WM_CLOSING:
TRACE("WINE_WM_CLOSING\n");
/* sanity check: this should not happen since the device must have been reset before */ /* sanity check: this should not happen since the device must have been reset before */
if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n"); if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
wwo->hThread = 0; wwo->hThread = 0;
@ -732,6 +741,7 @@ static DWORD CALLBACK wodPlayer(LPVOID pmt)
break; break;
} }
if (wwo->state == WINE_WS_PLAYING) { if (wwo->state == WINE_WS_PLAYING) {
TRACE("Writing Fragment\n");
wodPlayer_WriteFragments(wwo); wodPlayer_WriteFragments(wwo);
} }
wodPlayer_Notify(wwo, uDevID, FALSE); wodPlayer_Notify(wwo, uDevID, FALSE);
@ -740,6 +750,7 @@ static DWORD CALLBACK wodPlayer(LPVOID pmt)
if (!had_msg) { /* if we've received a msg we've just done this so we if (!had_msg) { /* if we've received a msg we've just done this so we
won't repeat it */ won't repeat it */
if (wwo->state == WINE_WS_PLAYING) { if (wwo->state == WINE_WS_PLAYING) {
TRACE("Writing Fragment (entry 2)\n");
wodPlayer_WriteFragments(wwo); wodPlayer_WriteFragments(wwo);
} }
wodPlayer_Notify(wwo, uDevID, FALSE); wodPlayer_Notify(wwo, uDevID, FALSE);
@ -818,7 +829,7 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
if (access(SOUND_DEV, 0) != 0) if (access(SOUND_DEV, 0) != 0)
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
audio = AudioIOOpenX( O_WRONLY|O_NDELAY,&spec[PLAYBACK],&spec[PLAYBACK]); audio = AudioIOOpenX( O_WRONLY|O_NDELAY,&spec[CLIENT_PLAYBACK],&spec[CLIENT_PLAYBACK]);
if (audio == -1) { if (audio == -1) {
WARN("can't open sound device %s (%s)!\n", SOUND_DEV, strerror(errno)); WARN("can't open sound device %s (%s)!\n", SOUND_DEV, strerror(errno));
@ -861,17 +872,17 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
/*Set the sample rate*/ /*Set the sample rate*/
spec[PLAYBACK].rate=sample_rate; spec[CLIENT_PLAYBACK].rate=sample_rate;
/*And the size and signedness*/ /*And the size and signedness*/
spec[PLAYBACK].precision=(wwo->format.wBitsPerSample ); spec[CLIENT_PLAYBACK].precision=(wwo->format.wBitsPerSample );
if (spec[PLAYBACK].precision==16) spec[PLAYBACK].type=TYPE_SIGNED; else spec[PLAYBACK].type=TYPE_UNSIGNED; if (spec[CLIENT_PLAYBACK].precision==16) spec[CLIENT_PLAYBACK].type=TYPE_SIGNED; else spec[CLIENT_PLAYBACK].type=TYPE_UNSIGNED;
spec[PLAYBACK].channels=(wwo->format.wf.nChannels); spec[CLIENT_PLAYBACK].channels=(wwo->format.wf.nChannels);
spec[PLAYBACK].encoding=ENCODE_PCM; spec[CLIENT_PLAYBACK].encoding=ENCODE_PCM;
spec[PLAYBACK].endian=ENDIAN_INTEL; spec[CLIENT_PLAYBACK].endian=ENDIAN_INTEL;
spec[PLAYBACK].max_blocks=16; /*FIXME This is the libaudioio equivalent to fragments, it controls latency*/ spec[CLIENT_PLAYBACK].max_blocks=16; /*FIXME This is the libaudioio equivalent to fragments, it controls latency*/
audio = AudioIOOpenX( O_WRONLY|O_NDELAY,&spec[PLAYBACK],&spec[PLAYBACK]); audio = AudioIOOpenX( O_WRONLY|O_NDELAY,&spec[CLIENT_PLAYBACK],&spec[CLIENT_PLAYBACK]);
if (audio == -1) { if (audio == -1) {
WARN("can't open sound device %s (%s)!\n", SOUND_DEV, strerror(errno)); WARN("can't open sound device %s (%s)!\n", SOUND_DEV, strerror(errno));
@ -892,6 +903,7 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
InitializeCriticalSection(&wwo->msg_crst); InitializeCriticalSection(&wwo->msg_crst);
if (!(dwFlags & WAVE_DIRECTSOUND)) { if (!(dwFlags & WAVE_DIRECTSOUND)) {
TRACE("Starting wodPlayer Thread\n");
wwo->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); wwo->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD)wDevID, 0, &(wwo->dwThreadID)); wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD)wDevID, 0, &(wwo->dwThreadID));
if (wwo->hThread) if (wwo->hThread)
@ -1927,7 +1939,7 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
} }
if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED; if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
audio = AudioIOOpenX( O_RDONLY|O_NDELAY, &spec[RECORD],&spec[RECORD]); audio = AudioIOOpenX( O_RDONLY|O_NDELAY, &spec[CLIENT_RECORD],&spec[CLIENT_RECORD]);
if (audio == -1) { if (audio == -1) {
WARN("can't open sound device %s (%s)!\n", SOUND_DEV, strerror(errno)); WARN("can't open sound device %s (%s)!\n", SOUND_DEV, strerror(errno));
return MMSYSERR_ALLOCATED; return MMSYSERR_ALLOCATED;
@ -1954,10 +1966,10 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
wwi->format.wf.nChannels; wwi->format.wf.nChannels;
} }
spec[RECORD].rate=sample_rate = wwi->format.wf.nSamplesPerSec; spec[CLIENT_RECORD].rate=sample_rate = wwi->format.wf.nSamplesPerSec;
dsp_stereo = ((spec[RECORD].channels=wwi->format.wf.nChannels) > 1) ? TRUE : FALSE; dsp_stereo = ((spec[CLIENT_RECORD].channels=wwi->format.wf.nChannels) > 1) ? TRUE : FALSE;
spec[RECORD].precision= wwi->format.wBitsPerSample; spec[CLIENT_RECORD].precision= wwi->format.wBitsPerSample;
spec[RECORD].type=(spec[RECORD].precision==16)?TYPE_SIGNED:TYPE_UNSIGNED; spec[CLIENT_RECORD].type=(spec[CLIENT_RECORD].precision==16)?TYPE_SIGNED:TYPE_UNSIGNED;
/* This is actually hand tuned to work so that my SB Live: /* This is actually hand tuned to work so that my SB Live:
* - does not skip * - does not skip