204 {
206 auto s = std::make_unique<state_pipewire_cap>();
207
208 std::string_view cfg_sv(cfg);
209 while(!cfg_sv.empty()){
210 auto tok =
tokenize(cfg_sv,
':',
'"');
211
214
218 }
else if(
key ==
"target"){
220 }
else if(
key ==
"channels"){
222 }
else if(
key ==
"buffer-len"){
224 }
else if(
key ==
"sample-rate"){
226 }
227 }
228
230
233
234 auto props = pw_properties_new(
235 PW_KEY_MEDIA_TYPE, "Audio",
236 PW_KEY_MEDIA_CATEGORY, "Capture",
237 PW_KEY_MEDIA_ROLE, "Communication",
238 PW_KEY_APP_NAME, "UltraGrid",
239 PW_KEY_APP_ICON_NAME, "ultragrid",
240 PW_KEY_NODE_NAME, "ug capture",
242 nullptr);
243
245
247 pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", s->quant, s->sample_rate);
248
249 std::byte buffer[1024];
250 auto pod_builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
251
252 auto audio_info = SPA_AUDIO_INFO_RAW_INIT(
253 .format = format,
254 .rate = s->sample_rate,
255 .channels = s->ch_count,
256 );
257
258 const spa_pod *
params = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_EnumFormat,
259 &audio_info);
260
261
262
263
265
266 s->stream.reset(pw_stream_new(
267 s->pw.pipewire_core.get(),
268 "UltraGrid capture",
269 props));
270
271 pw_stream_add_listener(
272 s->stream.get(),
273 &s->stream_listener.get(),
275 s.get());
276
277 int ring_size = s->bps * s->ch_count * (s->sample_rate * s->buf_len_ms * 2 / 1000);
279
280 pw_stream_connect(s->stream.get(),
281 PW_DIRECTION_INPUT,
282 PW_ID_ANY,
283 static_cast<pw_stream_flags>(
284 PW_STREAM_FLAG_AUTOCONNECT |
285 PW_STREAM_FLAG_MAP_BUFFERS |
286 PW_STREAM_FLAG_RT_PROCESS),
288
289 while(true){
290 pw_thread_loop_wait(s->pw.pipewire_loop.get());
291 const char *
error =
nullptr;
292 auto stream_state = pw_stream_get_state(s->stream.get(), &error);
293 if(stream_state == PW_STREAM_STATE_STREAMING){
294 break;
295 }
296 if(stream_state == PW_STREAM_STATE_ERROR){
298 return nullptr;
299 }
300 }
301
302 return s.release();
303}
static const pw_stream_events stream_events
static void audio_cap_pw_help()
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
bool initialize_pw_common(pipewire_state_common &s, int fd)
spa_audio_format get_pw_format_from_bps(unsigned bps)
#define STREAM_TARGET_PROPERTY_KEY
struct ring_buffer * ring_buffer_init(int size)
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
bool parse_num(std::string_view sv, T &res, int base=10)