Index: /trunk/src/VBox/Devices/Audio/dsound_template.h
===================================================================
--- /trunk/src/VBox/Devices/Audio/dsound_template.h	(revision 53416)
+++ /trunk/src/VBox/Devices/Audio/dsound_template.h	(revision 53417)
@@ -169,19 +169,10 @@
 static void dsound_fini_out (HWVoiceOut *hw)
 {
-    HRESULT hr;
     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
-
-    if (ds->FIELD) {
-        hr = glue (IFACE, _Stop) (ds->FIELD);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not stop " NAME "\n");
-        }
-
-        hr = glue (IFACE, _Release) (ds->FIELD);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not release " NAME "\n");
-        }
-        ds->FIELD = NULL;
-    }
+    dsoundPlayClose (ds);
+    ds->old_pos = 0;
+    ds->first_time = 1;
+    ds->playback_buffer_size = 0;
+    memset (&ds->as, 0, sizeof(ds->as));
 }
 #endif
@@ -194,4 +185,5 @@
     ds->last_read_pos = 0;
     ds->capture_buffer_size = 0;
+    ds->dsound_capture = NULL;
     ds->dsound_capture_buffer = NULL;
     ds->as = *as;
@@ -209,89 +201,21 @@
 static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as)
 {
-    int err;
-    HRESULT hr;
-    dsound *s = &glob_dsound;
-    WAVEFORMATEX wfx;
-    audsettings_t obt_as;
-    const char *typ = "DAC";
     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
-    DSBUFFERDESC bd;
-    DSBCAPS bc;
-
-    err = waveformat_from_audio_settings (&wfx, as);
-    if (err) {
-        return -1;
-    }
-
-    memset (&bd, 0, sizeof (bd));
-    bd.dwSize = sizeof (bd);
-    bd.lpwfxFormat = &wfx;
-    bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
-    bd.dwBufferBytes = conf.bufsize_out;
-    hr = IDirectSound_CreateSoundBuffer (
-        s->dsound,
-        &bd,
-        &ds->dsound_buffer,
-        NULL
-        );
-
-    if (FAILED (hr)) {
-        dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
-        return -1;
-    }
-
-    hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
-    if (FAILED (hr)) {
-        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
-        goto fail0;
-    }
-
-#ifdef DEBUG_DSOUND
-    dolog (NAME "\n");
-    print_wave_format (&wfx);
-#endif
-
-    memset (&bc, 0, sizeof (bc));
-    bc.dwSize = sizeof (bc);
-
-    hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
-    if (FAILED (hr)) {
-        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
-        goto fail0;
-    }
-
-    err = waveformat_to_audio_settings (&wfx, &obt_as);
-    if (err) {
-        goto fail0;
-    }
-
+
+    ds->dsound = NULL;
+    ds->dsound_buffer = NULL;
+    ds->old_pos = 0;
     ds->first_time = 1;
-    obt_as.endianness = 0;
-    audio_pcm_init_info (&hw->info, &obt_as);
-
-    if (bc.dwBufferBytes & hw->info.align) {
-        dolog (
-            "GetCaps returned misaligned buffer size %ld, alignment %d\n",
-            bc.dwBufferBytes, hw->info.align + 1
-            );
-    }
-    hw->samples = bc.dwBufferBytes >> hw->info.shift;
-
-#ifdef DEBUG_DSOUND
-    dolog ("caps %ld, desc %ld\n",
-           bc.dwBufferBytes, bd.dwBufferBytes);
-
-    dolog ("bufsize %d, freq %d, chan %d, bits %d, sign %d\n",
-           hw->samples << hw->info.shift,
-           hw->info.freq,
-           hw->info.nchannels,
-           hw->info.bits,
-           hw->info.sign);
-#endif
-    return 0;
-
- fail0:
-    glue (dsound_fini_, TYPE) (hw);
-    return -1;
+    ds->playback_buffer_size = 0;
+    ds->as = *as;
+
+    /* Init default settings. */
+    audio_pcm_init_info (&hw->info, &ds->as);
+    hw->samples = conf.bufsize_out >> hw->info.shift;
+
+    /* Try to open playback in case the device is already there. */
+    dsoundPlayOpen (ds);
+
+    return 0;
 }
 #endif
Index: /trunk/src/VBox/Devices/Audio/dsoundaudio.c
===================================================================
--- /trunk/src/VBox/Devices/Audio/dsoundaudio.c	(revision 53416)
+++ /trunk/src/VBox/Devices/Audio/dsoundaudio.c	(revision 53417)
@@ -60,6 +60,4 @@
 #include "audio_int.h"
 
