blob: fda6852d6a902b0fb671271bd0b1f361448dd49c [file] [log] [blame]
// Copyright 2018 The Chromium 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 "services/audio/public/cpp/input_ipc.h"
#include <utility>
#include "base/bind_helpers.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/audio/public/mojom/constants.mojom.h"
namespace audio {
InputIPC::InputIPC(std::unique_ptr<service_manager::Connector> connector,
const std::string& device_id,
media::mojom::AudioLogPtr log)
: stream_(),
stream_client_binding_(this),
device_id_(std::move(device_id)),
stream_factory_(),
stream_factory_info_(),
log_(std::move(log)),
weak_factory_(this) {
DETACH_FROM_SEQUENCE(sequence_checker_);
DCHECK(connector);
connector->BindInterface(audio::mojom::kServiceName,
mojo::MakeRequest(&stream_factory_info_));
}
InputIPC::~InputIPC() = default;
void InputIPC::CreateStream(media::AudioInputIPCDelegate* delegate,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t total_segments) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(delegate);
DCHECK(!delegate_);
delegate_ = delegate;
if (!stream_factory_.is_bound())
stream_factory_.Bind(std::move(stream_factory_info_));
media::mojom::AudioInputStreamRequest stream_request =
mojo::MakeRequest(&stream_);
media::mojom::AudioInputStreamClientPtr client;
stream_client_binding_.Bind(mojo::MakeRequest(&client));
// Unretained is safe because we own the binding.
stream_client_binding_.set_connection_error_handler(
base::BindOnce(&InputIPC::OnError, base::Unretained(this)));
// For now we don't care about key presses, so we pass a invalid buffer.
mojo::ScopedSharedBufferHandle invalid_key_press_count_buffer;
stream_factory_->CreateInputStream(
std::move(stream_request), std::move(client), nullptr,
log_ ? std::move(log_) : nullptr, device_id_, params, total_segments,
automatic_gain_control, std::move(invalid_key_press_count_buffer),
base::BindOnce(&InputIPC::StreamCreated, weak_factory_.GetWeakPtr()));
}
void InputIPC::StreamCreated(media::mojom::AudioDataPipePtr data_pipe,
bool initially_muted) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(delegate_);
if (data_pipe.is_null()) {
OnError();
return;
}
base::PlatformFile socket_handle;
auto result =
mojo::UnwrapPlatformFile(std::move(data_pipe->socket), &socket_handle);
DCHECK_EQ(result, MOJO_RESULT_OK);
base::SharedMemoryHandle memory_handle;
mojo::UnwrappedSharedMemoryHandleProtection protection;
result = mojo::UnwrapSharedMemoryHandle(std::move(data_pipe->shared_memory),
&memory_handle, nullptr, &protection);
DCHECK_EQ(result, MOJO_RESULT_OK);
DCHECK_EQ(protection, mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
delegate_->OnStreamCreated(memory_handle, socket_handle, initially_muted);
}
void InputIPC::RecordStream() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(stream_.is_bound());
stream_->Record();
}
void InputIPC::SetVolume(double volume) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(stream_.is_bound());
stream_->SetVolume(volume);
}
void InputIPC::CloseStream() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
delegate_ = nullptr;
if (stream_client_binding_.is_bound())
stream_client_binding_.Close();
stream_.reset();
}
void InputIPC::OnError() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(delegate_);
delegate_->OnError();
}
void InputIPC::OnMutedStateChanged(bool is_muted) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(delegate_);
delegate_->OnMuted(is_muted);
}
} // namespace audio