OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/linux/audio_manager_linux.h" | 5 #include "media/audio/linux/audio_manager_linux.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/environment.h" | 8 #include "base/environment.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/nix/xdg_util.h" | 10 #include "base/nix/xdg_util.h" |
11 #include "base/process_util.h" | 11 #include "base/process_util.h" |
12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
13 #include "media/audio/audio_output_dispatcher.h" | 13 #include "media/audio/audio_output_dispatcher.h" |
14 #include "media/audio/fake_audio_input_stream.h" | |
15 #include "media/audio/fake_audio_output_stream.h" | |
16 #include "media/audio/linux/alsa_input.h" | 14 #include "media/audio/linux/alsa_input.h" |
17 #include "media/audio/linux/alsa_output.h" | 15 #include "media/audio/linux/alsa_output.h" |
18 #include "media/audio/linux/alsa_wrapper.h" | 16 #include "media/audio/linux/alsa_wrapper.h" |
19 #if defined(USE_PULSEAUDIO) | 17 #if defined(USE_PULSEAUDIO) |
20 #include "media/audio/pulse/pulse_output.h" | 18 #include "media/audio/pulse/pulse_output.h" |
21 #endif | 19 #endif |
22 #include "media/base/limits.h" | 20 #include "media/base/limits.h" |
23 #include "media/base/media_switches.h" | 21 #include "media/base/media_switches.h" |
24 | 22 |
25 // Maximum number of output streams that can be open simultaneously. | 23 // Maximum number of output streams that can be open simultaneously. |
26 static const size_t kMaxOutputStreams = 50; | 24 static const int kMaxOutputStreams = 50; |
27 | 25 |
28 static const int kMaxInputChannels = 2; | 26 static const int kMaxInputChannels = 2; |
29 | 27 |
30 // Since "default", "pulse" and "dmix" devices are virtual devices mapped to | 28 // Since "default", "pulse" and "dmix" devices are virtual devices mapped to |
31 // real devices, we remove them from the list to avoiding duplicate counting. | 29 // real devices, we remove them from the list to avoiding duplicate counting. |
32 // In addition, note that we support no more than 2 channels for recording, | 30 // In addition, note that we support no more than 2 channels for recording, |
33 // hence surround devices are not stored in the list. | 31 // hence surround devices are not stored in the list. |
34 static const char* kInvalidAudioInputDevices[] = { | 32 static const char* kInvalidAudioInputDevices[] = { |
35 "default", | 33 "default", |
36 "null", | 34 "null", |
37 "pulse", | 35 "pulse", |
38 "dmix", | 36 "dmix", |
39 }; | 37 }; |
40 | 38 |
41 // Implementation of AudioManager. | 39 // Implementation of AudioManager. |
42 bool AudioManagerLinux::HasAudioOutputDevices() { | 40 bool AudioManagerLinux::HasAudioOutputDevices() { |
43 return HasAnyAlsaAudioDevice(kStreamPlayback); | 41 return HasAnyAlsaAudioDevice(kStreamPlayback); |
44 } | 42 } |
45 | 43 |
46 bool AudioManagerLinux::HasAudioInputDevices() { | 44 bool AudioManagerLinux::HasAudioInputDevices() { |
47 return HasAnyAlsaAudioDevice(kStreamCapture); | 45 return HasAnyAlsaAudioDevice(kStreamCapture); |
48 } | 46 } |
49 | 47 |
50 AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream( | 48 AudioManagerLinux::AudioManagerLinux() { |
51 const AudioParameters& params) { | 49 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
52 // Early return for testing hook. | |
53 if (params.format == AudioParameters::AUDIO_MOCK) | |
54 return FakeAudioOutputStream::MakeFakeStream(params); | |
55 | |
56 // Don't allow opening more than |kMaxOutputStreams| streams. | |
57 if (active_output_stream_count_ >= kMaxOutputStreams) | |
58 return NULL; | |
59 | |
60 AudioOutputStream* stream = NULL; | |
61 #if defined(USE_PULSEAUDIO) | |
62 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUsePulseAudio)) { | |
63 stream = new PulseAudioOutputStream(params, this); | |
64 } else { | |
65 #endif | |
66 std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice; | |
67 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
68 switches::kAlsaOutputDevice)) { | |
69 device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
70 switches::kAlsaOutputDevice); | |
71 } | |
72 stream = new AlsaPcmOutputStream(device_name, params, wrapper_.get(), this); | |
73 #if defined(USE_PULSEAUDIO) | |
74 } | |
75 #endif | |
76 ++active_output_stream_count_; | |
77 DCHECK(stream); | |
78 return stream; | |
79 } | 50 } |
80 | 51 |
81 AudioInputStream* AudioManagerLinux::MakeAudioInputStream( | |
82 const AudioParameters& params, const std::string& device_id) { | |
83 if (!params.IsValid() || params.channels > kMaxInputChannels || | |
84 device_id.empty()) { | |
85 return NULL; | |
86 } | |
87 | |
88 if (params.format == AudioParameters::AUDIO_MOCK) { | |
89 return FakeAudioInputStream::MakeFakeStream(params); | |
90 } | |
91 | |
92 std::string device_name = (device_id == AudioManagerBase::kDefaultDeviceId) ? | |
93 AlsaPcmInputStream::kAutoSelectDevice : device_id; | |
94 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) { | |
95 device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
96 switches::kAlsaInputDevice); | |
97 } | |
98 | |
99 AlsaPcmInputStream* stream = new AlsaPcmInputStream(this, | |
100 device_name, params, wrapper_.get()); | |
101 | |
102 return stream; | |
103 } | |
104 | |
105 AudioManagerLinux::AudioManagerLinux() : active_output_stream_count_(0U) {} | |
106 | |
107 AudioManagerLinux::~AudioManagerLinux() { | 52 AudioManagerLinux::~AudioManagerLinux() { |
108 Shutdown(); | 53 Shutdown(); |
109 // All the streams should have been deleted on the audio thread via Shutdown. | |
110 CHECK_EQ(active_output_stream_count_, 0U); | |
111 } | 54 } |
112 | 55 |
113 void AudioManagerLinux::Init() { | 56 void AudioManagerLinux::Init() { |
114 AudioManagerBase::Init(); | 57 AudioManagerBase::Init(); |
115 wrapper_.reset(new AlsaWrapper()); | 58 wrapper_.reset(new AlsaWrapper()); |
116 } | 59 } |
117 | 60 |
118 void AudioManagerLinux::MuteAll() { | 61 void AudioManagerLinux::MuteAll() { |
119 NOTIMPLEMENTED(); | 62 NOTIMPLEMENTED(); |
120 } | 63 } |
121 | 64 |
122 void AudioManagerLinux::UnMuteAll() { | 65 void AudioManagerLinux::UnMuteAll() { |
123 NOTIMPLEMENTED(); | 66 NOTIMPLEMENTED(); |
124 } | 67 } |
125 | 68 |
126 void AudioManagerLinux::ReleaseOutputStream(AudioOutputStream* stream) { | |
127 if (stream) { | |
128 delete stream; | |
129 --active_output_stream_count_; | |
130 DCHECK_GE(active_output_stream_count_, 0U); | |
131 } | |
132 } | |
133 | |
134 bool AudioManagerLinux::CanShowAudioInputSettings() { | 69 bool AudioManagerLinux::CanShowAudioInputSettings() { |
135 scoped_ptr<base::Environment> env(base::Environment::Create()); | 70 scoped_ptr<base::Environment> env(base::Environment::Create()); |
136 base::nix::DesktopEnvironment desktop = base::nix::GetDesktopEnvironment( | 71 base::nix::DesktopEnvironment desktop = base::nix::GetDesktopEnvironment( |
137 env.get()); | 72 env.get()); |
138 return (desktop == base::nix::DESKTOP_ENVIRONMENT_GNOME || | 73 return (desktop == base::nix::DESKTOP_ENVIRONMENT_GNOME || |
139 desktop == base::nix::DESKTOP_ENVIRONMENT_KDE3 || | 74 desktop == base::nix::DESKTOP_ENVIRONMENT_KDE3 || |
140 desktop == base::nix::DESKTOP_ENVIRONMENT_KDE4); | 75 desktop == base::nix::DESKTOP_ENVIRONMENT_KDE4); |
141 } | 76 } |
142 | 77 |
143 void AudioManagerLinux::ShowAudioInputSettings() { | 78 void AudioManagerLinux::ShowAudioInputSettings() { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 hints = NULL; | 231 hints = NULL; |
297 } else { | 232 } else { |
298 DLOG(WARNING) << "HasAnyAudioDevice: unable to get device hints: " | 233 DLOG(WARNING) << "HasAnyAudioDevice: unable to get device hints: " |
299 << wrapper_->StrError(error); | 234 << wrapper_->StrError(error); |
300 } | 235 } |
301 } | 236 } |
302 | 237 |
303 return has_device; | 238 return has_device; |
304 } | 239 } |
305 | 240 |
| 241 AudioOutputStream* AudioManagerLinux::MakeLinearOutputStream( |
| 242 const AudioParameters& params) { |
| 243 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format); |
| 244 return MakeOutputStream(params); |
| 245 } |
| 246 |
| 247 AudioOutputStream* AudioManagerLinux::MakeLowLatencyOutputStream( |
| 248 const AudioParameters& params) { |
| 249 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format); |
| 250 return MakeOutputStream(params); |
| 251 } |
| 252 |
| 253 AudioInputStream* AudioManagerLinux::MakeLinearInputStream( |
| 254 const AudioParameters& params, const std::string& device_id) { |
| 255 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format); |
| 256 return MakeInputStream(params, device_id); |
| 257 } |
| 258 |
| 259 AudioInputStream* AudioManagerLinux::MakeLowLatencyInputStream( |
| 260 const AudioParameters& params, const std::string& device_id) { |
| 261 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format); |
| 262 return MakeInputStream(params, device_id); |
| 263 } |
| 264 |
| 265 AudioOutputStream* AudioManagerLinux::MakeOutputStream( |
| 266 const AudioParameters& params) { |
| 267 AudioOutputStream* stream = NULL; |
| 268 #if defined(USE_PULSEAUDIO) |
| 269 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUsePulseAudio)) { |
| 270 stream = new PulseAudioOutputStream(params, this); |
| 271 } else { |
| 272 #endif |
| 273 std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice; |
| 274 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 275 switches::kAlsaOutputDevice)) { |
| 276 device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 277 switches::kAlsaOutputDevice); |
| 278 } |
| 279 stream = new AlsaPcmOutputStream(device_name, params, wrapper_.get(), this); |
| 280 #if defined(USE_PULSEAUDIO) |
| 281 } |
| 282 #endif |
| 283 DCHECK(stream); |
| 284 return stream; |
| 285 } |
| 286 |
| 287 AudioInputStream* AudioManagerLinux::MakeInputStream( |
| 288 const AudioParameters& params, const std::string& device_id) { |
| 289 if (params.channels > kMaxInputChannels) |
| 290 return NULL; |
| 291 |
| 292 std::string device_name = (device_id == AudioManagerBase::kDefaultDeviceId) ? |
| 293 AlsaPcmInputStream::kAutoSelectDevice : device_id; |
| 294 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) { |
| 295 device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 296 switches::kAlsaInputDevice); |
| 297 } |
| 298 |
| 299 return new AlsaPcmInputStream(this, device_name, params, wrapper_.get()); |
| 300 } |
| 301 |
306 AudioManager* CreateAudioManager() { | 302 AudioManager* CreateAudioManager() { |
307 return new AudioManagerLinux(); | 303 return new AudioManagerLinux(); |
308 } | 304 } |
OLD | NEW |