-/* #define DEBUG_DSOUND */
-
 #define DSLOGF(a) do { LogRel2(a); } while(0)
 #define DSLOGREL(a)                 \
@@ -79,8 +77,6 @@
     int restore_retries;
     int getstatus_retries;
-    int set_primary;
     int bufsize_in;
     int bufsize_out;
-    audsettings_t settings;
     int latency_millis;
     char *device_guid_out;
@@ -90,12 +86,6 @@
     1,
     1,
-    0,
     16384,
     16384,
-    {
-        44100,
-        2,
-        AUD_FMT_S16
-    },
     10,
     NULL,
@@ -104,8 +94,6 @@
 
 typedef struct {
-    LPDIRECTSOUND dsound;
-    LPDIRECTSOUNDCAPTURE dsound_capture;
-    LPDIRECTSOUNDBUFFER dsound_primary_buffer;
-    audsettings_t settings;
+    RTUUID devguid_play;
+    LPCGUID devguidp_play;
     RTUUID devguid_capture;
     LPCGUID devguidp_capture;
@@ -116,12 +104,10 @@
 typedef struct {
     HWVoiceOut hw;
+    LPDIRECTSOUND dsound;
     LPDIRECTSOUNDBUFFER dsound_buffer;
     DWORD old_pos;
     int first_time;
-#ifdef DEBUG_DSOUND
-    DWORD old_ppos;
-    DWORD played;
-    DWORD mixed;
-#endif
+    int playback_buffer_size;
+    audsettings_t as;
 } DSoundVoiceOut;
 
@@ -130,8 +116,11 @@
     int last_read_pos;
     int capture_buffer_size;
+    LPDIRECTSOUNDCAPTURE dsound_capture;
     LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
     audsettings_t as;
     HRESULT hr_last_run_in;
 } DSoundVoiceIn;
+
+static void dsound_clear_sample (DSoundVoiceOut *ds);
 
 static void dsound_log_hresult (HRESULT hr)
@@ -313,17 +302,4 @@
 }
 
-#ifdef DEBUG_DSOUND
-static void print_wave_format (WAVEFORMATEX *wfx)
-{
-    dolog ("tag             = %d\n", wfx->wFormatTag);
-    dolog ("nChannels       = %d\n", wfx->nChannels);
-    dolog ("nSamplesPerSec  = %ld\n", wfx->nSamplesPerSec);
-    dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);
-    dolog ("nBlockAlign     = %d\n", wfx->nBlockAlign);
-    dolog ("wBitsPerSample  = %d\n", wfx->wBitsPerSample);
-    dolog ("cbSize          = %d\n", wfx->cbSize);
-}
-#endif
-
 static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
 {
@@ -342,10 +318,10 @@
 
         default:
-            dsound_logerr (hr, "Could not restore playback buffer\n");
+            DSLOGREL(("DSound: restore playback buffer %Rhrc\n", hr));
             return -1;
         }
     }
 
-    dolog ("%d attempts to restore playback buffer failed\n", i);
+    DSLOGF(("DSound: %d attempts to restore playback buffer failed\n", i));
     return -1;
 }
@@ -444,39 +420,305 @@
 }
 
