blob: 441cfbe517fcdeb826bdac0ca885af4d497ee54d [file] [log] [blame]
// Copyright 2019 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 "chromecast/media/cma/backend/mixer/mixer_service_receiver.h"
#include <string>
#include <utility>
#include "base/logging.h"
#include "chromecast/media/audio/mixer_service/conversions.h"
#include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
#include "chromecast/media/audio/mixer_service/mixer_socket.h"
#include "chromecast/media/cma/backend/mixer/mixer_input_connection.h"
#include "chromecast/media/cma/backend/mixer/stream_mixer.h"
namespace chromecast {
namespace media {
class MixerServiceReceiver::ControlConnection
: public mixer_service::MixerSocket::Delegate {
public:
ControlConnection(StreamMixer* mixer,
MixerServiceReceiver* receiver,
std::unique_ptr<mixer_service::MixerSocket> socket)
: mixer_(mixer), receiver_(receiver), socket_(std::move(socket)) {
DCHECK(mixer_);
DCHECK(receiver_);
DCHECK(socket_);
socket_->SetDelegate(this);
}
~ControlConnection() override = default;
void OnStreamCountChanged() {
if (!send_stream_count_) {
return;
}
mixer_service::Generic message;
auto* counts = message.mutable_stream_count();
counts->set_primary(receiver_->primary_stream_count_);
counts->set_sfx(receiver_->sfx_stream_count_);
socket_->SendProto(message);
}
private:
friend class MixerServiceReceiver;
// mixer_service::MixerSocket::Delegate implementation:
bool HandleMetadata(const mixer_service::Generic& message) override {
if (message.has_set_volume_limit()) {
mixer_->SetOutputLimit(
mixer_service::ConvertContentType(
message.set_volume_limit().content_type()),
message.set_volume_limit().max_volume_multiplier());
}
if (message.has_set_device_muted()) {
mixer_->SetMuted(mixer_service::ConvertContentType(
message.set_device_muted().content_type()),
message.set_device_muted().muted());
}
if (message.has_set_device_volume()) {
mixer_->SetVolume(mixer_service::ConvertContentType(
message.set_device_volume().content_type()),
message.set_device_volume().volume_multiplier());
}
if (message.has_configure_postprocessor()) {
mixer_->SetPostProcessorConfig(
message.configure_postprocessor().name(),
message.configure_postprocessor().config());
}
if (message.has_reload_postprocessors()) {
mixer_->ResetPostProcessors([](bool, const std::string&) {});
}
if (message.has_request_stream_count()) {
send_stream_count_ = message.request_stream_count().subscribe();
OnStreamCountChanged();
}
return true;
}
bool HandleAudioData(char* data, int size, int64_t timestamp) override {
return true;
}
bool HandleAudioBuffer(scoped_refptr<net::IOBuffer> buffer,
char* data,
int size,
int64_t timestamp) override {
return true;
}
void OnConnectionError() override {
receiver_->RemoveControlConnection(this);
}
StreamMixer* const mixer_;
MixerServiceReceiver* const receiver_;
const std::unique_ptr<mixer_service::MixerSocket> socket_;
bool send_stream_count_ = false;
DISALLOW_COPY_AND_ASSIGN(ControlConnection);
};
MixerServiceReceiver::MixerServiceReceiver(StreamMixer* mixer) : mixer_(mixer) {
DCHECK(mixer_);
}
MixerServiceReceiver::~MixerServiceReceiver() = default;
void MixerServiceReceiver::OnStreamCountChanged(int primary, int sfx) {
primary_stream_count_ = primary;
sfx_stream_count_ = sfx;
for (const auto& control : control_connections_) {
control.second->OnStreamCountChanged();
}
}
void MixerServiceReceiver::CreateOutputStream(
std::unique_ptr<mixer_service::MixerSocket> socket,
const mixer_service::Generic& message) {
DCHECK(message.has_output_stream_params());
// MixerInputConnection manages its own lifetime.
auto* connection = new MixerInputConnection(mixer_, std::move(socket),
message.output_stream_params());
connection->HandleMetadata(message);
}
void MixerServiceReceiver::CreateLoopbackConnection(
std::unique_ptr<mixer_service::MixerSocket> socket,
const mixer_service::Generic& message) {
LOG(INFO) << "Unhandled loopback connection";
}
void MixerServiceReceiver::CreateAudioRedirection(
std::unique_ptr<mixer_service::MixerSocket> socket,
const mixer_service::Generic& message) {
LOG(INFO) << "Unhandled redirection connection";
}
void MixerServiceReceiver::CreateControlConnection(
std::unique_ptr<mixer_service::MixerSocket> socket,
const mixer_service::Generic& message) {
auto connection =
std::make_unique<ControlConnection>(mixer_, this, std::move(socket));
ControlConnection* ptr = connection.get();
control_connections_[ptr] = std::move(connection);
ptr->HandleMetadata(message);
}
void MixerServiceReceiver::RemoveControlConnection(ControlConnection* ptr) {
control_connections_.erase(ptr);
}
} // namespace media
} // namespace chromecast