PlaybackStream.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright (c) 2023, Gregory Bertilson <zaggy1024@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/AtomicRefCounted.h>
  8. #include <AK/Function.h>
  9. #include <AK/Queue.h>
  10. #include <AK/Time.h>
  11. #include <LibAudio/SampleFormats.h>
  12. #include <LibCore/Forward.h>
  13. #include <LibThreading/ConditionVariable.h>
  14. #include <LibThreading/MutexProtected.h>
  15. #include <LibThreading/Thread.h>
  16. namespace Audio {
  17. enum class OutputState {
  18. Playing,
  19. Suspended,
  20. };
  21. // This class implements high-level audio playback behavior. It is primarily intended as an abstract cross-platform
  22. // interface to be used by Ladybird (and its dependent libraries) for playback.
  23. //
  24. // The interface is designed to be simple and robust. All control functions can be called safely from any thread.
  25. // Timing information provided by the class should allow audio timestamps to be tracked with the best accuracy possible.
  26. class PlaybackStream : public AtomicRefCounted<PlaybackStream> {
  27. public:
  28. using AudioDataRequestCallback = Function<ReadonlyBytes(Bytes buffer, PcmSampleFormat format, size_t sample_count)>;
  29. // Creates a new audio Output class.
  30. //
  31. // The initial_output_state parameter determines whether it will begin playback immediately.
  32. //
  33. // The AudioDataRequestCallback will be called when the Output needs more audio data to fill
  34. // its buffers and continue playback.
  35. static ErrorOr<NonnullRefPtr<PlaybackStream>> create(OutputState initial_output_state, u32 sample_rate, u8 channels, u32 target_latency_ms, AudioDataRequestCallback&&);
  36. virtual ~PlaybackStream() = default;
  37. // Sets the callback function that will be fired whenever the server consumes more data than is made available
  38. // by the data request callback. It will fire when either the data request runs too long, or the data request
  39. // returns no data. If all the input data has been exhausted and this event fires, that means that playback
  40. // has ended.
  41. virtual void set_underrun_callback(Function<void()>) = 0;
  42. // Resume playback from the suspended state, requesting new data for audio buffers as soon as possible.
  43. //
  44. // The value provided to the promise resolution will match the `total_time_played()` at the exact moment that
  45. // the stream was resumed.
  46. virtual NonnullRefPtr<Core::ThreadedPromise<Duration>> resume() = 0;
  47. // Completes playback of any buffered audio data and then suspends playback and buffering.
  48. virtual NonnullRefPtr<Core::ThreadedPromise<void>> drain_buffer_and_suspend() = 0;
  49. // Drops any buffered audio data and then suspends playback and buffering. This can used be to stop playback
  50. // as soon as possible instead of waiting for remaining audio to play.
  51. virtual NonnullRefPtr<Core::ThreadedPromise<void>> discard_buffer_and_suspend() = 0;
  52. // Returns a accurate monotonically-increasing time duration that is based on the number of samples that have
  53. // been played by the output device. The value is interpolated and takes into account latency to the speakers
  54. // whenever possible.
  55. //
  56. // This function should be able to run from any thread safely.
  57. virtual ErrorOr<Duration> total_time_played() = 0;
  58. virtual NonnullRefPtr<Core::ThreadedPromise<void>> set_volume(double volume) = 0;
  59. };
  60. }