-static void dsoundCaptureInterfaceRelease (dsound *s)
-{
-    if (s->dsound_capture) {
-        HRESULT hr = IDirectSoundCapture_Release (s->dsound_capture);
+/*
+ * DirectSound playback
+ */
+
+static void dsoundPlayInterfaceRelease (DSoundVoiceOut *ds)
+{
+    if (ds->dsound) {
+        IDirectSound_Release (ds->dsound);
+        ds->dsound = NULL;
+    }
+}
+
+static int dsoundPlayInterfaceCreate (DSoundVoiceOut *ds)
+{
+    dsound *s = &glob_dsound;
+
+    HRESULT hr;
+
+    if (ds->dsound != NULL) {
+        DSLOGF(("DSound: DirectSound instance already exists\n"));
+        return 0;
+    }
+
+    hr = CoCreateInstance (&CLSID_DirectSound, NULL, CLSCTX_ALL,
+                           &IID_IDirectSound, (void **) &ds->dsound);
+    if (FAILED (hr)) {
+        DSLOGREL(("DSound: DirectSound create instance %Rhrc\n", hr));
+    }
+    else {
+        hr = IDirectSound_Initialize (ds->dsound, s->devguidp_play);
+        if (SUCCEEDED(hr)) {
+            HWND hwnd = GetDesktopWindow ();
+            hr = IDirectSound_SetCooperativeLevel (ds->dsound, hwnd, DSSCL_PRIORITY);
+            if (FAILED (hr)) {
+                DSLOGREL(("DSound: set cooperative level for window %p %Rhrc\n", hwnd, hr));
+            }
+        }
         if (FAILED (hr)) {
-            DSLOGF(("DSound: DirectSoundCapture release %Rhrc\n", hr));
-        }
-        s->dsound_capture = NULL;
-    }
-}
-
-static int dsoundCaptureInterfaceCreate (dsound *s)
-{
+            if (hr == DSERR_NODRIVER) {
+                DSLOGREL(("DSound: DirectSound playback is currently unavailable\n"));
+            }
+            else {
+                DSLOGREL(("DSound: DirectSound initialize %Rhrc\n", hr));
+            }
+            dsoundPlayInterfaceRelease (ds);
+        }
+    }
+
+    return SUCCEEDED (hr)? 0: -1;
+}
+
+static void dsoundPlayClose (DSoundVoiceOut *ds)
+{
+    dsound *s = &glob_dsound;
+
     HRESULT hr;
 
-    if (s->dsound_capture != NULL) {
+    DSLOGF(("DSound: playback close %p buffer %p\n", ds, ds->dsound_buffer));
+
+    if (ds->dsound_buffer) {
+        hr = IDirectSoundBuffer_Stop (ds->dsound_buffer);
+        if (FAILED (hr)) {
+            DSLOGREL(("DSound: playback close Stop %Rhrc\n", hr));
+        }
+
+        IDirectSoundBuffer_Release (ds->dsound_buffer);
+        ds->dsound_buffer = NULL;
+    }
+
+    dsoundPlayInterfaceRelease (ds);
+}
+
+static int dsoundPlayOpen (DSoundVoiceOut *ds)
+{
+    dsound *s = &glob_dsound;
+
+    int err;
+    HRESULT hr;
+    WAVEFORMATEX wfx;
+    DSBUFFERDESC bd;
+    DSBCAPS bc;
+
+    DSLOGF(("DSound: playback open %p size %d samples, freq %d, chan %d, bits %d, sign %d\n",
+            ds,
+            ds->hw.samples,
+            ds->hw.info.freq,
+            ds->hw.info.nchannels,
+            ds->hw.info.bits,
+            ds->hw.info.sign));
+
+    if (ds->dsound_buffer != NULL) {
+        /* Should not happen but be forgiving. */
+        DSLOGREL(("DSound: DirectSoundBuffer already exists\n"));
+        dsoundPlayClose (ds);
+    }
+
+    err = waveformat_from_audio_settings (&wfx, &ds->as);
+    if (err) {
+        return err;
+    }
+
+    err = dsoundPlayInterfaceCreate (ds);
+    if (err) {
+        return err;
+    }
+
+    memset (&bd, 0, sizeof (bd));
+    bd.dwSize = sizeof (bd);
+    bd.lpwfxFormat = &wfx;
+    bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
+    bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift;
+    hr = IDirectSound_CreateSoundBuffer (ds->dsound,
+                                         &bd, &ds->dsound_buffer, NULL);
+    if (FAILED (hr)) {
+        DSLOGREL(("DSound: playback CreateSoundBuffer %Rhrc\n", hr));
+        goto fail0;
+    }
+
+    /* Query the actual parameters. */
+
+    hr = IDirectSoundBuffer_GetFormat (ds->dsound_buffer, &wfx, sizeof (wfx), NULL);
+    if (FAILED (hr)) {
+        DSLOGREL(("DSound: playback GetFormat %Rhrc\n", hr));
+        goto fail0;
+    }
+
+    memset (&bc, 0, sizeof (bc));
+    bc.dwSize = sizeof (bc);
+    hr = IDirectSoundBuffer_GetCaps (ds->dsound_buffer, &bc);
+    if (FAILED (hr)) {
+        DSLOGREL(("DSound: playback GetCaps %Rhrc\n", hr));
+        goto fail0;
+    }
+
+    DSLOGF(("DSound: playback format: size %d bytes\n"
+            "  tag             = %d\n"
+            "  nChannels       = %d\n"
+            "  nSamplesPerSec  = %d\n"
+            "  nAvgBytesPerSec = %d\n"
+            "  nBlockAlign     = %d\n"
+            "  wBitsPerSample  = %d\n"
+            "  cbSize          = %d\n",
+            bc.dwBufferBytes,
+            wfx.wFormatTag,
+            wfx.nChannels,
+            wfx.nSamplesPerSec,
+            wfx.nAvgBytesPerSec,
+            wfx.nBlockAlign,
+            wfx.wBitsPerSample,
+            wfx.cbSize));
+
+    if (bc.dwBufferBytes & ds->hw.info.align) {
+        DSLOGREL(("DSound: playback GetCaps returned misaligned buffer size %ld, alignment %d\n",
+                  bc.dwBufferBytes, ds->hw.info.align + 1));
+    }
+
+    if (ds->hw.samples != 0 && ds->hw.samples != (bc.dwBufferBytes >> ds->hw.info.shift)) {
+        DSLOGREL(("DSound: playback buffer size mismatch dsound %d, hw %d bytes\n",
+                  bc.dwBufferBytes, ds->hw.samples << ds->hw.info.shift));
+    }
+
+    /* Initial state.
+     * dsoundPlayStart initializes part of it to make sure that Stop/Start continues with a correct
+     * playback buffer position.
+     */
+    ds->playback_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift;
+    DSLOGF(("DSound: playback open playback_buffer_size %d\n", ds->playback_buffer_size));
+
+    return 0;
+
+ fail0:
+    dsoundPlayClose (ds);
+    return -1;
+}
+
+static int dsoundPlayGetStatus (DSoundVoiceOut *ds, DWORD *statusp)
+{
+    HRESULT hr;
+    DWORD status;
+    int i;
+
+    if (ds->dsound_buffer != NULL) {
+        for (i = 0; i < RT_MAX(conf.getstatus_retries, 1); ++i) {
+            hr = IDirectSoundBuffer_GetStatus (ds->dsound_buffer, &status);
+            if (FAILED (hr)) {
+                DSLOGF(("DSound: playback start GetStatus %Rhrc\n", hr));
+                break;
+            }
+
+            if ((status & DSBSTATUS_BUFFERLOST) == 0) {
+                break;
+            }
+
+            if (dsound_restore_out (ds->dsound_buffer)) {
+                hr = E_FAIL;
+                break;
+            }
+        }
+    }
+    else
+    {
+        hr = E_FAIL;
+    }
+
+    if (SUCCEEDED (hr)) {
+        *statusp = status;
+        return 0;
+    }
+    return -1;
+}
+
+static void dsoundPlayStop (DSoundVoiceOut *ds)
+{
+    HRESULT hr;
+    DWORD status;
+
+    if (ds->dsound_buffer != NULL) {
+        /* This performs some restore, so call it anyway and ignore result. */
+        dsoundPlayGetStatus (ds, &status);
+
+        hr = IDirectSoundBuffer_Stop (ds->dsound_buffer);
+        if (FAILED (hr)) {
+            DSLOGF(("DSound: stop playback buffer %Rhrc\n", hr));
+        }
+    }
+}
+
+static int dsoundPlayStart (DSoundVoiceOut *ds)
+{
+    HRESULT hr;
+    DWORD status;
+
+    if (ds->dsound_buffer != NULL) {
+        if (dsoundPlayGetStatus (ds, &status)) {
+            DSLOGF(("DSound: playback start GetStatus failed\n"));
+            hr = E_FAIL;
+        }
+        else {
+            if (status & DSBSTATUS_PLAYING) {
+                DSLOGF(("DSound: already playing\n"));
+            }
+            else {
+                dsound_clear_sample (ds);
+
+                /* Reinit the playback buffer position. */
+                ds->first_time = 1;
+
+                DSLOGF(("DSound: playback start\n"));
+
+                hr = IDirectSoundBuffer_Play (ds->dsound_buffer, 0, 0, DSBPLAY_LOOPING);
+                if (FAILED (hr)) {
+                    DSLOGREL(("DSound: playback start %Rhrc\n", hr));
+                }
+            }
+        }
+    }
+    else {
+        hr = E_FAIL;
+    }
+
+    return SUCCEEDED (hr)? 0: -1;
+}
+
+/*
+ * DirectSoundCapture
+ */
+
+static void dsoundCaptureInterfaceRelease (DSoundVoiceIn *ds)
+{
+    if (ds->dsound_capture) {
+        IDirectSoundCapture_Release (ds->dsound_capture);
+        ds->dsound_capture = NULL;
+    }
+}
+
+static int dsoundCaptureInterfaceCreate (DSoundVoiceIn *ds)
+{
+    dsound *s = &glob_dsound;
+
+    HRESULT hr;
+
+    if (ds->dsound_capture != NULL) {
         DSLOGF(("DSound: DirectSoundCapture instance already exists\n"));
-        return -1;
+        return 0;
     }
 
     hr = CoCreateInstance (&CLSID_DirectSoundCapture, NULL, CLSCTX_ALL,
-                           &IID_IDirectSoundCapture, (void **) &s->dsound_capture);
+                           &IID_IDirectSoundCapture, (void **) &ds->dsound_capture);
     if (FAILED (hr)) {
         DSLOGREL(("DSound: DirectSoundCapture create instance %Rhrc\n", hr));
     }
     else {
-        hr = IDirectSoundCapture_Initialize (s->dsound_capture, s->devguidp_capture);
+        hr = IDirectSoundCapture_Initialize (ds->dsound_capture, s->devguidp_capture);
         if (FAILED (hr)) {
             if (hr == DSERR_NODRIVER) {
-                DSLOGREL(("DSound: DirectSoundCapture not available\n"));
+                DSLOGREL(("DSound: DirectSound capture is currently unavailable\n"));
             }
             else {
                 DSLOGREL(("DSound: DirectSoundCapture initialize %Rhrc\n", hr));
             }
-            dsoundCaptureInterfaceRelease (s);
+            dsoundCaptureInterfaceRelease (ds);
         }
     }
@@ -497,12 +739,9 @@
         }
 
