Bug 1575995 - part3 : implement play/pause controller. r=chunmin
authoralwu <alwu@mozilla.com>
Wed, 18 Sep 2019 20:55:57 +0000
changeset 494028 deb0bc2ec44fcb4af8efca40c6938769e861bd18
parent 494027 a417c89cf52baa165e3821cce14ed126531e3ee7
child 494029 49618c34643003a9d4ed8584ecdeac18c5927569
push id36593
push useropoprus@mozilla.com
push dateThu, 19 Sep 2019 09:46:54 +0000
treeherdermozilla-central@6b93a83735ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschunmin
bugs1575995
milestone71.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 1575995 - part3 : implement play/pause controller. r=chunmin The ideal situation for media control should be incooperated with the audio competition so that we only have to control one controller. However, if it's multiple controllers at the same time, we would tend to only control the last one in order to reduce confustion. Ex. If we pause controller A first, and then start controller B. So what should we do when we press `play/pause` hardware key? To resume controller A or to stop controller B, or do both things at the same time? Differential Revision: https://phabricator.services.mozilla.com/D43315
dom/media/mediacontrol/MediaControlService.cpp
dom/media/mediacontrol/MediaControlService.h
dom/media/mediacontrol/MediaHardwareKeysEvent.cpp
dom/media/mediacontrol/tests/gtest/TestMediaControlService.cpp
--- a/dom/media/mediacontrol/MediaControlService.cpp
+++ b/dom/media/mediacontrol/MediaControlService.cpp
@@ -100,27 +100,29 @@ RefPtr<MediaController> MediaControlServ
 
 void MediaControlService::AddMediaController(
     const RefPtr<MediaController>& aController) {
   MOZ_DIAGNOSTIC_ASSERT(aController);
   const uint64_t cId = aController->Id();
   MOZ_DIAGNOSTIC_ASSERT(!mControllers.GetValue(cId),
                         "Controller has been added already!");
   mControllers.Put(cId, aController);
+  mControllerHistory.AppendElement(cId);
   LOG("Add media controller %" PRId64 ", currentNum=%" PRId64, cId,
       GetControllersNum());
 }
 
 void MediaControlService::RemoveMediaController(
     const RefPtr<MediaController>& aController) {
   MOZ_DIAGNOSTIC_ASSERT(aController);
   const uint64_t cId = aController->Id();
   MOZ_DIAGNOSTIC_ASSERT(mControllers.GetValue(cId),
                         "Controller does not exist!");
   mControllers.Remove(cId);
+  mControllerHistory.RemoveElement(cId);
   LOG("Remove media controller %" PRId64 ", currentNum=%" PRId64, cId,
       GetControllersNum());
 }
 
 void MediaControlService::PlayAllControllers() const {
   for (auto iter = mControllers.ConstIter(); !iter.Done(); iter.Next()) {
     const RefPtr<MediaController>& controller = iter.Data();
     controller->Play();
@@ -147,10 +149,18 @@ void MediaControlService::ShutdownAllCon
     controller->Shutdown();
   }
 }
 
 uint64_t MediaControlService::GetControllersNum() const {
   return mControllers.Count();
 }
 
