266 {
268
269 unsigned rate =
desc.sample_rate;
271
272 auto props = pw_properties_new(
273 PW_KEY_MEDIA_TYPE, "Audio",
274 PW_KEY_MEDIA_CATEGORY, "Playback",
275 PW_KEY_MEDIA_ROLE, "Communication",
276 PW_KEY_APP_NAME, "UltraGrid",
277 PW_KEY_APP_ICON_NAME, "ultragrid",
278 PW_KEY_NODE_NAME, "ug play",
280 nullptr);
281
283 pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", s->quant, rate);
284
285 std::byte buffer[1024];
286 auto pod_builder = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
287
288 auto audio_info = SPA_AUDIO_INFO_RAW_INIT(
289 .format = format,
290 .rate = rate,
292 );
293 const spa_pod *
params = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_EnumFormat,
294 &audio_info);
295
297
298
299
300
302
303 s->stream.reset(pw_stream_new(
304 s->pw.pipewire_core.get(),
305 "UltraGrid playback",
306 props));
307
308 pw_stream_add_listener(
309 s->stream.get(),
310 &s->stream_listener.get(),
312 s);
313
314 unsigned ring_size = (s->buf_len_ms *
desc.sample_rate / 1000) *
desc.ch_count *
desc.bps * 2;
316
317 pw_stream_connect(s->stream.get(),
318 PW_DIRECTION_OUTPUT,
319 PW_ID_ANY,
320 static_cast<pw_stream_flags>(
321 PW_STREAM_FLAG_AUTOCONNECT |
322 PW_STREAM_FLAG_MAP_BUFFERS |
323 PW_STREAM_FLAG_RT_PROCESS),
325
326 while(true){
327 pw_thread_loop_wait(s->pw.pipewire_loop.get());
328 const char *
error =
nullptr;
329 auto stream_state = pw_stream_get_state(s->stream.get(), &error);
330 if(stream_state == PW_STREAM_STATE_STREAMING){
331 return true;
332 }
333 if(stream_state == PW_STREAM_STATE_ERROR){
335 return false;
336 }
337 }
338
339 return true;
340}
static const pw_stream_events stream_events
#define LOG_LEVEL_ERROR
general errors
spa_audio_format get_pw_format_from_bps(unsigned bps)
#define STREAM_TARGET_PROPERTY_KEY
struct ring_buffer * ring_buffer_init(int size)