-        hr = IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer);
-        if (FAILED (hr)) {
-            DSLOGF(("DSound: close capture buffer release %Rhrc\n", hr));
-        }
+        IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer);
         ds->dsound_capture_buffer = NULL;
     }
 
-    dsoundCaptureInterfaceRelease (s);
+    dsoundCaptureInterfaceRelease (ds);
 }
 
@@ -537,5 +776,5 @@
     }
 
-    err = dsoundCaptureInterfaceCreate (s);
+    err = dsoundCaptureInterfaceCreate (ds);
     if (err) {
         return err;
@@ -546,5 +785,5 @@
     bd.lpwfxFormat = &wfx;
     bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift;
-    hr = IDirectSoundCapture_CreateCaptureBuffer (s->dsound_capture,
+    hr = IDirectSoundCapture_CreateCaptureBuffer (ds->dsound_capture,
                                                   &bd, &ds->dsound_capture_buffer, NULL);
 
@@ -609,5 +848,5 @@
     ds->last_read_pos = cpos >> ds->hw.info.shift;
     ds->capture_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift;
-    DSLOGF(("DSound: open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size));
+    DSLOGF(("DSound: capture open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size));
 
     ds->hr_last_run_in = S_OK;
@@ -645,4 +884,7 @@
             }
             else {
+                /** @todo Fill the capture beffer with silence here. */
+
+                DSLOGF(("DSound: capture start\n"));
                 hr = IDirectSoundCaptureBuffer_Start (ds->dsound_capture_buffer, DSCBSTART_LOOPING);
                 if (FAILED (hr)) {
@@ -664,42 +906,4 @@
 #undef DSBTYPE_IN
 
-static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp)
-{
-    HRESULT hr;
-    int i;
-
-    for (i = 0; i < conf.getstatus_retries; ++i) {
-        hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not get playback buffer status\n");
-            return -1;
-        }
-
-        if (*statusp & DSERR_BUFFERLOST) {
-            if (dsound_restore_out (dsb)) {
-                return -1;
-            }
-            continue;
-        }
-        break;
-    }
-
-    return 0;
-}
-
-static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,
-                                 DWORD *statusp)
-{
-    HRESULT hr;
-
-    hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp);
-    if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not get capture buffer status\n");
-        return -1;
-    }
-
-    return 0;
-}
-
 static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
 {
@@ -719,5 +923,4 @@
     if (src_len1) {
         hw->clip (dst, src1, src_len1);
-//        mixeng_sniff_and_clear (hw, src1, dst, src_len1);
     }
 
@@ -725,5 +928,4 @@
         dst = advance (dst, src_len1 << hw->info.shift);
         hw->clip (dst, src2, src_len2);
-//        mixeng_sniff_and_clear (hw, src2, dst, src_len2);
     }
 
@@ -731,5 +933,5 @@
 }
 
-static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
+static void dsound_clear_sample (DSoundVoiceOut *ds)
 {
     int err;
@@ -738,8 +940,8 @@
 
     err = dsound_lock_out (
-        dsb,
-        &hw->info,
+        ds->dsound_buffer,
+        &ds->hw.info,
         0,
-        hw->samples << hw->info.shift,
+        ds->playback_buffer_size << ds->hw.info.shift,
         &p1, &p2,
         &blen1, &blen2,
@@ -750,184 +952,37 @@
     }
 
-    len1 = blen1 >> hw->info.shift;
-    len2 = blen2 >> hw->info.shift;
-
-#ifdef DEBUG_DSOUND
-    dolog ("clear %p,%ld,%ld %p,%ld,%ld\n",
-           p1, blen1, len1,
-           p2, blen2, len2);
-#endif
+    len1 = blen1 >> ds->hw.info.shift;
+    len2 = blen2 >> ds->hw.info.shift;
 
     if (p1 && len1) {
-        audio_pcm_info_clear_buf (&hw->info, p1, len1);
+        audio_pcm_info_clear_buf (&ds->hw.info, p1, len1);
     }
 
     if (p2 && len2) {
-        audio_pcm_info_clear_buf (&hw->info, p2, len2);
-    }
-
-    dsound_unlock_out (dsb, p1, p2, blen1, blen2);
-}
-
-static void dsound_close (dsound *s)
-{
-    HRESULT hr;
-
-    if (s->dsound_primary_buffer) {
-        hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not release primary buffer\n");
-        }
-        s->dsound_primary_buffer = NULL;
-    }
-}
-
-static int dsound_open (dsound *s)
-{
-    int err;
-    HRESULT hr;
-    WAVEFORMATEX wfx;
-    DSBUFFERDESC dsbd;
-    HWND hwnd;
-
-    hwnd = GetDesktopWindow ();
-    hr = IDirectSound_SetCooperativeLevel (
-        s->dsound,
-        hwnd,
-        DSSCL_PRIORITY
-        );
-
-    if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not set cooperative level for window %p\n",
-                       hwnd);
-#else
-        LogRel(("DSound: Could not set cooperative level for window %p\n", hwnd));
-        dsound_log_hresult(hr);
-#endif
-        return -1;
-    }
-
-    if (!conf.set_primary) {
-        return 0;
-    }
-
-    err = waveformat_from_audio_settings (&wfx, &conf.settings);
-    if (err) {
-        return -1;
-    }
-
-    memset (&dsbd, 0, sizeof (dsbd));
-    dsbd.dwSize = sizeof (dsbd);
-    dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
-    dsbd.dwBufferBytes = 0;
-    dsbd.lpwfxFormat = NULL;
-
-    hr = IDirectSound_CreateSoundBuffer (
-        s->dsound,
-        &dsbd,
-        &s->dsound_primary_buffer,
-        NULL
-        );
-    if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not create primary playback buffer\n");
-#else
-        LogRel(("DSound: Could not create primary playback buffer\n"));
-        dsound_log_hresult(hr);
-#endif
-        return -1;
-    }
-
-    hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx);
-    if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not set primary playback buffer format\n");
-#else
-        LogRel(("DSound: Could not set primary playback buffer format\n"));
-        dsound_log_hresult(hr);
-#endif
-    }
-
-    hr = IDirectSoundBuffer_GetFormat (
-        s->dsound_primary_buffer,
-        &wfx,
-        sizeof (wfx),
-        NULL
-        );
-    if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not get primary playback buffer format\n");
-#else
-        LogRel(("DSound: Could not get primary playback buffer format\n"));
-        dsound_log_hresult(hr);
-#endif
-        goto fail0;
-    }
-
-#ifdef DEBUG_DSOUND
-    dolog ("Primary\n");
-    print_wave_format (&wfx);
-#endif
-
-    err = waveformat_to_audio_settings (&wfx, &s->settings);
-    if (err) {
-        goto fail0;
-    }
-
-    return 0;
-
- fail0:
-    dsound_close (s);
-    return -1;
+        audio_pcm_info_clear_buf (&ds->hw.info, p2, len2);
+    }
+
+    dsound_unlock_out (ds->dsound_buffer, p1, p2, blen1, blen2);
 }
 
 static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
 {
-    HRESULT hr;
-    DWORD status;
     DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
-    LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
-
-    if (!dsb) {
-        dolog ("Attempt to control voice without a buffer\n");
-        return 0;
-    }
 
     switch (cmd) {
     case VOICE_ENABLE:
-        if (dsound_get_status_out (dsb, &status)) {
-            return -1;
-        }
-
-        if (status & DSBSTATUS_PLAYING) {
-            dolog ("warning: Voice is already playing\n");
-            return 0;
-        }
-
-        dsound_clear_sample (hw, dsb);
-
-        hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not start playing buffer\n");
-            return -1;
-        }
-        break;
-
-    case VOICE_DISABLE:
-        if (dsound_get_status_out (dsb, &status)) {
-            return -1;
-        }
-
-        if (status & DSBSTATUS_PLAYING) {
-            hr = IDirectSoundBuffer_Stop (dsb);
-            if (FAILED (hr)) {
-                dsound_logerr (hr, "Could not stop playing buffer\n");
+        /* Try to start playback. If it fails, then reopen and try again. */
+        if (dsoundPlayStart (ds)) {
+            dsoundPlayClose (ds);
+            dsoundPlayOpen (ds);
+
+            if (dsoundPlayStart (ds)) {
                 return -1;
             }
         }
-        else {
-            dolog ("warning: Voice is not playing\n");
-        }
+        break;
+
+    case VOICE_DISABLE:
+        dsoundPlayStop (ds);
         break;
     }
@@ -955,10 +1010,10 @@
 
     if (!dsb) {
-        dolog ("Attempt to run empty with playback buffer\n");
+        DSLOGF(("DSound: run_out no playback buffer\n"));
         return 0;
     }
 
     hwshift = hw->info.shift;
-    bufsize = hw->samples << hwshift;
+    bufsize = ds->playback_buffer_size << hwshift;
 
     live = audio_pcm_hw_get_live_out (hw);
@@ -967,15 +1022,15 @@
         dsb,
         &ppos,
-        ds->first_time ? &wpos : NULL
+        &wpos
         );
     if (hr == DSERR_BUFFERLOST) {
         if (dsound_restore_out(dsb))
             return 0;
-        hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, ds->first_time ? &wpos : NULL);
+        hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, &wpos);
         if (hr == DSERR_BUFFERLOST)
             return 0;   // Avoid log flooding if the error is still there.
     }
     if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not get playback buffer position\n");
