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