chromium/chromecast/media/cma/backend/android/volume_control_android.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMECAST_MEDIA_CMA_BACKEND_ANDROID_VOLUME_CONTROL_ANDROID_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_ANDROID_VOLUME_CONTROL_ANDROID_H_

#include <map>
#include <vector>

#include "base/android/jni_android.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "chromecast/media/cma/backend/android/audio_sink_manager.h"
#include "chromecast/media/cma/backend/android/volume_cache.h"

namespace chromecast {
namespace media {

class VolumeControlAndroid : SystemVolumeTableAccessApi {
 public:
  VolumeControlAndroid();

  VolumeControlAndroid(const VolumeControlAndroid&) = delete;
  VolumeControlAndroid& operator=(const VolumeControlAndroid&) = delete;

  ~VolumeControlAndroid() override;

  void AddVolumeObserver(VolumeObserver* observer);
  void RemoveVolumeObserver(VolumeObserver* observer);
  float GetVolume(AudioContentType type);
  void SetVolume(VolumeChangeSource source, AudioContentType type, float level);
  bool IsMuted(AudioContentType type);
  void SetMuted(VolumeChangeSource source, AudioContentType type, bool muted);
  void SetOutputLimit(AudioContentType type, float limit);
  float VolumeToDbFSCached(AudioContentType type, float volume);
  float DbFSToVolumeCached(AudioContentType type, float db);

  // Called from java to signal a change volume.
  void OnVolumeChange(JNIEnv* env,
                      const base::android::JavaParamRef<jobject>& obj,
                      jint type,
                      jfloat level);

  void OnMuteChange(JNIEnv* env,
                    const base::android::JavaParamRef<jobject>& obj,
                    jint type,
                    jboolean muted);

  // SystemVolumeTableAccessApi implementation.
  int GetMaxVolumeIndex(AudioContentType type) override;
  float VolumeToDbFS(AudioContentType type, float volume) override;

 private:
  void InitializeOnThread();
  void SetVolumeOnThread(VolumeChangeSource source,
                         AudioContentType type,
                         float level,
                         bool from_android);
  void SetMutedOnThread(VolumeChangeSource source,
                        AudioContentType type,
                        bool muted,
                        bool from_android);
  void ReportVolumeChangeOnThread(AudioContentType type, float level);
  void ReportMuteChangeOnThread(AudioContentType type, bool muted);

  // For the user of the VolumeControl, all volume values are in the volume
  // table domain of kMedia (MUSIC). For volume types other than media,
  // VolumeControl converts them internally into their proper volume table
  // domains.
  float MapIntoDifferentVolumeTableDomain(AudioContentType from_type,
                                          AudioContentType to_type,
                                          float level);

  const bool is_single_volume_;
  base::android::ScopedJavaGlobalRef<jobject> j_volume_control_;

  std::map<AudioContentType, std::unique_ptr<VolumeCache>> volume_cache_;

  base::Lock volume_lock_;
  std::map<AudioContentType, float> volumes_;
  std::map<AudioContentType, bool> muted_;

  base::Lock observer_lock_;
  std::vector<VolumeObserver*> volume_observers_;

  base::Thread thread_;
  base::WaitableEvent initialize_complete_event_;
};

}  // namespace media
}  // namespace chromecast

#endif  // CHROMECAST_MEDIA_CMA_BACKEND_ANDROID_VOLUME_CONTROL_ANDROID_H_