+        DSLOGF(("DSound: get playback buffer position %Rhrc\n", hr));
         return 0;
     }
@@ -986,10 +1041,11 @@
         if (conf.latency_millis) {
             DWORD cur_blat;
-
+            DWORD conf_blat;
+
+            conf_blat = millis_to_bytes (&hw->info, conf.latency_millis);
             cur_blat = audio_ring_dist (wpos, ppos, bufsize);
-            ds->first_time = 0;
             old_pos = wpos;
-            old_pos +=
-                millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat;
+            if (conf_blat > cur_blat) /* Do not write before wpos. */
+               old_pos += conf_blat - cur_blat;
             old_pos %= bufsize;
             old_pos &= ~hw->info.align;
@@ -998,20 +1054,12 @@
             old_pos = wpos;
         }
-#ifdef DEBUG_DSOUND
-        ds->played = 0;
-        ds->mixed = 0;
-#endif
+        ds->first_time = 0;
     }
     else {
         if (ds->old_pos == ppos) {
-#ifdef DEBUG_DSOUND
-            dolog ("old_pos == ppos\n");
-#endif
+            /* Full buffer. */
             return 0;
         }
 
-#ifdef DEBUG_DSOUND
-        ds->played += audio_ring_dist (ds->old_pos, ppos, bufsize);
-#endif
         old_pos = ds->old_pos;
     }
