Line data Source code
1 : /*
2 : * Copyright (C) 2004-2026 Savoir-faire Linux Inc.
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 : #pragma once
18 :
19 : #include "noncopyable.h"
20 : #include "pulselayer.h"
21 :
22 : #include <pulse/pulseaudio.h>
23 : #include <string>
24 :
25 : namespace jami {
26 :
27 : inline AVSampleFormat
28 0 : sampleFormatFromPulse(pa_sample_format_t format)
29 : {
30 0 : switch (format) {
31 0 : case PA_SAMPLE_S16LE:
32 : case PA_SAMPLE_S16BE:
33 0 : return AV_SAMPLE_FMT_S16;
34 0 : case PA_SAMPLE_FLOAT32LE:
35 : case PA_SAMPLE_FLOAT32BE:
36 0 : return AV_SAMPLE_FMT_FLT;
37 0 : case PA_SAMPLE_S32LE:
38 : case PA_SAMPLE_S32BE:
39 0 : return AV_SAMPLE_FMT_S32;
40 0 : default:
41 0 : return AV_SAMPLE_FMT_S16;
42 : }
43 : }
44 :
45 : inline pa_sample_format_t
46 0 : pulseSampleFormatFromAv(AVSampleFormat format)
47 : {
48 0 : switch (format) {
49 0 : case AV_SAMPLE_FMT_S16:
50 0 : return PA_SAMPLE_S16LE;
51 0 : case AV_SAMPLE_FMT_FLT:
52 0 : return PA_SAMPLE_FLOAT32LE;
53 0 : case AV_SAMPLE_FMT_S32:
54 0 : return PA_SAMPLE_S32LE;
55 0 : default:
56 0 : return PA_SAMPLE_S16LE;
57 : }
58 : }
59 :
60 : class AudioStream
61 : {
62 : public:
63 : using OnReady = std::function<void()>;
64 : using OnData = std::function<void(size_t)>;
65 :
66 : /**
67 : * Constructor
68 : *
69 : * @param context pulseaudio's application context.
70 : * @param mainloop pulseaudio's main loop
71 : * @param description
72 : * @param types
73 : * @param audio sampling rate
74 : * @param pointer to pa_source_info or pa_sink_info (depending on type).
75 : * @param true if echo cancelling should be used with this stream
76 : */
77 : AudioStream(pa_context*,
78 : pa_threaded_mainloop*,
79 : const char*,
80 : AudioDeviceType,
81 : unsigned,
82 : pa_sample_format_t,
83 : const PaDeviceInfos&,
84 : bool,
85 : OnReady onReady,
86 : OnData onData);
87 :
88 : ~AudioStream();
89 :
90 : void start();
91 : void stop();
92 :
93 : /**
94 : * Accessor: Get the pulseaudio stream object
95 : * @return pa_stream* The stream
96 : */
97 0 : pa_stream* stream() { return audiostream_; }
98 :
99 0 : const pa_sample_spec* sampleSpec() const { return pa_stream_get_sample_spec(audiostream_); }
100 :
101 : inline size_t sampleSize() const { return pa_sample_size(sampleSpec()); }
102 0 : inline size_t frameSize() const { return pa_frame_size(sampleSpec()); }
103 :
104 : inline uint8_t channels() const { return sampleSpec()->channels; }
105 :
106 0 : inline AudioFormat format() const
107 : {
108 0 : auto s = sampleSpec();
109 0 : return AudioFormat(s->rate, s->channels, sampleFormatFromPulse(s->format));
110 : }
111 :
112 0 : inline std::string getDeviceName() const
113 : {
114 0 : auto res = pa_stream_get_device_name(audiostream_);
115 0 : if (!res)
116 0 : return {};
117 0 : return res;
118 : }
119 :
120 : bool isReady();
121 :
122 0 : void setEchoCancelCb(std::function<void(bool)>&& cb) { echoCancelCb = cb; }
123 :
124 : private:
125 : NON_COPYABLE(AudioStream);
126 :
127 : OnReady onReady_;
128 : OnData onData_;
129 :
130 : /**
131 : * Mandatory asynchronous callback on the audio stream state
132 : */
133 : void stateChanged(pa_stream* s);
134 : void moved(pa_stream* s);
135 : void opEnded(pa_operation* s);
136 :
137 : /**
138 : * The pulse audio object
139 : */
140 : pa_stream* audiostream_;
141 :
142 : /**
143 : * A pointer to the opaque threaded main loop object
144 : */
145 : pa_threaded_mainloop* mainloop_;
146 :
147 : /**
148 : * The type of this audio stream
149 : */
150 : AudioDeviceType audioType_;
151 :
152 : /**
153 : * Function called whenever the stream is moved and we check for an echo canceller
154 : */
155 : std::function<void(bool)> echoCancelCb;
156 :
157 : std::set<pa_operation*> ongoing_ops;
158 : };
159 :
160 : } // namespace jami
|