Bug 1482659 - Purge the last sound, free then start to play a sound. r=m_kato,masayuki, a=RyanVM
authorThomas Nguyen <tnguyen@mozilla.com>
Wed, 09 Jan 2019 12:26:46 +0000
changeset 506618 c4bda79261ba60e22768197f8219d7061e066227
parent 506617 947bc1c824fee0e098660f656f77df59c3225abe
child 506619 aaeaf42a092dd7c12c17e6a5850aa9d93129477f
push id10482
push userryanvm@gmail.com
push dateThu, 10 Jan 2019 17:30:03 +0000
treeherdermozilla-beta@c4bda79261ba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato, masayuki, RyanVM
bugs1482659
milestone65.0
Bug 1482659 - Purge the last sound, free then start to play a sound. r=m_kato,masayuki, a=RyanVM Because we don't know when the PlaySound API stop/finish playing. So when starting to play a sound, we should call PlaySound(0,0,PURGE) to stop playing then free the last data sound. Differential Revision: https://phabricator.services.mozilla.com/D14554
widget/windows/nsSound.cpp
widget/windows/nsSound.h
--- a/widget/windows/nsSound.cpp
+++ b/widget/windows/nsSound.cpp
@@ -108,22 +108,26 @@ mozilla::StaticRefPtr<nsISound> nsSound:
 NS_IMPL_ISUPPORTS(nsSound, nsISound, nsIStreamLoaderObserver, nsIObserver)
 
 nsSound::nsSound() : mInited(false) {}
 
 nsSound::~nsSound() {}
 
 void nsSound::PurgeLastSound() {
   // Halt any currently playing sound.
-  if (mPlayerThread) {
-    mPlayerThread->Dispatch(
-        NS_NewRunnableFunction(
-            "nsSound::PurgeLastSound",
-            []() { ::PlaySound(nullptr, nullptr, SND_PURGE); }),
-        NS_DISPATCH_NORMAL);
+  if (mSoundPlayer) {
+    if (mPlayerThread) {
+      mPlayerThread->Dispatch(NS_NewRunnableFunction(
+        "nsSound::PurgeLastSound", [player = std::move(mSoundPlayer)]() {
+          // Capture move mSoundPlayer to lambda then
+          // PlaySoundW(nullptr, nullptr, SND_PURGE) will be called before
+          // freeing the nsSoundPlayer.
+          ::PlaySoundW(nullptr, nullptr, SND_PURGE);
+        }), NS_DISPATCH_NORMAL);
+    }
   }
 }
 
 NS_IMETHODIMP nsSound::Beep() {
   ::MessageBeep(0);
 
   return NS_OK;
 }
@@ -153,20 +157,21 @@ NS_IMETHODIMP nsSound::OnStreamComplete(
     }
 #endif
     return aStatus;
   }
 
   PurgeLastSound();
 
   if (data && dataLen > 0) {
-    RefPtr<nsSoundPlayer> player = new nsSoundPlayer(data, dataLen);
-    MOZ_ASSERT(player, "Could not create player");
+    MOZ_ASSERT(!mSoundPlayer, "mSoundPlayer should be null");
+    mSoundPlayer = new nsSoundPlayer(data, dataLen);
+    MOZ_ASSERT(mSoundPlayer, "Could not create player");
 
-    nsresult rv = mPlayerThread->Dispatch(player, NS_DISPATCH_NORMAL);
+    nsresult rv = mPlayerThread->Dispatch(mSoundPlayer, NS_DISPATCH_NORMAL);
     if (NS_WARN_IF(FAILED(rv))) {
       return rv;
     }
   }
 
   return NS_OK;
 }
 
@@ -233,17 +238,17 @@ NS_IMETHODIMP nsSound::Init() {
   // We have to use the sound library for something to make sure
   // it is initialized.
   // If we wait until the first sound is played, there will
   // be a time lag as the library gets loaded.
   // This should be done in player thread otherwise it will block main thread
   // at the first time loading sound library.
   mPlayerThread->Dispatch(
       NS_NewRunnableFunction(
-          "nsSound::Init", []() { ::PlaySound(nullptr, nullptr, SND_PURGE); }),
+          "nsSound::Init", []() { ::PlaySoundW(nullptr, nullptr, SND_PURGE); }),
       NS_DISPATCH_NORMAL);
 
   mInited = true;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsSound::PlayEventSound(uint32_t aEventId) {
@@ -271,17 +276,17 @@ NS_IMETHODIMP nsSound::PlayEventSound(ui
       sound = L".Default";
       break;
     default:
       // Win32 plays no sounds at NS_SYSSOUND_PROMPT_DIALOG and
       // NS_SYSSOUND_SELECT_DIALOG.
       return NS_OK;
   }
   NS_ASSERTION(sound, "sound is null");
-
-  nsCOMPtr<nsIRunnable> player = new nsSoundPlayer(nsDependentString(sound));
-  MOZ_ASSERT(player, "Could not create player");
-  nsresult rv = mPlayerThread->Dispatch(player, NS_DISPATCH_NORMAL);
+  MOZ_ASSERT(!mSoundPlayer, "mSoundPlayer should be null");
+  mSoundPlayer = new nsSoundPlayer(nsDependentString(sound));
+  MOZ_ASSERT(mSoundPlayer, "Could not create player");
+  nsresult rv = mPlayerThread->Dispatch(mSoundPlayer, NS_DISPATCH_NORMAL);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
--- a/widget/windows/nsSound.h
+++ b/widget/windows/nsSound.h
@@ -9,16 +9,17 @@
 
 #include "nsISound.h"
 #include "nsIObserver.h"
 #include "nsIStreamLoader.h"
 #include "nsCOMPtr.h"
 #include "mozilla/StaticPtr.h"
 
 class nsIThread;
+class nsIRunnable;
 
 class nsSound : public nsISound,
                 public nsIStreamLoaderObserver,
                 public nsIObserver
 
 {
  public:
   nsSound();
@@ -32,14 +33,15 @@ class nsSound : public nsISound,
  private:
   virtual ~nsSound();
   void PurgeLastSound();
 
  private:
   nsresult CreatePlayerThread();
 
   nsCOMPtr<nsIThread> mPlayerThread;
+  nsCOMPtr<nsIRunnable> mSoundPlayer;
   bool mInited;
 
   static mozilla::StaticRefPtr<nsISound> sInstance;
 };
 
 #endif /* __nsSound_h__ */