text: // 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_loopback_connection.h"
  
  #include <utility>
  
  #include "base/check.h"
  #include "chromecast/media/audio/mixer_service/conversions.h"
  #include "chromecast/media/audio/mixer_service/loopback_interrupt_reason.h"
  #include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
  #include "chromecast/net/io_buffer_pool.h"
  
  namespace chromecast {
  namespace media {
  
  namespace {
  
  enum MessageTypes : int {
    kStreamConfig = 1,
    kInterrupt,
  };
  
  }  // namespace
  
  MixerLoopbackConnection::MixerLoopbackConnection(
      std::unique_ptr<mixer_service::MixerSocket> socket)
      : socket_(std::move(socket)) {
    DCHECK(socket_);
    socket_->SetDelegate(this);
  }
  
  MixerLoopbackConnection::~MixerLoopbackConnection() = default;
  
  void MixerLoopbackConnection::SetErrorCallback(base::OnceClosure callback) {
    if (pending_error_) {
      pending_error_ = false;
      std::move(callback).Run();
      return;
    }
    error_callback_ = std::move(callback);
  }
  
  void MixerLoopbackConnection::SetStreamConfig(SampleFormat sample_format,
                                                int sample_rate,
                                                int num_channels,
                                                int data_size) {
    mixer_service::Generic message;
    mixer_service::StreamConfig* config = message.mutable_stream_config();
    config->set_sample_format(mixer_service::ConvertSampleFormat(sample_format));
    config->set_sample_rate(sample_rate);
    config->set_num_channels(num_channels);
    config->set_data_size(data_size);
    socket_->SendProto(kStreamConfig, message);
  
    sent_stream_config_ = true;
  }
  
  void MixerLoopbackConnection::SendAudio(
      scoped_refptr<net::IOBuffer> audio_buffer,
      int data_size_bytes,
      int64_t timestamp) {
    DCHECK(sent_stream_config_);
    if (!socket_->SendAudioBuffer(std::move(audio_buffer), data_size_bytes,
                                  timestamp)) {
      SendInterrupt(LoopbackInterruptReason::kSocketOverflow);
    }
  }
  
  void MixerLoopbackConnection::SendInterrupt(LoopbackInterruptReason reason) {
    mixer_service::Generic message;
    mixer_service::StreamInterruption* interrupt =
        message.mutable_stream_interruption();
    interrupt->set_reason(
        static_cast<mixer_service::StreamInterruption::InterruptionReason>(
            reason));
    socket_->SendProto(kInterrupt, message);
  }
  
  bool MixerLoopbackConnection::HandleMetadata(
      const mixer_service::Generic& message) {
    return true;
  }
  
  bool MixerLoopbackConnection::HandleAudioData(char* data,
                                                size_t size,
                                                int64_t timestamp) {
    return true;
  }
  
  void MixerLoopbackConnection::OnConnectionError() {
    if (error_callback_) {
      std::move(error_callback_).Run();
      return;
    }
    pending_error_ = true;
  }
  
  }  // namespace media
  }  // namespace chromecast
  