summaryrefslogtreecommitdiffstats
path: root/ash/system/win/audio/tray_audio_delegate_win.cc
blob: 18e46af3bdd968f68c6f17d76367beef154eb7d8 (plain)
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
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/win/audio/tray_audio_delegate_win.h"

#include <audiopolicy.h>
#include <cmath>

#include "media/audio/win/core_audio_util_win.h"

using base::win::ScopedComPtr;

namespace {

// Volume value which should be considered as muted in range [0, 100].
const int kMuteThresholdPercent = 1;

// Lowest volume which is considered to be audible in the range [0, 100].
const int kDefaultUnmuteVolumePercent = 4;

}  // namespace

namespace ash  {
namespace system {

void TrayAudioDelegateWin::AdjustOutputVolumeToAudibleLevel() {
  if (GetOutputVolumeLevel() <= kMuteThresholdPercent)
    SetOutputVolumeLevel(kDefaultUnmuteVolumePercent);
}

int TrayAudioDelegateWin::GetOutputDefaultVolumeMuteLevel() {
  return kMuteThresholdPercent;
}

int TrayAudioDelegateWin::GetOutputVolumeLevel() {
  ScopedComPtr<ISimpleAudioVolume> volume_control =
      CreateDefaultVolumeControl();
  if (!volume_control.get())
    return 0;

  float level = 0.0f;
  if (FAILED(volume_control->GetMasterVolume(&level)))
    return 0;

  // MSVC prior to 2013 doesn't have a round function.  The below code is not
  // conformant to C99 round(), but since we know that 0 <= level <= 100, it
  // should be ok.
  return static_cast<int>(level + 0.5);
}

int TrayAudioDelegateWin::GetActiveOutputDeviceIconId() {
  return kNoAudioDeviceIcon;
}

bool TrayAudioDelegateWin::HasAlternativeSources() {
  return false;
}

bool TrayAudioDelegateWin::IsOutputAudioMuted() {
  ScopedComPtr<ISimpleAudioVolume> volume_control =
      CreateDefaultVolumeControl();

  if (!volume_control.get())
    return false;

  BOOL mute = FALSE;
  if (FAILED(volume_control->GetMute(&mute)))
    return false;

  return !!mute;
}

void TrayAudioDelegateWin::SetOutputAudioIsMuted(bool is_muted) {
  ScopedComPtr<ISimpleAudioVolume> volume_control =
      CreateDefaultVolumeControl();

  if (!volume_control.get())
    return;

  volume_control->SetMute(is_muted, NULL);
}

void TrayAudioDelegateWin::SetOutputVolumeLevel(int level) {
  ScopedComPtr<ISimpleAudioVolume> volume_control =
      CreateDefaultVolumeControl();

  if (!volume_control.get())
    return;

  float volume_level = static_cast<float>(level) / 100.0f;
  volume_control->SetMasterVolume(volume_level, NULL);
}

void TrayAudioDelegateWin::SetInternalSpeakerChannelMode(
    AudioChannelMode mode) {
}

ScopedComPtr<ISimpleAudioVolume>
TrayAudioDelegateWin::CreateDefaultVolumeControl() {
  ScopedComPtr<ISimpleAudioVolume> volume_control;
  ScopedComPtr<IAudioSessionManager> session_manager;

  ScopedComPtr<IMMDevice> device =
      media::CoreAudioUtil::CreateDefaultDevice(eRender, eConsole);
  if (!device.get() ||
      FAILED(device->Activate(__uuidof(IAudioSessionManager), CLSCTX_ALL, NULL,
                              session_manager.ReceiveVoid()))) {
    return volume_control;
  }

  session_manager->GetSimpleAudioVolume(NULL, FALSE,
      volume_control.Receive());

  return volume_control;
}

}  // namespace system
}  // namespace ash