+// This class turns wxSoundBackend that doesn't support asynchronous playback
+// into one that does
+class wxSoundSyncOnlyAdaptor : public wxSoundBackend
+{
+public:
+    wxSoundSyncOnlyAdaptor(wxSoundBackend *backend)
+        : m_backend(backend), m_playing(false) {}
+    virtual ~wxSoundSyncOnlyAdaptor()
+    {
+        delete m_backend;
+    }
+    wxString GetName() const
+    {
+        return m_backend->GetName();
+    }
+    int GetPriority() const
+    {
+        return m_backend->GetPriority();
+    }
+    bool IsAvailable() const
+    {
+        return m_backend->IsAvailable();
+    }
+    bool HasNativeAsyncPlayback() const
+    {
+        return true;
+    }
+    bool Play(wxSoundData *data, unsigned flags,
+              volatile wxSoundPlaybackStatus *status);
+    void Stop();
+    bool IsPlaying() const;
+
+private:
+    friend class wxSoundAsyncPlaybackThread;
+
+    wxSoundBackend *m_backend;
+    bool m_playing;
+#if wxUSE_THREADS
+    // player thread holds this mutex and releases it after it finishes
+    // playing, so that the main thread knows when it can play sound
+    wxMutex m_mutexRightToPlay;
+    wxSoundPlaybackStatus m_status;
+#endif
+};
+
+
+#if wxUSE_THREADS
+wxThread::ExitCode wxSoundAsyncPlaybackThread::Entry()
+{
+    m_adapt->m_backend->Play(m_data, m_flags & ~wxSOUND_ASYNC,
+                             &m_adapt->m_status);
+
+    m_data->DecRef();
+    m_adapt->m_playing = false;
+    m_adapt->m_mutexRightToPlay.Unlock();
+    wxLogTrace(_T("sound"), _T("terminated async playback thread"));
+    return 0;
+}
+#endif
+
+bool wxSoundSyncOnlyAdaptor::Play(wxSoundData *data, unsigned flags,
+                                  volatile wxSoundPlaybackStatus *status)
+{
+    Stop();
+    if (flags & wxSOUND_ASYNC)
+    {
+#if wxUSE_THREADS
+        m_mutexRightToPlay.Lock();
+        m_status.m_playing = true;
+        m_status.m_stopRequested = false;
+        data->IncRef();
+        wxThread *th = new wxSoundAsyncPlaybackThread(this, data, flags);
+        th->Create();
+        th->Run();
+        wxLogTrace(_T("sound"), _T("launched async playback thread"));
+        return true;
+#else
+        wxLogError(_("Unable to play sound asynchronously."));
+        return false;
+#endif
+    }
+    else
+    {
+#if wxUSE_THREADS
+        m_mutexRightToPlay.Lock();
+#endif
+        bool rv = m_backend->Play(data, flags, status);
+#if wxUSE_THREADS
+        m_mutexRightToPlay.Unlock();
+#endif
+        return rv;
+    }
+}
+
+void wxSoundSyncOnlyAdaptor::Stop()
+{
+    wxLogTrace(_T("sound"), _T("asking audio to stop"));
+
+#if wxUSE_THREADS
+    // tell the player thread (if running) to stop playback ASAP:
+    m_status.m_stopRequested = true;
+
+    // acquire the mutex to be sure no sound is being played, then
+    // release it because we don't need it for anything (the effect of this
+    // is that calling thread will wait until playback thread reacts to
+    // our request to interrupt playback):
+    m_mutexRightToPlay.Lock();
+    m_mutexRightToPlay.Unlock();
+    wxLogTrace(_T("sound"), _T("audio was stopped"));
+#endif
+}
+
+bool wxSoundSyncOnlyAdaptor::IsPlaying() const
+{
+#if wxUSE_THREADS
+    return m_status.m_playing;
+#else
+    return false;
+#endif
+}
+
+