@@ -1027,6 +1075,6 @@
 
     if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) {
-        dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n",
-               len, bufsize, old_pos, ppos);
+        DSLOGF(("DSound: error len=%d bufsize=%d old_pos=%ld ppos=%ld\n",
+               len, bufsize, old_pos, ppos));
         return 0;
     }
@@ -1037,7 +1085,4 @@
     }
 
-#ifdef DEBUG_DSOUND
-    ds->old_ppos = ppos;
-#endif
     err = dsound_lock_out (
         dsb,
@@ -1068,13 +1113,4 @@
     ds->old_pos = (old_pos + (decr << hwshift)) % bufsize;
 
-#ifdef DEBUG_DSOUND
-    ds->mixed += decr << hwshift;
-
-    dolog ("played %lu mixed %lu diff %ld sec %f\n",
-           ds->played,
-           ds->mixed,
-           ds->mixed - ds->played,
-           abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second);
-#endif
     return decr;
 }
@@ -1206,30 +1242,22 @@
 }
 
+static int dsoundIsAvailable (void)
+{
+    LPDIRECTSOUND dsound;
+    HRESULT hr = CoCreateInstance (&CLSID_DirectSound, NULL, CLSCTX_ALL,
+                                   &IID_IDirectSound, (void **) &dsound);
+    if (SUCCEEDED(hr)) {
+        IDirectSound_Release (dsound);
+        return 1;
+    }
+
+    DSLOGREL(("DSound: is unavailable %Rhrc\n", hr));
+    return 0;
+}
+
 static void dsound_audio_fini (void *opaque)
 {
-    HRESULT hr;
     dsound *s = opaque;
-
-    if (!s->dsound) {
-        goto dsound_audio_fini_exit;
-    }
-
-    hr = IDirectSound_Release (s->dsound);
-    if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not release DirectSound\n");
-    }
-    s->dsound = NULL;
-
-    if (!s->dsound_capture) {
-        goto dsound_audio_fini_exit;
-    }
-
-    hr = IDirectSoundCapture_Release (s->dsound_capture);
-    if (FAILED (hr)) {
-        dsound_logerr (hr, "Could not release DirectSoundCapture\n");
-    }
-    s->dsound_capture = NULL;
-
-dsound_audio_fini_exit:
+    NOREF(s);
     CoUninitialize();
 }
