Fix segmentation fault caused by incorrect referencing of client audio
format specifications array.
This commit is contained in:
parent
fc40dcf985
commit
dc1ceb95cb
|
@ -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, ¶m)) {
|
while (wodPlayer_RetrieveMessage(wwo, &msg, ¶m)) {
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue