summaryrefslogtreecommitdiff
path: root/soundbox/pipewire-binding.c
blob: bd23ff02f01d7cf80e5325e0c3fd22dec9dd1c18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <pipewire/pipewire.h>
#include <spa/param/audio/format-utils.h>

#include "pipewire-binding.h"


#define SAMPLING_RATE 48000
#define CHANNELS      2
#define VOLUME        0.7
#define NODE_NAME     "soundbox"
#define STRIDE        sizeof(int16_t) * CHANNELS


static void on_process(void *userdata)
{
	struct pw_stream *stream = *(struct pw_stream **)userdata;
	struct pw_buffer *pw_buf;
	struct spa_buffer *spa_buf;
	int n_frames;
	int16_t *src;

	if ((pw_buf = pw_stream_dequeue_buffer(stream)) == NULL) {
		return;
	}

	spa_buf = pw_buf->buffer;
	if ((src = spa_buf->datas[0].data) == NULL) {
		return;
	}

	n_frames = spa_buf->datas[0].chunk->size / STRIDE;
	if (pw_buf->requested) {
		n_frames = SPA_MIN(pw_buf->requested, n_frames);
	}

	size_t len = spa_buf->datas[0].chunk->size;

	goHandleData(src, len);

	spa_buf->datas[0].chunk->offset = 0;
	spa_buf->datas[0].chunk->stride = STRIDE;
	spa_buf->datas[0].chunk->size = n_frames * STRIDE;

	pw_stream_queue_buffer(stream, pw_buf);
}


static const struct pw_stream_events stream_events = {
	.version = PW_VERSION_STREAM_EVENTS,
	.process = on_process,
};


void pw_stdout(void)
{
	pw_init(NULL, NULL);

	struct pw_main_loop *loop = pw_main_loop_new(NULL);

	struct pw_stream *stream = NULL;
	stream = pw_stream_new_simple(
		pw_main_loop_get_loop(loop),
		NODE_NAME,
		pw_properties_new(
			PW_KEY_MEDIA_TYPE, "Audio",
			PW_KEY_CONFIG_NAME, "client-rt.conf",
			PW_KEY_MEDIA_CATEGORY, "Capture",
			PW_KEY_MEDIA_ROLE, "Music",
			NULL
		),
		&stream_events,
		&stream
	);

	uint8_t buffer[1024];
	struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
	const struct spa_pod *params[] = {
		spa_format_audio_raw_build(
			&b,
			SPA_PARAM_EnumFormat,
			&SPA_AUDIO_INFO_RAW_INIT(
				.format = SPA_AUDIO_FORMAT_S16,
				.channels = CHANNELS,
				.rate = SAMPLING_RATE
			)
		)
	};

	pw_stream_connect(
		stream,
		PW_DIRECTION_INPUT,
		PW_ID_ANY,
		PW_STREAM_FLAG_MAP_BUFFERS |
		PW_STREAM_FLAG_RT_PROCESS,
		params,
		sizeof(params) / sizeof(params[0])
	);

	pw_main_loop_run(loop);

	pw_stream_destroy(stream);
	pw_main_loop_destroy(loop);
	pw_deinit();
}