device_listener_output_stream.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright (c) 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/audio/device_listener_output_stream.h"
  5. #include "base/bind.h"
  6. #include "base/logging.h"
  7. #include "base/task/single_thread_task_runner.h"
  8. namespace audio {
  9. DeviceListenerOutputStream::DeviceListenerOutputStream(
  10. media::AudioManager* audio_manager,
  11. media::AudioOutputStream* wrapped_stream,
  12. base::OnceClosure on_device_change_callback)
  13. : audio_manager_(audio_manager),
  14. stream_(wrapped_stream),
  15. on_device_change_callback_(std::move(on_device_change_callback)),
  16. task_runner_(audio_manager->GetTaskRunner()) {
  17. DCHECK(task_runner_->BelongsToCurrentThread());
  18. DCHECK(stream_);
  19. audio_manager_->AddOutputDeviceChangeListener(this);
  20. }
  21. DeviceListenerOutputStream::~DeviceListenerOutputStream() {
  22. DCHECK(task_runner_->BelongsToCurrentThread());
  23. audio_manager_->RemoveOutputDeviceChangeListener(this);
  24. }
  25. bool DeviceListenerOutputStream::Open() {
  26. DCHECK(task_runner_->BelongsToCurrentThread());
  27. DCHECK(on_device_change_callback_);
  28. return stream_->Open();
  29. }
  30. void DeviceListenerOutputStream::Start(
  31. media::AudioOutputStream::AudioSourceCallback* source_callback) {
  32. DCHECK(task_runner_->BelongsToCurrentThread());
  33. DCHECK(!source_callback_);
  34. DCHECK(source_callback);
  35. DCHECK(on_device_change_callback_);
  36. source_callback_ = source_callback;
  37. stream_->Start(this);
  38. }
  39. void DeviceListenerOutputStream::Stop() {
  40. DCHECK(task_runner_->BelongsToCurrentThread());
  41. stream_->Stop();
  42. source_callback_ = nullptr;
  43. }
  44. void DeviceListenerOutputStream::SetVolume(double volume) {
  45. stream_->SetVolume(volume);
  46. }
  47. void DeviceListenerOutputStream::GetVolume(double* volume) {
  48. stream_->GetVolume(volume);
  49. }
  50. void DeviceListenerOutputStream::Close() {
  51. DCHECK(task_runner_->BelongsToCurrentThread());
  52. DCHECK(!source_callback_);
  53. // ExtractAsDangling clears the underlying pointer and returns another raw_ptr
  54. // instance that is allowed to dangle.
  55. stream_.ExtractAsDangling()->Close();
  56. // To match a typical AudioOutputStream usage pattern.
  57. delete this;
  58. }
  59. void DeviceListenerOutputStream::Flush() {
  60. stream_->Flush();
  61. }
  62. void DeviceListenerOutputStream::OnDeviceChange() {
  63. DCHECK(task_runner_->BelongsToCurrentThread());
  64. std::move(on_device_change_callback_).Run();
  65. // Close() must have been called and |this| deleted at this point.
  66. }
  67. int DeviceListenerOutputStream::OnMoreData(base::TimeDelta delay,
  68. base::TimeTicks delay_timestamp,
  69. int prior_frames_skipped,
  70. media::AudioBus* dest) {
  71. return source_callback_->OnMoreData(delay, delay_timestamp,
  72. prior_frames_skipped, dest);
  73. }
  74. int DeviceListenerOutputStream::OnMoreData(base::TimeDelta delay,
  75. base::TimeTicks delay_timestamp,
  76. int prior_frames_skipped,
  77. media::AudioBus* dest,
  78. bool is_mixing) {
  79. return source_callback_->OnMoreData(delay, delay_timestamp,
  80. prior_frames_skipped, dest, is_mixing);
  81. }
  82. void DeviceListenerOutputStream::OnError(ErrorType type) {
  83. if (type == ErrorType::kDeviceChange) {
  84. task_runner_->PostTask(
  85. FROM_HERE, base::BindOnce(&DeviceListenerOutputStream::OnDeviceChange,
  86. weak_factory_.GetWeakPtr()));
  87. return;
  88. }
  89. // Handles errors on the audio manager thread. We defer errors for one
  90. // second in case they are the result of a device change; delay chosen to
  91. // exceed duration of device changes which take a few hundred milliseconds.
  92. // |this| will be deleted after the client processes the device change, that
  93. // way the posted callback will be cancelled.
  94. task_runner_->PostDelayedTask(
  95. FROM_HERE,
  96. base::BindOnce(&DeviceListenerOutputStream::ReportError,
  97. weak_factory_.GetWeakPtr(), type),
  98. base::Seconds(1));
  99. }
  100. void DeviceListenerOutputStream::ReportError(ErrorType type) {
  101. DCHECK(task_runner_->BelongsToCurrentThread());
  102. DCHECK_NE(type, ErrorType::kDeviceChange);
  103. if (source_callback_)
  104. source_callback_->OnError(type);
  105. }
  106. } // namespace audio