Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
pulseaudio_device.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Roc Streaming authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_sndio/target_pulseaudio/roc_sndio/pulseaudio_device.h
10 //! @brief PulseAudio device.
11 
12 #ifndef ROC_SNDIO_PULSEAUDIO_DEVICE_H_
13 #define ROC_SNDIO_PULSEAUDIO_DEVICE_H_
14 
15 #include <pulse/pulseaudio.h>
16 
17 #include "roc_audio/frame.h"
18 #include "roc_core/noncopyable.h"
19 #include "roc_core/rate_limiter.h"
20 #include "roc_core/stddefs.h"
21 #include "roc_core/time.h"
22 #include "roc_packet/units.h"
23 #include "roc_sndio/config.h"
24 #include "roc_sndio/isink.h"
25 #include "roc_sndio/isource.h"
26 
27 namespace roc {
28 namespace sndio {
29 
30 //! PulseAudio device.
31 //! Can be either source or sink depending on constructor parameter.
32 class PulseaudioDevice : public ISink, public ISource, public core::NonCopyable<> {
33 public:
34  //! Initialize.
35  PulseaudioDevice(const Config& config, DeviceType device_type);
37 
38  //! Open output device.
39  bool open(const char* device);
40 
41  //! Cast IDevice to ISink.
42  virtual ISink* to_sink();
43 
44  //! Cast IDevice to ISink.
45  virtual ISource* to_source();
46 
47  //! Get device type.
48  virtual DeviceType type() const;
49 
50  //! Get device state.
51  virtual DeviceState state() const;
52 
53  //! Pause reading.
54  virtual void pause();
55 
56  //! Resume paused reading.
57  virtual bool resume();
58 
59  //! Restart reading from the beginning.
60  virtual bool restart();
61 
62  //! Get sample specification of the sink.
63  virtual audio::SampleSpec sample_spec() const;
64 
65  //! Get latency of the sink.
66  virtual core::nanoseconds_t latency() const;
67 
68  //! Check if the device supports latency reports.
69  virtual bool has_latency() const;
70 
71  //! Check if the device has own clock.
72  virtual bool has_clock() const;
73 
74  //! Adjust source clock to match consumer clock.
76 
77  //! Write audio frame.
78  virtual void write(audio::Frame& frame);
79 
80  //! Read audio frame.
81  virtual bool read(audio::Frame& frame);
82 
83 private:
84  static void context_state_cb_(pa_context* context, void* userdata);
85 
86  static void
87  device_info_cb_(pa_context* context, const void* info, int eol, void* userdata);
88 
89  static void stream_state_cb_(pa_stream* stream, void* userdata);
90  static void stream_request_cb_(pa_stream* stream, size_t length, void* userdata);
91 
92  static void timer_cb_(pa_mainloop_api* mainloop,
93  pa_time_event* timer,
94  const struct timeval* tv,
95  void* userdata);
96 
97  bool request_frame_(audio::Frame& frame);
98 
99  void want_mainloop_() const;
100  bool start_mainloop_();
101  void stop_mainloop_();
102 
103  bool open_();
104  void close_();
105  void set_opened_(bool opened);
106 
107  bool open_context_();
108  void close_context_();
109 
110  bool start_device_info_op_();
111  void cancel_device_info_op_();
112 
113  bool load_device_params_(const pa_sample_spec& device_spec);
114  void init_stream_params_(const pa_sample_spec& device_spec);
115  bool open_stream_();
116  void close_stream_();
117  ssize_t request_stream_(audio::sample_t* data, size_t size);
118  ssize_t write_stream_(const audio::sample_t* data, size_t size);
119  ssize_t read_stream_(audio::sample_t* data, size_t size);
120  ssize_t wait_stream_();
121 
122  bool get_latency_(core::nanoseconds_t& latency) const;
123  void report_latency_();
124 
125  void start_timer_(core::nanoseconds_t timeout);
126  bool stop_timer_();
127 
128  const DeviceType device_type_;
129  const char* device_;
130 
131  audio::SampleSpec sample_spec_;
132 
133  core::nanoseconds_t frame_len_ns_;
134  packet::stream_timestamp_diff_t frame_len_samples_;
135 
136  core::nanoseconds_t target_latency_ns_;
137  packet::stream_timestamp_diff_t target_latency_samples_;
138 
139  core::nanoseconds_t timeout_ns_;
140  packet::stream_timestamp_diff_t timeout_samples_;
141 
142  const audio::sample_t* record_frag_data_;
143  size_t record_frag_size_;
144  bool record_frag_flag_;
145 
146  bool open_done_;
147  bool opened_;
148 
149  pa_threaded_mainloop* mainloop_;
150  pa_context* context_;
151  pa_operation* device_info_op_;
152  pa_stream* stream_;
153  pa_time_event* timer_;
154 
155  core::nanoseconds_t timer_deadline_ns_;
156 
157  pa_sample_spec stream_spec_;
158  pa_buffer_attr buff_attrs_;
159 
160  core::RateLimiter rate_limiter_;
161 };
162 
163 } // namespace sndio
164 } // namespace roc
165 
166 #endif // ROC_SNDIO_PULSEAUDIO_DEVICE_H_
Audio frame.
Definition: frame.h:25
Sample specification. Describes sample rate and channels.
Definition: sample_spec.h:30
Base class for non-copyable objects.
Definition: noncopyable.h:23
Sink interface.
Definition: isink.h:22
Source interface.
Definition: isource.h:23
PulseAudio device. Can be either source or sink depending on constructor parameter.
virtual void pause()
Pause reading.
virtual bool has_clock() const
Check if the device has own clock.
virtual bool restart()
Restart reading from the beginning.
bool open(const char *device)
Open output device.
virtual DeviceState state() const
Get device state.
virtual ISink * to_sink()
Cast IDevice to ISink.
virtual audio::SampleSpec sample_spec() const
Get sample specification of the sink.
PulseaudioDevice(const Config &config, DeviceType device_type)
Initialize.
virtual bool read(audio::Frame &frame)
Read audio frame.
virtual bool has_latency() const
Check if the device supports latency reports.
virtual DeviceType type() const
Get device type.
virtual bool resume()
Resume paused reading.
virtual ISource * to_source()
Cast IDevice to ISink.
virtual void write(audio::Frame &frame)
Write audio frame.
virtual void reclock(core::nanoseconds_t timestamp)
Adjust source clock to match consumer clock.
virtual core::nanoseconds_t latency() const
Get latency of the sink.
Audio frame.
Sink interface.
Source interface.
float sample_t
Raw audio sample.
Definition: sample.h:22
nanoseconds_t timestamp(clock_t clock)
Get current timestamp in nanoseconds.
int64_t nanoseconds_t
Nanoseconds.
Definition: time.h:58
int32_t stream_timestamp_diff_t
Packet stream timestamp delta.
Definition: units.h:41
DeviceType
Device type.
Definition: device_type.h:19
DeviceState
Device state.
Definition: device_state.h:19
Root namespace.
Non-copyable object.
Rate limiter.
Sink and source config.
Commonly used types and functions.
Sink and source config.
Definition: config.h:29
Time definitions.
Various units used in packets.