#ifndef SERVICES_AUDIO_OUTPUT_STREAM_H_
#define SERVICES_AUDIO_OUTPUT_STREAM_H_
#include <memory>
#include <string>
#include <string_view>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/sync_socket.h"
#include "base/timer/timer.h"
#include "media/mojo/mojom/audio_data_pipe.mojom.h"
#include "media/mojo/mojom/audio_logging.mojom.h"
#include "media/mojo/mojom/audio_output_stream.mojom.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
#include "mojo/public/cpp/system/buffer.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "services/audio/loopback_coordinator.h"
#include "services/audio/output_controller.h"
#include "services/audio/sync_reader.h"
namespace base {
class UnguessableToken;
}
namespace media {
class AudioManager;
class AudioParameters;
}
namespace audio {
class OutputStream final : public media::mojom::AudioOutputStream,
public media::mojom::DeviceSwitchInterface,
public OutputController::EventHandler {
public:
using DeleteCallback = base::OnceCallback<void(OutputStream*)>;
using CreatedCallback =
base::OnceCallback<void(media::mojom::ReadWriteAudioDataPipePtr)>;
using ManagedDeviceOutputStreamCreateCallback =
OutputController::ManagedDeviceOutputStreamCreateCallback;
OutputStream(
CreatedCallback created_callback,
DeleteCallback delete_callback,
ManagedDeviceOutputStreamCreateCallback
managed_device_output_stream_create_callback,
mojo::PendingReceiver<media::mojom::AudioOutputStream> stream_receiver,
mojo::PendingReceiver<media::mojom::DeviceSwitchInterface>
device_switch_receiver,
mojo::PendingAssociatedRemote<media::mojom::AudioOutputStreamObserver>
observer,
mojo::PendingRemote<media::mojom::AudioLog> log,
media::AudioManager* audio_manager,
const std::string& output_device_id,
const media::AudioParameters& params,
LoopbackCoordinator* coordinator,
const base::UnguessableToken& loopback_group_id);
OutputStream(const OutputStream&) = delete;
OutputStream& operator=(const OutputStream&) = delete;
~OutputStream() final;
void Play() final;
void Pause() final;
void Flush() final;
void SetVolume(double volume) final;
void SwitchAudioOutputDeviceId(const std::string& output_device_id) final;
void OnControllerPlaying() final;
void OnControllerPaused() final;
void OnControllerError() final;
void OnLog(std::string_view message) final;
private:
friend class AudibilityHelperImpl;
friend class OutputStreamAudibilityHelperTest;
class AudibilityHelper {
public:
using GetPowerLevelCB = base::RepeatingCallback<float()>;
using OnAudibleStateChangedCB =
base::RepeatingCallback<void(bool is_audible)>;
AudibilityHelper() = default;
virtual ~AudibilityHelper() = default;
virtual void StartPolling(
GetPowerLevelCB get_power_level_cb,
OnAudibleStateChangedCB on_audible_state_changed_cb) = 0;
virtual void StopPolling() = 0;
virtual bool IsAudible() = 0;
};
static std::unique_ptr<AudibilityHelper> MakeAudibilityHelperForTest();
void CreateAudioPipe(CreatedCallback created_callback);
void OnError();
void CallDeleter();
void OnAudibleStateChanged(bool is_audible);
PRINTF_FORMAT(2, 3) void SendLogMessage(const char* format, ...);
SEQUENCE_CHECKER(owning_sequence_);
base::CancelableSyncSocket foreign_socket_;
DeleteCallback delete_callback_;
mojo::Receiver<AudioOutputStream> receiver_;
mojo::Receiver<DeviceSwitchInterface> device_switch_receiver_;
mojo::AssociatedRemote<media::mojom::AudioOutputStreamObserver> observer_;
const mojo::SharedRemote<media::mojom::AudioLog> log_;
const raw_ptr<LoopbackCoordinator> coordinator_;
SyncReader reader_;
OutputController controller_;
const base::UnguessableToken loopback_group_id_;
bool playing_ = false;
std::unique_ptr<AudibilityHelper> audibility_helper_;
base::WeakPtrFactory<OutputStream> weak_factory_{this};
};
}
#endif