Bug 1482659 - Purge the last sound, free then start to play a sound r=m_kato,masayuki
authorThomas Nguyen <tnguyen@mozilla.com>
Wed, 09 Jan 2019 12:26:46 +0000
changeset 510297 5665c5f251985c3f2e54a5bb0f18db99a58b8acd
parent 510296 606870290cd6ece614fe54d67f273fe2a803ecdd
child 510298 740f1995b1281671ca4fe49ad97d834a19d29016
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato, masayuki
bugs1482659
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1482659 - Purge the last sound, free then start to play a sound r=m_kato,masayuki 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__ */