wodOpen() should return MMSYSERR_ALLOCATED if the device is already allocated. Allow for multiple audio devices. Fix wodPlayer_reset as with aRts we cannot cancel audio data already written to the server. Rename some functions. Cleanup unused code.
diff --git a/dlls/winmm/winearts/arts.c b/dlls/winmm/winearts/arts.c index f49ceb3..eb10352 100644 --- a/dlls/winmm/winearts/arts.c +++ b/dlls/winmm/winearts/arts.c
@@ -75,7 +75,7 @@ /* ARTS_MidiInit(); FIXME: no midi support in artsc so we don't have any in the arts driver */ return 1; - case DRV_FREE: return ARTS_CloseDevice(); + case DRV_FREE: return ARTS_WaveClose(); case DRV_OPEN: return ARTS_drvOpen((LPSTR)dwParam1); case DRV_CLOSE: return ARTS_drvClose(dwDevID); case DRV_ENABLE: return 1;
diff --git a/dlls/winmm/winearts/arts.h b/dlls/winmm/winearts/arts.h index b090053..6cffa5e 100644 --- a/dlls/winmm/winearts/arts.h +++ b/dlls/winmm/winearts/arts.h
@@ -29,6 +29,6 @@ #endif extern LONG ARTS_WaveInit(void); -extern LONG ARTS_CloseDevice(void); +extern LONG ARTS_WaveClose(void); #endif /* __WINE_ARTS_H */
diff --git a/dlls/winmm/winearts/audio.c b/dlls/winmm/winearts/audio.c index 9c84240..0db2c8a 100644 --- a/dlls/winmm/winearts/audio.c +++ b/dlls/winmm/winearts/audio.c
@@ -22,13 +22,18 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/* NOTE: + * with arts we cannot stop the audio that is already in + * the servers buffer, so to reduce delays during starting + * and stoppping of audio streams adjust the + * audio buffer size in the kde control center or in the + * artsd startup script + * * FIXME: * pause in waveOut does not work correctly in loop mode * * TODO: * implement wave-in support with artsc - * only one sound card is currently supported, add more */ /*#define EMULATE_SB16*/ @@ -60,10 +65,10 @@ #include <artsc.h> -#define BUFFER_SIZE 16 * 1024 +#define BUFFER_SIZE 16 * 1024 #define SPACE_THRESHOLD 5 * 1024 -#define MAX_WAVEOUTDRV (1) +#define MAX_WAVEOUTDRV (10) /* state diagram for waveOut writing: * @@ -221,19 +226,45 @@ } /****************************************************************** - * ARTS_OpenDevice + * ARTS_CloseDevice + * */ -static int ARTS_OpenDevice(void) +void ARTS_CloseDevice(WINE_WAVEOUT* wwo) +{ + arts_close_stream(wwo->play_stream); /* close the arts stream */ + wwo->play_stream = (arts_stream_t*)-1; + + /* free up the buffer we use for volume and reset the size */ + if(wwo->sound_buffer) + HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); + + wwo->buffer_size = 0; +} + +/****************************************************************** + * ARTS_Init + */ +static int ARTS_Init(void) { return arts_init(); /* initialize arts and return errorcode */ } /****************************************************************** - * ARTS_CloseDevice - * + * ARTS_WaveClose */ -LONG ARTS_CloseDevice(void) +LONG ARTS_WaveClose(void) { + int iDevice; + + /* close all open devices */ + for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++) + { + if(WOutDev[iDevice].play_stream != (arts_stream_t*)-1) + { + ARTS_CloseDevice(&WOutDev[iDevice]); + } + } + arts_free(); /* free up arts */ return 1; } @@ -250,54 +281,53 @@ TRACE("called\n"); - /* start with output device */ + if ((errorcode = ARTS_Init()) < 0) + { + ERR("arts_init() failed (%d)\n", errorcode); + return -1; + } /* initialize all device handles to -1 */ for (i = 0; i < MAX_WAVEOUTDRV; ++i) - WOutDev[i].play_stream = (arts_stream_t*)-1; - - /* FIXME: only one device is supported */ - memset(&WOutDev[0].caps, 0, sizeof(WOutDev[0].caps)); - - if ((errorcode = ARTS_OpenDevice()) < 0) { - ERR("arts_init() failed (%d)\n", errorcode); - return -1; - } - + WOutDev[i].play_stream = (arts_stream_t*)-1; + memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps)); /* zero out + caps values */ /* FIXME: some programs compare this string against the content of the registry * for MM drivers. The names have to match in order for the program to work * (e.g. MS win9x mplayer.exe) */ #ifdef EMULATE_SB16 - WOutDev[0].caps.wMid = 0x0002; - WOutDev[0].caps.wPid = 0x0104; - strcpy(WOutDev[0].caps.szPname, "SB16 Wave Out"); + WOutDev[i].caps.wMid = 0x0002; + WOutDev[i].caps.wPid = 0x0104; + strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out"); #else - WOutDev[0].caps.wMid = 0x00FF; /* Manufac ID */ - WOutDev[0].caps.wPid = 0x0001; /* Product ID */ - /* strcpy(WOutDev[0].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/ - strcpy(WOutDev[0].caps.szPname, "CS4236/37/38"); + WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */ + WOutDev[i].caps.wPid = 0x0001; /* Product ID */ + /* strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/ + strcpy(WOutDev[i].caps.szPname, "CS4236/37/38"); #endif - WOutDev[0].caps.vDriverVersion = 0x0100; - WOutDev[0].caps.dwFormats = 0x00000000; - WOutDev[0].caps.dwSupport = WAVECAPS_VOLUME; + WOutDev[i].caps.vDriverVersion = 0x0100; + WOutDev[i].caps.dwFormats = 0x00000000; + WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME; - WOutDev[0].caps.wChannels = 2; - WOutDev[0].caps.dwSupport |= WAVECAPS_LRVOLUME; + WOutDev[i].caps.wChannels = 2; + WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4M08; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4S08; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4S16; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_4M16; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2M08; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2S08; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2M16; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_2S16; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1M08; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1S08; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1M16; - WOutDev[0].caps.dwFormats |= WAVE_FORMAT_1S16; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16; + WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16; + } + return 0; } @@ -450,6 +480,7 @@ wwo->dwPlayedTotal = wwo->dwWrittenTotal - (wwo->dwBufferSize - arts_stream_get(wwo->play_stream, ARTS_P_BUFFER_SPACE)); + return TRUE; } @@ -530,10 +561,6 @@ wwo->format.wBitsPerSample * wwo->format.wf.nChannels) /1000); - /* FIXME: this is a hack since the waitvalue we calculate is too -large for some reason.... */ - waitvalue/=4; - TRACE("wait value of %d\n", waitvalue); /* return the time left to play the buffer */ @@ -689,15 +716,10 @@ { wodUpdatePlayedTotal(wwo); - /* updates current notify list */ - wodPlayer_NotifyCompletions(wwo, FALSE); + wodPlayer_NotifyCompletions(wwo, FALSE); /* updates current notify list */ - /* flush all possible output */ - /* close and open the stream to end the playback and prepare for - new playback */ - arts_close_stream(wwo->play_stream); - wwo->play_stream = arts_play_stream(wwo->format.wf.nSamplesPerSec, - wwo->format.wBitsPerSample, wwo->format.wf.nChannels, "winearts"); + /* we aren't able to flush any data that has already been written */ + /* to arts, otherwise we would do the flushing here */ if (reset) { enum win_wm_message msg; @@ -741,19 +763,9 @@ wwo->dwPartialOffset = 0; wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */ } else { - LPWAVEHDR ptr; - DWORD sz = wwo->dwPartialOffset; - - /* reset all the data as if we had written only up to lpPlayedTotal bytes */ - /* compute the max size playable from lpQueuePtr */ - for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext) { - sz += ptr->dwBufferLength; - } - /* because the reset lpPlayPtr will be lpQueuePtr */ - if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("grin\n"); - wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal); - wwo->dwWrittenTotal = wwo->dwPlayedTotal; - wwo->lpPlayPtr = wwo->lpQueuePtr; + /* the data already written is going to be played, so take */ + /* this fact into account here */ + wwo->dwPlayedTotal = wwo->dwWrittenTotal; } wwo->state = WINE_WS_PAUSED; } @@ -940,6 +952,13 @@ return MMSYSERR_BADDEVICEID; } + /* if this device is already open tell the app that it is allocated */ + if(WOutDev[wDevID].play_stream != (arts_stream_t*)-1) + { + TRACE("device already allocated\n"); + return MMSYSERR_ALLOCATED; + } + /* only PCM format is supported so far... */ if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM || lpDesc->lpFormat->nChannels == 0 || @@ -990,8 +1009,7 @@ was set to for future use */ wwo->dwBufferSize = arts_stream_set(wwo->play_stream, ARTS_P_BUFFER_SIZE, BUFFER_SIZE); - TRACE("Tried to set BUFFER_SIZE of %d, wwo->dwBufferSize is actually - %ld\n", BUFFER_SIZE, wwo->dwBufferSize); + TRACE("Tried to set BUFFER_SIZE of %d, wwo->dwBufferSize is actually %ld\n", BUFFER_SIZE, wwo->dwBufferSize); wwo->dwPlayedTotal = 0; wwo->dwWrittenTotal = 0; @@ -1049,14 +1067,8 @@ ARTS_DestroyRingMessage(&wwo->msgRing); - arts_close_stream(wwo->play_stream); /* close the arts stream */ + ARTS_CloseDevice(wwo); /* close the stream and clean things up */ - /* free up the buffer we use for volume and reset the size */ - if(wwo->sound_buffer) - HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); - wwo->buffer_size = 0; - - wwo->play_stream = (arts_stream_t*)-1; ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L); } return ret; @@ -1330,10 +1342,7 @@ */ static DWORD wodGetNumDevs(void) { - DWORD ret = 1; - - /* FIXME: For now, only one sound device (SOUND_DEV) is allowed */ - return ret; + return MAX_WAVEOUTDRV; } /************************************************************************** @@ -1381,30 +1390,6 @@ /*======================================================================* * Low level DSOUND implementation * *======================================================================*/ - -typedef struct IDsDriverImpl IDsDriverImpl; -typedef struct IDsDriverBufferImpl IDsDriverBufferImpl; - -struct IDsDriverImpl -{ - /* IUnknown fields */ - ICOM_VFIELD(IDsDriver); - DWORD ref; - /* IDsDriverImpl fields */ - UINT wDevID; - IDsDriverBufferImpl*primary; -}; - -struct IDsDriverBufferImpl -{ - /* IUnknown fields */ - ICOM_VFIELD(IDsDriverBuffer); - DWORD ref; - /* IDsDriverBufferImpl fields */ - IDsDriverImpl* drv; - DWORD buflen; -}; - static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv) { /* we can't perform memory mapping as we don't have a file stream