| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/alsa_input.h" | 5 #include "media/audio/linux/alsa_input.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/time.h" | 11 #include "base/time.h" |
| 12 #include "media/audio/audio_manager.h" | 12 #include "media/audio/audio_manager.h" |
| 13 #include "media/audio/linux/alsa_output.h" | 13 #include "media/audio/linux/alsa_output.h" |
| 14 #include "media/audio/linux/alsa_util.h" | 14 #include "media/audio/linux/alsa_util.h" |
| 15 #include "media/audio/linux/alsa_wrapper.h" | 15 #include "media/audio/linux/alsa_wrapper.h" |
| 16 #include "media/audio/linux/audio_manager_linux.h" | 16 #include "media/audio/linux/audio_manager_linux.h" |
| 17 | 17 |
| 18 static const int kNumPacketsInRingBuffer = 3; | 18 static const int kNumPacketsInRingBuffer = 3; |
| 19 | 19 |
| 20 static const char kDefaultDevice1[] = "default"; | 20 static const char kDefaultDevice1[] = "default"; |
| 21 static const char kDefaultDevice2[] = "plug:default"; | 21 static const char kDefaultDevice2[] = "plug:default"; |
| 22 | 22 |
| 23 const char* AlsaPcmInputStream::kAutoSelectDevice = ""; | 23 const char* AlsaPcmInputStream::kAutoSelectDevice = ""; |
| 24 | 24 |
| 25 AlsaPcmInputStream::AlsaPcmInputStream(const std::string& device_name, | 25 AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerLinux* audio_manager, |
| 26 const std::string& device_name, |
| 26 const AudioParameters& params, | 27 const AudioParameters& params, |
| 27 AlsaWrapper* wrapper) | 28 AlsaWrapper* wrapper) |
| 28 : device_name_(device_name), | 29 : audio_manager_(audio_manager), |
| 30 device_name_(device_name), |
| 29 params_(params), | 31 params_(params), |
| 30 bytes_per_packet_(params.samples_per_packet * | 32 bytes_per_packet_(params.samples_per_packet * |
| 31 (params.channels * params.bits_per_sample) / 8), | 33 (params.channels * params.bits_per_sample) / 8), |
| 32 wrapper_(wrapper), | 34 wrapper_(wrapper), |
| 33 packet_duration_ms_( | 35 packet_duration_ms_( |
| 34 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) / | 36 (params.samples_per_packet * base::Time::kMillisecondsPerSecond) / |
| 35 params.sample_rate), | 37 params.sample_rate), |
| 36 callback_(NULL), | 38 callback_(NULL), |
| 37 device_handle_(NULL), | 39 device_handle_(NULL), |
| 38 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 40 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 // packet might have got filled, to accommodate some delays in the audio | 105 // packet might have got filled, to accommodate some delays in the audio |
| 104 // driver. This could also give us a smooth read sequence going forward. | 106 // driver. This could also give us a smooth read sequence going forward. |
| 105 int64 delay_ms = packet_duration_ms_ + packet_duration_ms_ / 2; | 107 int64 delay_ms = packet_duration_ms_ + packet_duration_ms_ / 2; |
| 106 next_read_time_ = base::Time::Now() + base::TimeDelta::FromMilliseconds( | 108 next_read_time_ = base::Time::Now() + base::TimeDelta::FromMilliseconds( |
| 107 delay_ms); | 109 delay_ms); |
| 108 MessageLoop::current()->PostDelayedTask( | 110 MessageLoop::current()->PostDelayedTask( |
| 109 FROM_HERE, | 111 FROM_HERE, |
| 110 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), | 112 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), |
| 111 delay_ms); | 113 delay_ms); |
| 112 | 114 |
| 113 static_cast<AudioManagerLinux*>(AudioManager::GetAudioManager())-> | 115 audio_manager_->IncreaseActiveInputStreamCount(); |
| 114 IncreaseActiveInputStreamCount(); | |
| 115 } | 116 } |
| 116 } | 117 } |
| 117 | 118 |
| 118 bool AlsaPcmInputStream::Recover(int original_error) { | 119 bool AlsaPcmInputStream::Recover(int original_error) { |
| 119 int error = wrapper_->PcmRecover(device_handle_, original_error, 1); | 120 int error = wrapper_->PcmRecover(device_handle_, original_error, 1); |
| 120 if (error < 0) { | 121 if (error < 0) { |
| 121 // Docs say snd_pcm_recover returns the original error if it is not one | 122 // Docs say snd_pcm_recover returns the original error if it is not one |
| 122 // of the recoverable ones, so this log message will probably contain the | 123 // of the recoverable ones, so this log message will probably contain the |
| 123 // same error twice. | 124 // same error twice. |
| 124 LOG(WARNING) << "Unable to recover from \"" | 125 LOG(WARNING) << "Unable to recover from \"" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), | 218 base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()), |
| 218 delay_ms); | 219 delay_ms); |
| 219 } | 220 } |
| 220 | 221 |
| 221 void AlsaPcmInputStream::Stop() { | 222 void AlsaPcmInputStream::Stop() { |
| 222 if (!device_handle_ || !callback_) | 223 if (!device_handle_ || !callback_) |
| 223 return; | 224 return; |
| 224 | 225 |
| 225 // Stop is always called before Close. In case of error, this will be | 226 // Stop is always called before Close. In case of error, this will be |
| 226 // also called when closing the input controller. | 227 // also called when closing the input controller. |
| 227 static_cast<AudioManagerLinux*>(AudioManager::GetAudioManager())-> | 228 audio_manager_->DecreaseActiveInputStreamCount(); |
| 228 DecreaseActiveInputStreamCount(); | |
| 229 | 229 |
| 230 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. | 230 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. |
| 231 int error = wrapper_->PcmDrop(device_handle_); | 231 int error = wrapper_->PcmDrop(device_handle_); |
| 232 if (error < 0) | 232 if (error < 0) |
| 233 HandleError("PcmDrop", error); | 233 HandleError("PcmDrop", error); |
| 234 } | 234 } |
| 235 | 235 |
| 236 void AlsaPcmInputStream::Close() { | 236 void AlsaPcmInputStream::Close() { |
| 237 scoped_ptr<AlsaPcmInputStream> self_deleter(this); | 237 scoped_ptr<AlsaPcmInputStream> self_deleter(this); |
| 238 | 238 |
| 239 // Check in case we were already closed or not initialized yet. | 239 // Check in case we were already closed or not initialized yet. |
| 240 if (!device_handle_ || !callback_) | 240 if (!device_handle_ || !callback_) |
| 241 return; | 241 return; |
| 242 | 242 |
| 243 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. | 243 weak_factory_.InvalidateWeakPtrs(); // Cancel the next scheduled read. |
| 244 int error = alsa_util::CloseDevice(wrapper_, device_handle_); | 244 int error = alsa_util::CloseDevice(wrapper_, device_handle_); |
| 245 if (error < 0) | 245 if (error < 0) |
| 246 HandleError("PcmClose", error); | 246 HandleError("PcmClose", error); |
| 247 | 247 |
| 248 audio_packet_.reset(); | 248 audio_packet_.reset(); |
| 249 device_handle_ = NULL; | 249 device_handle_ = NULL; |
| 250 callback_->OnClose(this); | 250 callback_->OnClose(this); |
| 251 } | 251 } |
| 252 | 252 |
| 253 void AlsaPcmInputStream::HandleError(const char* method, int error) { | 253 void AlsaPcmInputStream::HandleError(const char* method, int error) { |
| 254 LOG(WARNING) << method << ": " << wrapper_->StrError(error); | 254 LOG(WARNING) << method << ": " << wrapper_->StrError(error); |
| 255 callback_->OnError(this, error); | 255 callback_->OnError(this, error); |
| 256 } | 256 } |
| OLD | NEW |