+already_AddRefed<MediaController>
+MediaControlService::GetLastAddedController() {
+  if (mControllerHistory.IsEmpty()) {
+    return nullptr;
+  }
+  return GetControllerById(mControllerHistory.LastElement()).forget();
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/media/mediacontrol/MediaControlService.h
+++ b/dom/media/mediacontrol/MediaControlService.h
@@ -38,28 +38,31 @@ class MediaControlService final : public
   RefPtr<MediaController> GetOrCreateControllerById(const uint64_t aId) const;
   RefPtr<MediaController> GetControllerById(const uint64_t aId) const;
   AudioFocusManager& GetAudioFocusManager() { return mAudioFocusManager; }
 
   void AddMediaController(const RefPtr<MediaController>& aController);
   void RemoveMediaController(const RefPtr<MediaController>& aController);
   uint64_t GetControllersNum() const;
 
+  already_AddRefed<MediaController> GetLastAddedController();
+
  private:
   MediaControlService();
   ~MediaControlService();
 
   void Shutdown();
 
   void PlayAllControllers() const;
   void PauseAllControllers() const;
   void StopAllControllers() const;
   void ShutdownAllControllers() const;
 
   nsDataHashtable<nsUint64HashKey, RefPtr<MediaController>> mControllers;
+  nsTArray<uint64_t> mControllerHistory;
   AudioFocusManager mAudioFocusManager;
   MediaHardwareKeysManager mHardwareKeysManager;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif
--- a/dom/media/mediacontrol/MediaHardwareKeysEvent.cpp
+++ b/dom/media/mediacontrol/MediaHardwareKeysEvent.cpp
@@ -41,19 +41,31 @@ static const char* ToMediaControlKeysEve
             ("MediaHardwareKeysEventListener=%p, " msg, this,     \
              ToMediaControlKeysEventStr(key), ##__VA_ARGS__));    \
   }
 
 void MediaHardwareKeysEventListener::OnKeyPressed(
     MediaControlKeysEvent aKeyEvent) {
   LOG_KEY("OnKeyPressed '%s'", aKeyEvent);
   switch (aKeyEvent) {
-    case MediaControlKeysEvent::ePlayPause:
-      // TODO : implement playing/pausing controller in following patch.
+    case MediaControlKeysEvent::ePlayPause: {
+      RefPtr<MediaControlService> service = MediaControlService::GetService();
+      MOZ_ASSERT(service);
+      RefPtr<MediaController> controller = service->GetLastAddedController();
+      if (!controller) {
+        return;
+      }
+
+      if (controller->IsPlaying()) {
+        controller->Pause();
+      } else {
+        controller->Play();
+      }
       return;
+    }
     case MediaControlKeysEvent::eNext:
     case MediaControlKeysEvent::ePrev:
       // TODO : implement related controller functions.
       return;
     default:
       LOG("Error : undefined event!");
       return;
   }
--- a/dom/media/mediacontrol/tests/gtest/TestMediaControlService.cpp
+++ b/dom/media/mediacontrol/tests/gtest/TestMediaControlService.cpp
@@ -28,8 +28,37 @@ TEST(MediaControlService, TestAddOrRemov
   ASSERT_TRUE(service->GetControllersNum() == 2);
 
   service->RemoveMediaController(controller1);
   ASSERT_TRUE(service->GetControllersNum() == 1);
 
   service->RemoveMediaController(controller2);
   ASSERT_TRUE(service->GetControllersNum() == 0);
 }
+
+TEST(MediaControlService, TestLastAddedController)
+{
+  RefPtr<MediaControlService> service = MediaControlService::GetService();
+  ASSERT_TRUE(service->GetControllersNum() == 0);
+
+  RefPtr<MediaController> controller1 =
+      new TabMediaController(FIRST_CONTROLLER_ID);
+  service->AddMediaController(controller1);
+
+  RefPtr<MediaController> lastController = service->GetLastAddedController();
+  ASSERT_TRUE(lastController->Id() == FIRST_CONTROLLER_ID);
+
+  RefPtr<MediaController> controller2 =
+      new TabMediaController(SECOND_CONTROLLER_ID);
+  service->AddMediaController(controller2);
+
+  lastController = service->GetLastAddedController();
+  ASSERT_TRUE(lastController->Id() == SECOND_CONTROLLER_ID);
+
+  service->RemoveMediaController(controller2);
+  lastController = service->GetLastAddedController();
+  ASSERT_TRUE(lastController->Id() == FIRST_CONTROLLER_ID);
+
+  service->RemoveMediaController(controller1);
+  lastController = service->GetLastAddedController();
+  ASSERT_TRUE(service->GetControllersNum() == 0);
+  ASSERT_TRUE(!lastController);
+}