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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include <pipewire/pipewire.h>
#include <spa/param/audio/format-utils.h>
#include "pipewire-binding.h"
#include "pipewire/main-loop.h"
#define SAMPLING_RATE 48000
#define CHANNELS 2
#define VOLUME 0.7
#define NODE_NAME "soundbox"
#define STRIDE sizeof(int16_t) * CHANNELS
struct pw_go_capture {
struct pw_main_loop *loop;
struct pw_stream *stream;
};
static void on_process(void *userdata)
{
struct pw_go_capture *capture = (struct pw_go_capture *)userdata;
struct pw_buffer *pw_buf;
struct spa_buffer *spa_buf;
int n_frames;
int16_t *src;
if ((pw_buf = pw_stream_dequeue_buffer(capture->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(capture->stream, pw_buf);
}
static const struct pw_stream_events stream_events = {
.version = PW_VERSION_STREAM_EVENTS,
.process = on_process,
};
void *pw_go_capture_init(void)
{
pw_init(NULL, NULL);
struct pw_go_capture *capture = malloc(sizeof(struct pw_go_capture));
capture->loop = pw_main_loop_new(NULL);
capture->stream = pw_stream_new_simple(
pw_main_loop_get_loop(capture->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,
capture
);
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(
capture->stream,
PW_DIRECTION_INPUT,
PW_ID_ANY,
PW_STREAM_FLAG_MAP_BUFFERS |
PW_STREAM_FLAG_RT_PROCESS,
params,
sizeof(params) / sizeof(params[0])
);
return (void *)capture;
}
void pw_go_capture_run(void *cdata)
{
struct pw_go_capture *capture = cdata;
pw_main_loop_run(capture->loop);
pw_stream_destroy(capture->stream);
pw_main_loop_destroy(capture->loop);
free(capture);
pw_deinit();
}
void pw_go_capture_deinit(void *cdata)
{
struct pw_go_capture *capture = cdata;
pw_main_loop_quit(capture->loop);
}
|