blob: 82b1dc9189120b66ea3762c796d7ac83ea8cf712 [file] [log] [blame]
// 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.
#include "src/media/audio/audio_core/audio_core_impl.h"
#include <lib/async/cpp/task.h>
#include "src/media/audio/audio_core/audio_admin.h"
#include "src/media/audio/audio_core/audio_capturer.h"
#include "src/media/audio/audio_core/audio_device_manager.h"
#include "src/media/audio/audio_core/audio_renderer.h"
#include "src/media/audio/audio_core/process_config.h"
#include "src/media/audio/audio_core/stream_usage.h"
#include "src/media/audio/audio_core/throttle_output.h"
#include "src/media/audio/lib/format/format.h"
#include "src/media/audio/lib/logging/logging.h"
namespace media::audio {
AudioCoreImpl::AudioCoreImpl(Context* context) : context_(*context) {
FX_DCHECK(context);
// The main async_t here is responsible for receiving audio payloads sent by applications, so it
// has real time requirements just like mixing threads. Ideally, this task would not run on the
// same thread that processes *all* non-mix audio service jobs (even non-realtime ones), but that
// will take more significant restructuring, when we can deal with realtime requirements in place.
AcquireAudioCoreImplProfile(&context_.component_context(),
[](zx_status_t status, zx::profile profile) {
FX_DCHECK(profile);
FX_DCHECK(status == ZX_OK);
if (status == ZX_OK && profile) {
status = zx::thread::self()->set_profile(profile, 0);
FX_DCHECK(status == ZX_OK);
}
});
// Set up our audio policy.
LoadDefaults();
context_.component_context().outgoing()->AddPublicService(bindings_.GetHandler(this));
}
AudioCoreImpl::~AudioCoreImpl() { Shutdown(); }
void AudioCoreImpl::Shutdown() {
TRACE_DURATION("audio", "AudioCoreImpl::Shutdown");
context_.device_manager().Shutdown();
}
void AudioCoreImpl::CreateAudioRenderer(
fidl::InterfaceRequest<fuchsia::media::AudioRenderer> audio_renderer_request) {
TRACE_DURATION("audio", "AudioCoreImpl::CreateAudioRenderer");
AUDIO_LOG(DEBUG);
context_.route_graph().AddRenderer(
AudioRenderer::Create(std::move(audio_renderer_request), &context_));
}
void AudioCoreImpl::CreateAudioCapturerWithConfiguration(
fuchsia::media::AudioStreamType stream_type,
fuchsia::media::AudioCapturerConfiguration configuration,
fidl::InterfaceRequest<fuchsia::media::AudioCapturer> audio_capturer_request) {
auto format = Format::Create(stream_type);
if (format.is_error()) {
FX_LOGS(WARNING) << "Attempted to create AudioCapturer with invalid stream type";
return;
}
context_.route_graph().AddCapturer(AudioCapturer::Create(
std::move(configuration), std::make_optional<Format>(format.take_value()),
std::move(audio_capturer_request), &context_));
}
void AudioCoreImpl::CreateAudioCapturer(
bool loopback, fidl::InterfaceRequest<fuchsia::media::AudioCapturer> audio_capturer_request) {
TRACE_DURATION("audio", "AudioCoreImpl::CreateAudioCapturer");
AUDIO_LOG(DEBUG);
auto configuration = loopback ? fuchsia::media::AudioCapturerConfiguration::WithLoopback(
fuchsia::media::LoopbackAudioCapturerConfiguration())
: fuchsia::media::AudioCapturerConfiguration::WithInput(
fuchsia::media::InputAudioCapturerConfiguration());
context_.route_graph().AddCapturer(
AudioCapturer::Create(std::move(configuration), /*format= */ std::nullopt,
std::move(audio_capturer_request), &context_));
}
void AudioCoreImpl::SetRenderUsageGain(fuchsia::media::AudioRenderUsage render_usage,
float gain_db) {
TRACE_DURATION("audio", "AudioCoreImpl::SetRenderUsageGain");
context_.volume_manager().SetUsageGain(
fuchsia::media::Usage::WithRenderUsage(std::move(render_usage)), gain_db);
}
void AudioCoreImpl::SetCaptureUsageGain(fuchsia::media::AudioCaptureUsage capture_usage,
float gain_db) {
TRACE_DURATION("audio", "AudioCoreImpl::SetCaptureUsageGain");
context_.volume_manager().SetUsageGain(
fuchsia::media::Usage::WithCaptureUsage(std::move(capture_usage)), gain_db);
}
void AudioCoreImpl::BindUsageVolumeControl(
fuchsia::media::Usage usage,
fidl::InterfaceRequest<fuchsia::media::audio::VolumeControl> volume_control) {
TRACE_DURATION("audio", "AudioCoreImpl::BindUsageVolumeControl");
if (usage.is_render_usage()) {
context_.volume_manager().BindUsageVolumeClient(std::move(usage), std::move(volume_control));
} else {
volume_control.Close(ZX_ERR_NOT_SUPPORTED);
}
}
void AudioCoreImpl::SetInteraction(fuchsia::media::Usage active, fuchsia::media::Usage affected,
fuchsia::media::Behavior behavior) {
TRACE_DURATION("audio", "AudioCoreImpl::SetInteraction");
context_.audio_admin().SetInteraction(std::move(active), std::move(affected), behavior);
}
void AudioCoreImpl::LoadDefaults() {
TRACE_DURATION("audio", "AudioCoreImpl::LoadDefaults");
auto policy = PolicyLoader::LoadPolicy();
context_.audio_admin().SetInteractionsFromAudioPolicy(std::move(policy));
}
void AudioCoreImpl::ResetInteractions() {
TRACE_DURATION("audio", "AudioCoreImpl::ResetInteractions");
context_.audio_admin().ResetInteractions();
}
} // namespace media::audio