+// 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(wxT("sound"), wxT("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(wxT("sound"), wxT("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(wxT("sound"), wxT("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(wxT("sound"), wxT("audio was stopped"));
+#endif
+}
+
+bool wxSoundSyncOnlyAdaptor::IsPlaying() const
+{
+#if wxUSE_THREADS
+ return m_status.m_playing;
+#else
+ return false;
+#endif
+}
+
+