DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "MediaControlKeyManager.h"

#include "MediaControlUtils.h"
#include "MediaControlService.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Assertions.h"
#include "mozilla/Logging.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/widget/MediaKeysEventSourceFactory.h"

#undef LOG
#define LOG(msg, ...)                        \
  MOZ_LOG(gMediaControlLog, LogLevel::Debug, \
          ("MediaControlKeyManager=%p, " msg, this, ##__VA_ARGS__))

#undef LOG_INFO
#define LOG_INFO(msg, ...)                  \
  MOZ_LOG(gMediaControlLog, LogLevel::Info, \
          ("MediaControlKeyManager=%p, " msg, this, ##__VA_ARGS__))

namespace mozilla {
namespace dom {

bool MediaControlKeyManager::IsOpened() const {
  // As MediaControlKeyManager represents a platform-indenpendent event source,
  // which we can use to add other listeners to moniter media key events, we
  // would always return true even if we fail to open the real media key event
  // source, because we still have chances to open the source again when there
  // are other new controllers being added.
  return true;
}

bool MediaControlKeyManager::Open() {
  mControllerAmountChangedListener =
      MediaControlService::GetService()
          ->MediaControllerAmountChangedEvent()
          .Connect(AbstractThread::MainThread(), this,
                   &MediaControlKeyManager::ControllerAmountChanged);
  return true;
}

MediaControlKeyManager::~MediaControlKeyManager() {
  StopMonitoringControlKeys();
  mEventSource = nullptr;
  mControllerAmountChangedListener.DisconnectIfExists();
}

void MediaControlKeyManager::StartMonitoringControlKeys() {
  if (!StaticPrefs::media_hardwaremediakeys_enabled()) {
    return;
  }

  if (!mEventSource) {
    mEventSource = widget::CreateMediaControlKeySource();
  }

  // When cross-compiling with MinGW, we cannot use the related WinAPI, thus
  // mEventSource might be null there.
  if (!mEventSource) {
    return;
  }

  LOG_INFO("StartMonitoringControlKeys");
  if (!mEventSource->IsOpened() && mEventSource->Open()) {
    mEventSource->SetPlaybackState(mPlaybackState);
    mEventSource->SetMediaMetadata(mMetadata);
    mEventSource->AddListener(this);
  }
}

void MediaControlKeyManager::StopMonitoringControlKeys() {
  if (mEventSource && mEventSource->IsOpened()) {
    LOG_INFO("StopMonitoringControlKeys");
    mEventSource->Close();
  }
}

void MediaControlKeyManager::ControllerAmountChanged(
    uint64_t aControllerAmount) {
  LOG("Controller amount changed=%" PRId64, aControllerAmount);
  if (aControllerAmount > 0) {
    StartMonitoringControlKeys();
  } else if (aControllerAmount == 0) {
    StopMonitoringControlKeys();
  }
}

void MediaControlKeyManager::OnKeyPressed(MediaControlKey aKey) {
  for (auto listener : mListeners) {
    listener->OnKeyPressed(aKey);
  }
}

void MediaControlKeyManager::SetPlaybackState(
    MediaSessionPlaybackState aState) {
  if (mEventSource && mEventSource->IsOpened()) {
    mEventSource->SetPlaybackState(aState);
  }
  mPlaybackState = aState;
  LOG_INFO("playbackState=%s", ToMediaSessionPlaybackStateStr(mPlaybackState));
  if (StaticPrefs::media_mediacontrol_testingevents_enabled()) {
    if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
      obs->NotifyObservers(nullptr, "media-displayed-playback-changed",
                           nullptr);
    }
  }
}

MediaSessionPlaybackState MediaControlKeyManager::GetPlaybackState() const {
  return (mEventSource && mEventSource->IsOpened())
             ? mEventSource->GetPlaybackState()
             : mPlaybackState;
}

void MediaControlKeyManager::SetMediaMetadata(
    const MediaMetadataBase& aMetadata) {
  if (mEventSource && mEventSource->IsOpened()) {
    mEventSource->SetMediaMetadata(aMetadata);
  }
  mMetadata = aMetadata;
  LOG_INFO("title=%s, artist=%s album=%s",
           NS_ConvertUTF16toUTF8(mMetadata.mTitle).get(),
           NS_ConvertUTF16toUTF8(mMetadata.mArtist).get(),
           NS_ConvertUTF16toUTF8(mMetadata.mAlbum).get());
  if (StaticPrefs::media_mediacontrol_testingevents_enabled()) {
    if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
      obs->NotifyObservers(nullptr, "media-displayed-metadata-changed",
                           nullptr);
    }
  }
}

void MediaControlKeyManager::SetSupportedMediaKeys(
    const MediaKeysArray& aSupportedKeys) {
  mSupportedKeys.Clear();
  for (const auto& key : aSupportedKeys) {
    LOG_INFO("Supported keys=%s", ToMediaControlKeyStr(key));
    mSupportedKeys.AppendElement(key);
  }
  if (mEventSource && mEventSource->IsOpened()) {
    mEventSource->SetSupportedMediaKeys(mSupportedKeys);
  }
}

}  // namespace dom
}  // namespace mozilla