blob: 969cff1486e84298040ca236d33a1fdfc252bc55 [file] [log] [blame]
// Copyright 2023 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.
#ifndef SRC_MEDIA_AUDIO_CONSUMER_CONSUMER_H_
#define SRC_MEDIA_AUDIO_CONSUMER_CONSUMER_H_
#include <fidl/fuchsia.media/cpp/fidl.h>
#include <lib/async/dispatcher.h>
#include <lib/fidl/cpp/unified_messaging_declarations.h>
#include <lib/media/cpp/timeline_function.h>
#include <memory>
namespace media::audio {
class Consumer : public fidl::Server<fuchsia_media::AudioConsumer>,
public fidl::Server<fuchsia_media::StreamSink>,
public fidl::Server<fuchsia_media_audio::VolumeControl>,
public fidl::AsyncEventHandler<fuchsia_media::AudioRenderer>,
public std::enable_shared_from_this<Consumer> {
public:
// Creates a |Consumer| and binds it to |server_end|. |audio_core_client_end| is supplied here
// to enable dependency injection.
static void CreateAndBind(async_dispatcher_t* dispatcher,
fidl::ClientEnd<fuchsia_media::AudioCore> audio_core_client_end,
fidl::ServerEnd<fuchsia_media::AudioConsumer> server_end);
Consumer(async_dispatcher_t* dispatcher,
fidl::ClientEnd<fuchsia_media::AudioCore> audio_core_client_end);
~Consumer() override = default;
// Disallow copy, assign and move.
Consumer(const Consumer&) = delete;
Consumer& operator=(const Consumer&) = delete;
Consumer(Consumer&&) = delete;
Consumer& operator=(Consumer&&) = delete;
// fuchsia_media::AudioConsumer implementation.
void CreateStreamSink(CreateStreamSinkRequest& request,
CreateStreamSinkCompleter::Sync& completer) override;
void Start(StartRequest& request, StartCompleter::Sync& completer) override;
void Stop(StopCompleter::Sync& completer) override;
void SetRate(SetRateRequest& request, SetRateCompleter::Sync& completer) override;
void BindVolumeControl(BindVolumeControlRequest& request,
BindVolumeControlCompleter::Sync& completer) override;
void WatchStatus(WatchStatusCompleter::Sync& completer) override;
// fuchsia_media::StreamSink implementation.
void SendPacket(SendPacketRequest& request, SendPacketCompleter::Sync& completer) override;
void SendPacketNoReply(SendPacketNoReplyRequest& request,
SendPacketNoReplyCompleter::Sync& completer) override;
void EndOfStream(EndOfStreamCompleter::Sync& completer) override;
void DiscardAllPackets(DiscardAllPacketsCompleter::Sync& completer) override;
void DiscardAllPacketsNoReply(DiscardAllPacketsNoReplyCompleter::Sync& completer) override;
// fuchsia_media_audio::VolumeControl implementation.
void SetVolume(SetVolumeRequest& request, SetVolumeCompleter::Sync& completer) override;
void SetMute(SetMuteRequest& request, SetMuteCompleter::Sync& completer) override;
// fidl::AsyncEventHandler<fuchsia_media::AudioRenderer> implementation.
void OnMinLeadTimeChanged(
fidl::Event<fuchsia_media::AudioRenderer::OnMinLeadTimeChanged>& event) override;
// Handles errors concerning the connection to |AudioRenderer|.
void on_fidl_error(fidl::UnbindInfo error) override;
private:
template <typename Protocol>
class AsyncEventHandler : public fidl::AsyncEventHandler<Protocol> {
public:
explicit AsyncEventHandler(fit::function<void(fidl::UnbindInfo)> fidl_error_callback)
: fidl_error_callback_(std::move(fidl_error_callback)) {}
void on_fidl_error(fidl::UnbindInfo error) override { fidl_error_callback_(error); }
private:
fit::function<void(fidl::UnbindInfo)> fidl_error_callback_;
};
// Binds to an audio renderer and to |server_end|. If successful, this method calls
// |shared_from_this|, so this |Consumer| must be managed using a |shared_ptr| prior to calling
// this method. If the binding to |AudioRenderer| fails synchronously, |server_end| is dropped and
// |shared_from_this| is not called.
void Bind(fidl::ServerEnd<fuchsia_media::AudioConsumer> server_end);
// Unbinds all server and client connections.
void UnbindAll();
// Completes a pending |StreamSink| connection request if such a request exists.
// |stream_sink_binding_ref_| must be empty when this method is called.
void MaybeCompletePendingCreateStreamSinkRequest();
// Removes payload buffers previously added to the renderer, if any.
void RemoveAddedPayloadBuffers();
// Indicates that the status watched by |WatchStatus| has changed.
void StatusChanged();
// Completes a pending |WatchStatus| request if there is one and if the status is dirty.
void MaybeCompleteWatchStatus();
// Handles errors concerning the connection to |AudioCore|.
void OnAudioCoreFidlError(fidl::UnbindInfo error);
// Handles errors concerning the connection to |GainControl|.
void OnGainControlFidlError(fidl::UnbindInfo error);
async_dispatcher_t* dispatcher_;
std::optional<fidl::ServerBindingRef<fuchsia_media::AudioConsumer>> consumer_binding_ref_;
CreateStreamSinkRequest pending_stream_sink_request_;
std::optional<CreateStreamSinkCompleter::Async> pending_stream_sink_completer_;
std::optional<fidl::ServerBindingRef<fuchsia_media::StreamSink>> stream_sink_binding_ref_;
std::optional<fidl::ServerBindingRef<fuchsia_media_audio::VolumeControl>> volume_binding_ref_;
AsyncEventHandler<fuchsia_media::AudioCore> audio_core_event_handler_;
fidl::Client<fuchsia_media::AudioCore> audio_core_;
fidl::Client<fuchsia_media::AudioRenderer> renderer_;
uint32_t buffers_previously_added_ = 0;
AsyncEventHandler<fuchsia_media_audio::GainControl> gain_control_event_handler_;
fidl::Client<fuchsia_media_audio::GainControl> gain_control_;
std::optional<WatchStatusCompleter::Async> watch_status_completer_;
bool status_dirty_ = true;
media::TimelineFunction timeline_function_;
};
} // namespace media::audio
#endif // SRC_MEDIA_AUDIO_CONSUMER_CONSUMER_H_