@@ -1237,64 +1265,21 @@
 static void *dsound_audio_init (void)
 {
-    int err;
     HRESULT hr;
     dsound *s = &glob_dsound;
-    RTUUID devguid;
-    LPCGUID devguidp;
 
     hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
     if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not initialize COM\n");
-#else
-        LogRel(("DSound: Could not initialize COM\n"));
-        dsound_log_hresult(hr);
-#endif
+        DSLOGREL(("DSound: COM initialize %Rhrc\n", hr));
         return NULL;
     }
 
-    hr = CoCreateInstance (
-        &CLSID_DirectSound,
-        NULL,
-        CLSCTX_ALL,
-        &IID_IDirectSound,
-        (void **) &s->dsound
-        );
-    if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not create DirectSound instance\n");
-#else
-        LogRel(("DSound: Could not create DirectSound instance\n"));
-        dsound_log_hresult(hr);
-#endif
-        CoUninitialize();
-        return NULL;
-    }
-
     if (conf.device_guid_out) {
-        hr = RTUuidFromStr(&devguid, conf.device_guid_out);
-        if (FAILED (hr)) {
+        int rc = RTUuidFromStr(&s->devguid_play, conf.device_guid_out);
+        if (FAILED (rc)) {
             LogRel(("DSound: Could not parse DirectSound output device GUID\n"));
         }
-        devguidp = (LPCGUID)&devguid;
+        s->devguidp_play = (LPCGUID)&s->devguid_play;
     } else {
-        devguidp = NULL;
-    }
-    hr = IDirectSound_Initialize (s->dsound, devguidp);
-    if (FAILED (hr)) {
-#ifndef VBOX
-        dsound_logerr (hr, "Could not initialize DirectSound\n");
-#else
-        LogRel(("DSound: Could not initialize DirectSound\n"));
-        dsound_log_hresult(hr);
-#endif
-
-        hr = IDirectSound_Release (s->dsound);
-        if (FAILED (hr)) {
-            dsound_logerr (hr, "Could not release DirectSound\n");
-        }
-        s->dsound = NULL;
-        CoUninitialize();
-        return NULL;
+        s->devguidp_play = NULL;
     }
 
@@ -1309,11 +1294,10 @@
     }
 
