| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_AUDIO_CORE_IMPL_H_ |
| #define SRC_MEDIA_AUDIO_AUDIO_CORE_AUDIO_CORE_IMPL_H_ |
| |
| #include <fbl/intrusive_double_list.h> |
| #include <fbl/unique_ptr.h> |
| #include <fuchsia/media/cpp/fidl.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/sys/cpp/component_context.h> |
| |
| #include <mutex> |
| |
| #include "lib/fidl/cpp/binding_set.h" |
| #include "src/lib/fxl/macros.h" |
| #include "src/lib/fxl/synchronization/thread_annotations.h" |
| #include "src/media/audio/audio_core/audio_device_manager.h" |
| #include "src/media/audio/audio_core/audio_packet_ref.h" |
| #include "src/media/audio/audio_core/fwd_decls.h" |
| #include "src/media/audio/audio_core/pending_flush_token.h" |
| |
| namespace component { |
| class Services; |
| } |
| |
| namespace media::audio { |
| |
| class AudioCoreImpl : public fuchsia::media::AudioCore { |
| public: |
| AudioCoreImpl(std::unique_ptr<sys::ComponentContext> startup_context); |
| ~AudioCoreImpl() override; |
| |
| // Audio implementation. |
| void CreateAudioRenderer(fidl::InterfaceRequest<fuchsia::media::AudioRenderer> |
| audio_renderer_request) final; |
| |
| void CreateAudioCapturer(bool loopback, |
| fidl::InterfaceRequest<fuchsia::media::AudioCapturer> |
| audio_capturer_request) final; |
| |
| void SetSystemGain(float gain_db) final; |
| void SetSystemMute(bool muted) final; |
| |
| void SetRoutingPolicy(fuchsia::media::AudioOutputRoutingPolicy policy) final; |
| |
| void EnableDeviceSettings(bool enabled) final; |
| |
| // Called (indirectly) by AudioOutputs to schedule the callback for a |
| // packet was queued to an AudioRenderer. |
| // |
| // TODO(johngro): This bouncing through thread contexts is inefficient and |
| // will increase the latency requirements for clients (its going to take them |
| // some extra time to discover that their media has been completely consumed). |
| // When fidl exposes a way to safely invoke interface method callbacks from |
| // threads other than the thread which executed the method itself, we will |
| // want to switch to creating the callback message directly, instead of |
| // indirecting through the service. |
| void SchedulePacketCleanup(std::unique_ptr<AudioPacketRef> packet); |
| void ScheduleFlushCleanup(std::unique_ptr<PendingFlushToken> token); |
| |
| // Schedule a closure to run on the service's main message loop. |
| void ScheduleMainThreadTask(fit::closure task) { |
| FXL_DCHECK(dispatcher_); |
| async::PostTask(dispatcher_, std::move(task)); |
| } |
| |
| // Direct access to the service's async_t |
| async_dispatcher_t* dispatcher() const { return dispatcher_; } |
| |
| // Accessor for our encapsulated device manager. |
| AudioDeviceManager& GetDeviceManager() { return device_manager_; } |
| |
| float system_gain_db() const { return system_gain_db_; } |
| bool system_muted() const { return system_muted_; } |
| |
| private: |
| static constexpr float kDefaultSystemGainDb = -12.0f; |
| static constexpr bool kDefaultSystemMuted = false; |
| static constexpr float kMaxSystemAudioGainDb = Gain::kUnityGainDb; |
| |
| void NotifyGainMuteChanged(); |
| void PublishServices(); |
| void Shutdown(); |
| void DoPacketCleanup(); |
| |
| fidl::BindingSet<fuchsia::media::AudioCore> bindings_; |
| |
| // A reference to our thread's dispatcher object. Allows us to post events to |
| // be handled by our main application thread from things like the output |
| // manager's thread pool. |
| async_dispatcher_t* dispatcher_; |
| |
| // State for dealing with devices. |
| AudioDeviceManager device_manager_; |
| |
| std::unique_ptr<sys::ComponentContext> ctx_; |
| |
| // State for dealing with cleanup tasks. |
| std::mutex cleanup_queue_mutex_; |
| fbl::DoublyLinkedList<std::unique_ptr<AudioPacketRef>> packet_cleanup_queue_ |
| FXL_GUARDED_BY(cleanup_queue_mutex_); |
| fbl::DoublyLinkedList<std::unique_ptr<PendingFlushToken>> flush_cleanup_queue_ |
| FXL_GUARDED_BY(cleanup_queue_mutex_); |
| bool cleanup_scheduled_ FXL_GUARDED_BY(cleanup_queue_mutex_) = false; |
| bool shutting_down_ = false; |
| |
| // TODO(johngro): remove this state. Migrate users to AudioDeviceEnumerator, |
| // to control gain on a per-input/output basis. |
| // Either way, Gain and Mute should remain fully independent. |
| float system_gain_db_ = kDefaultSystemGainDb; |
| bool system_muted_ = kDefaultSystemMuted; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(AudioCoreImpl); |
| }; |
| |
| } // namespace media::audio |
| |
| #endif // SRC_MEDIA_AUDIO_AUDIO_CORE_AUDIO_CORE_IMPL_H_ |