-    err = dsound_open (s);
-    if (err) {
-        dsound_audio_fini (s);
-        return NULL;
-    }
-
-    return s;
+    /* Check that DSound interface is available. */
+    if (dsoundIsAvailable ())
+        return s;
+
+    dsound_audio_fini (s);
+    return NULL;
 }
 
@@ -1325,14 +1309,6 @@
     {"GetStatusRetries", AUD_OPT_INT, &conf.getstatus_retries,
      "Number of times to attempt getting status of the buffer", NULL, 0},
-    {"SetPrimary", AUD_OPT_BOOL, &conf.set_primary,
-     "Set the parameters of primary buffer", NULL, 0},
     {"LatencyMillis", AUD_OPT_INT, &conf.latency_millis,
      "(undocumented)", NULL, 0},
-    {"PrimaryFreq", AUD_OPT_INT, &conf.settings.freq,
-     "Primary buffer frequency", NULL, 0},
-    {"PrimaryChannels", AUD_OPT_INT, &conf.settings.nchannels,
-     "Primary buffer number of channels (1 - mono, 2 - stereo)", NULL, 0},
-    {"PrimaryFmt", AUD_OPT_FMT, &conf.settings.fmt,
-     "Primary buffer format", NULL, 0},
     {"BufsizeOut", AUD_OPT_INT, &conf.bufsize_out,
      "(undocumented)", NULL, 0},
